先写一个例子——生成n以内的Fibonacci数:
def fib(n):
a,b=0,1
while b<n:
print b,
a,b=b,a+b
def指出了接下来的部分是一个函数。Python和C语言类似,并不区分过程(无返回值)和函数(有返回值)。像上面那样严格的说就是一个过程(Procedure)。
对于一个项目而言,在不同的模块的代码中插入一段简洁明了的说明文字是很有必要的。Python支持类似Java-Doc的语法。例如:
def fib(n):
"""Print a Fibonacci series up to n."""
a,b=0,1
while b<n:
print b,
a,b=b,a+b
将说明文字放在一对“”“(三个又引号)之间,一些文档生成工具就会将这些文字提取出来,生成HTML或是LaTeX等文档。写这些文字费不了多少时间,养成这种习惯绝对是大有好处的。
函数的调用也非常简单,对于上面的而言,只需直接用fib(100),就会产生相应的输出:
虽然Python的函数可以不显式地写出return语句,实际上这种函数也会返回一个特殊的值None。例如有一个什么都不干的函数:
def fun():
pass
可以通过在解释器中用print来显示一下它的值:
def fib2(n):
"""Print a Finonacci series up to n."""
a,b=0,1
result=[]
while b<n:
result.append(b)
a,b=b,a+b
return result
append是List类的一个方法,即向一个List后添加元素。这个函数的效果如下:
Python函数支持默认参数。你可以定义一个两个参数的函数,但在调用的时候可以只告诉其中一个参数或是一个都不告诉——只要你在定义的时候指定了参数的默认值。这很像是从C++中学来的。
def ask_ok(prompt,retries=4,complaint='Yes or no, please!'):
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
这样就有了多种调用方式:
i = 5
def f(arg=i):
print arg
i = 6
f()
发现输出的是5而不是6,因为后来的i改变根本不会对函数里的arg造成影响。
要注意的是,函数的默认参数部分只会被计算一次。这样如果默认参数是某种复合类型(List,String,Class),可能会产生一种”积累效应“:
def f(a,L=[]):
L.append(a)
return L
如果调用三次:
def f(a,L=None):
if L is None:
L=[]
L.append(a)
return L
带关键字的参数
关键字可以理解为函数头部参数的名字。通过在调用函数的时候指定关键字,可以不按照参数定义的顺序来传递参数的值。
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, "!"
带关键字调用:
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 = keywords.keys()
keys.sort()
for kw in keys: print kw, ':', keywords[kw]
可以这样调用:
类似地,可以使用**操作符来传递一个字典,对应于带关键字传递参数的方式。
Lambda函数
Python从函数语言中学来了这一功能。Lambda函数是一种匿名函数,功能有些像函数的模板,通过它可能方便地生成其他函数。感觉Lambda函数更加需要领悟,只里仅仅记几个例子:





对于一个项目而言,在不同的模块的代码中插入一段简洁明了的说明文字是很有必要的。Python支持类似Java-Doc的语法。例如:






函数的调用也非常简单,对于上面的而言,只需直接用fib(100),就会产生相应的输出:
1 1 2 3 5 8 13 21 34 55 89
函数本身也可以被引用。对于已经定义好的fib来说,如果有一句:f=fib,就意味着f引用了fib这个函数。现在这两个名字所指的就是同一个东西。于是就可以这样使用:>>>f(100)
输出结果和上面的是一样的。可以比照着C语言中的”函数指针“来理解一下。虽然Python的函数可以不显式地写出return语句,实际上这种函数也会返回一个特殊的值None。例如有一个什么都不干的函数:


>>>print fun()
None
现在可以将上面的fib函数改造一下,让它不再直接产生输出,而是产生一个Fibonacci数列的List:None








>>>print fib2(100)
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
默认参数[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
Python函数支持默认参数。你可以定义一个两个参数的函数,但在调用的时候可以只告诉其中一个参数或是一个都不告诉——只要你在定义的时候指定了参数的默认值。这很像是从C++中学来的。








>>>ask_ok('Do you really want to quit?')
>>>ask_ok('Do you really want to quit?',2)
>>>ask_ok('Do you really want to quilt?',3,'What do you want to do?')
参数的默认值是在定义的时在函数的入口处确定下来的。这可以通过一个实验来说明:>>>ask_ok('Do you really want to quit?',2)
>>>ask_ok('Do you really want to quilt?',3,'What do you want to do?')





要注意的是,函数的默认参数部分只会被计算一次。这样如果默认参数是某种复合类型(List,String,Class),可能会产生一种”积累效应“:



>>> print f(1)
[1]
>>> print f(2)
[1, 2]
>>> print f(3)
[1, 2, 3]
要避免这种情况,就需要在定义的参数列表中显式地将L的默认值指定为None:
[1]
>>> print f(2)
[1, 2]
>>> print f(3)
[1, 2, 3]





关键字可以理解为函数头部参数的名字。通过在调用函数的时候指定关键字,可以不按照参数定义的顺序来传递参数的值。





parrot(1000)
parrot(action = 'VOOOOOM', voltage = 1000000)
parrot('a thousand', state = 'pushing up the daisies')
parrot('a million', 'bereft of life', 'jump')
下面的几种调用方式是错的:parrot(action = 'VOOOOOM', voltage = 1000000)
parrot('a thousand', state = 'pushing up the daisies')
parrot('a million', 'bereft of life', 'jump')
parrot() # 缺少指定参数
parrot(voltage=5.0, 'dead') # 没有指出关键字
parrot(110, voltage=220) # 传递重复参数
parrot(actor='John Cleese') # 不存在的关键字
更为灵活的是,可以通过在函数定义时用*name或**name的方式代表不确定的参数或带有关键字的参数(Dictionary)。这个用例子说明会容易理解一下:
parrot(voltage=5.0, 'dead') # 没有指出关键字
parrot(110, voltage=220) # 传递重复参数
parrot(actor='John Cleese') # 不存在的关键字








cheeseshop('Limburger', "It's very runny, sir.","It's really very, VERY runny, sir.",client='John Cleese', shopkeeper='Michael Palin',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
传递多个参数时还可以通过List来进行。List中的元素会被分离开,称为Unpack,这是Python解释器在幕后完成的。例如range函数可以指定两个参数,可以把这两个参数构成一个List,再将这个List传入:-- 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
>>> args = [3, 6]
>>> range(*args) # call with arguments unpacked from a list
[3, 4, 5] >>> range(*args) # call with arguments unpacked from a list
类似地,可以使用**操作符来传递一个字典,对应于带关键字传递参数的方式。
>>> 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, "!"
...
>>> d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"}
>>> parrot(**d)
-- This parrot wouldn't VOOM if you put four million volts through it. E's bleedin' demised !
用心领悟一下。... print "-- This parrot wouldn't", action,
... print "if you put", voltage, "volts through it.",
... print "E's", state, "!"
...
>>> d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"}
>>> parrot(**d)
-- This parrot wouldn't VOOM if you put four million volts through it. E's bleedin' demised !
Lambda函数
Python从函数语言中学来了这一功能。Lambda函数是一种匿名函数,功能有些像函数的模板,通过它可能方便地生成其他函数。感觉Lambda函数更加需要领悟,只里仅仅记几个例子:
>>> def make_incrementor(n):
... return lambda x: x + n
...
>>> f = make_incrementor(42)
>>> f(0)
42
>>> f(1)
43
... return lambda x: x + n
...
>>> f = make_incrementor(42)
>>> f(0)
42
>>> f(1)
43