使用关键字def定义函数
In [19]: def fib(n): ....: a, b = 0, 1 ....: while a < n: ....: print a, ....: a, b = b, a+b ....: In [20]: fib(2000) 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
函数可以直接传递给变量,相当于重新命名函数名:
In [21]: fib Out[21]: <function __main__.fib> In [22]: f = fib In [23]: f(100) 0 1 1 2 3 5 8 13 21 34 55 89
函数一般都有返回值,如果没有返回值,那么默认返回值是none
In [24]: def fib2(n): ....: result = [] ....: a,b=0,1 ....: while a<n: ....: result.append(a) ....: a,b=b,a+b ....: return result ....: In [25]: fib(2000) 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 In [26]: fib2(100) Out[26]: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
三种定义函数的参数值
1、给变量设置默认的参数值
In [1]: def ask_ok(prompt, retries=4, complaint='Yes or no, ple ...: while True: ...: ok=raw_input(prompt) ...: if ok in ('y','ye','yes'): ...: return True ...: if ok in ('n','no','nop','nope'): ...: return False ...: retries = retries - 1 ...: if retries < 0: ...: raise IOError('refusenik user') ...: print complaint
调用该函数有三种方式:
(1)只给第一个必要的变量赋值:
In [2]: ask_ok('Do you really want to quit?')
(2)除了第一个必要参数值,第二个可选参数值也赋值,相当于覆盖了原来的默认值
In [5]: ask_ok('OK to overwrite the file?',2)
(3)给所有参数都赋值
In [6]: ask_ok('OK to overwrite the file?',2,'Come on,only yes or not')
注意一般来说,参数值的默认值只会赋值一次,比如以下这个方式:
In [7]: i=5 In [8]: def f(arg=i): ...: print arg ...: In [9]: i=6 In [10]: f() 5
但是如果参数的默认赋值是可变的列表,字典或者实例,那就会有些不同的地方,以下例子说明这个问题:
In [11]: def f(a,L=[]): ....: L.append(a) ....: return L ....: In [12]: print f(1) [1] In [13]: print f(2) [1, 2] In [14]: print f(3) [1, 2, 3]
如果不希望列表或者字典在多个函数调用中被累积调用,可以使用以下方式:
In [15]: def f(a,L=None): ....: if L is None: ....: L=[] ....: L.append(a) ....: return L
2、关键词参数
函数在调用的时候可以使用关键词直接赋值,通过以下函数例子说明:
In [16]: def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'): ....: print "-- This parrot wouldn't", action, ....: print "if you put", voltage, "volts through it." ....: print "-- Lovely plumage, the", type ....: print "-- It's", state, "!"
parrot这个函数接受一个必要参数值(voltage)和三个可选参数值,函数可以通过以下几种方式调用:
parrot(1000) # 1 positional argument parrot(voltage=1000) # 1 keyword argument parrot(voltage=1000000, action='VOOOOOM') # 2 keyword arguments parrot(action='VOOOOOM', voltage=1000000) # 2 keyword arguments parrot('a million', 'bereft of life', 'jump') # 3 positional arguments parrot('a thousand', state='pushing up the daisies') # 1 positional, 1 keyword
以下几种方式不能用于调用函数:
parrot() # required argument missing parrot(voltage=5.0, 'dead') # non-keyword argument after a keyword argument parrot(110, voltage=220) # duplicate value for the same argument parrot(actor='John Cleese') # unknown keyword argument
可以使用形参(formal parameter)来定义函数,*name接受一个元组,**name接受一个字典,*name形参必须在**name之前如以下例子:
In [10]: def cheeseshop(kind, *arguments, **keywords): ....: print "-- Do you have any", kind, "?" ....: print "-- I'm sorry, we're all out of", kind ....: for arg in arguments: ....: print arg ....: print "-" * 40 ....: keys = sorted(keywords.keys()) ....: for kw in keys: ....: print kw, ":", keywords[kw]
In [11]: cheeseshop("Limburger", "It's very runny, sir.", ....: "It's really very, VERY runny, sir.", ....: shopkeeper='Michael Palin', ....: client="John Cleese", ....: sketch="Cheese Shop Sketch") -- Do you have any Limburger ? -- I'm sorry, we're all out of Limburger It's very runny, sir. It's really very, VERY runny, sir. ---------------------------------------- client : John Cleese shopkeeper : Michael Palin sketch : Cheese Shop Sketch
3、可变参数列表(Arbitaty Argument List)
In [12]: def write_multiple_items(file, separator, *args): ....: file.write(separator.join(args))
4、分拆参数列表(Unpacking Argument List)
当传递给函数调用的参数是列表或元组,那就需要分开位置变量,例如,系统内置的range()函数期望接收的是开始和结束的变量值,如果传递给它的是没有分开的参数,那么调用该函数时可以在参数前加“*”运算符来分拆列表或元组参数。
In [1]: range(3, 6) 正常调用 Out[1]: [3, 4, 5] In [2]: args = [3, 6] 列表 In [3]: range(*args) Out[3]: [3, 4, 5]
同样的方式,字典也可以使用"**"运算符来传递关键词参数:
In [4]: def parrot(voltage, state='a stiff', action='voom'): ...: print "-- This parrot wouldn't", action, ...: print "if you put", voltage, "volts through it.", ...: print "E's", state, "!" ...: In [5]: d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"} In [6]: parrot(**d) -- This parrot wouldn't VOOM if you put four million volts through it. E's bleedin' demised !
5、Lamba表达式
使用lamba关键词可以构造较小的匿名函数
In [7]: def make_incrementor(n): ...: return lambda x: x + n ...: In [8]: f = make_incrementor(42) In [9]: f(0) Out[9]: 42 In [10]: f(1) Out[10]: 43
构造一个函数作为参数传递给其他函数调用:
In [14]: pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')] In [15]: pairs.sort(key=lambda pair: pair[1]) In [16]: pairs Out[16]: [(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]
6、文档字符串(Documnet strings)
In [17]: def my_function(): ....: """Do nothing, but document it. ....: No, really, it doesn't do anything. ....: """ ....: pass ....: In [18]: print my_function.__doc__ Do nothing, but document it. No, really, it doesn't do anything.
7、编程风格PEP8
推荐 PEP 8,PEP8的主要要点:
(1)使用四个空格的缩进,不要使用tab;
(2)将行包裹起来,这样使它不要超过79个字符;
(3)使用空行来分隔函数和类,在函数里面分隔不同块;
(4)使用文档字符串(Docstring)
(5)使用空格隔开运算符,在逗号后面使用空格,但是不要直接在括弧构造中使用:
(6)函数和类命名要一致性,使用CamClass这样的格式来命名类,使用
lower_case_with_underscores这样的格式来命名函数和方法,要使用self来表示第一个函数方法的参数
(7)使用标准编码格式