函数
参考 :
#########################################################
http://www.w3cschool.cc/python/python-functions.html
http://developer.51cto.com/art/200809/88052.htm
http://www.pythondoc.com/pythontutorial27/controlflow.html#tut-functions
http://see.xidian.edu.cn/cpp/html/1829.html
http://www.cnblogs.com/linyawen/archive/2011/10/01/2196957.html
#########################################################
什么是函数?
通俗地说,函数就是完成特定功能的一个语句组,这组语句可以作为一个单位使用,并且给它取一个名字,这样,我们就可以通过函数名在程序的不同地方多次执行(这通常叫做函数调用),却不需要在所有地方都重复编写这些语句。
为什么使用函数?
主要是出于两个方面的考虑:
1. 为了降低编程的难度,通常将一个复杂的大问题分解成一系列更简单的小问题,然后将小问题继续划分成更小的问题,当问题细化为足够简单时,我们就可以分而治之。这时,我们可以使用函数来处理特定的问题,各个小问题解决了,大问题也就迎刃而解了。
2. 代码重用。我们定义的函数可以在一个程序的多个位置使用,也可以用于多个程序。此外,我们还可以把函数放到一个模块中供其他程序员使用,同时,我们也可以使用其他程序员定义的函数。这就避免了重复劳动,提供了工作效率。
我的理解:函数就是通过一次性的劳动,编写好一个能完成特定功能的语句块,这样下次再需要这个功能的时候,只要调用这个语句块就好了,不需要再次写一遍这个语句块,提升效率!
定义函数
自定义函数规则:
- 函数代码块以def关键词开头,后接函数标识符名称和圆括号()。
- 任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数。
- 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
- 函数内容以冒号起始,并且缩进。
- Return[expression]结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。
def 函数名(参数列表): 函数体
- 函数名可以是任何有效的Python标识符;
- 参数列表是调用该函数时传递给它的值,可以由多个、一个或零个参数组成,当有多个参数时各个参数由逗号分隔;
- 圆括号是必不可少的,即使没有参数也不能没有它;
- 函数体是函数每次被调用时执行的代码,可以由一个语句或多个语句组成,函数体一定要注意缩进;
- 不能忘记圆括号后面的冒号,这会导致语法错误
>>> def fib(n): # write Fibonacci series up to n ... """Print a Fibonacci series up to n.""" #强烈建议使用的文档字符,用于说明该函数 ... a, b = 0, 1 ... while a < n: ... print a, ... a, b = b, a+b ... >>> # Now call the function we just defined: ... fib(2000) 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
函数参数
参考:http://www.cnblogs.com/tqsummer/archive/2011/01/25/1944416.html
默认参数(缺省参数):调用函数时,缺省参数的值如果没有传入,则被认为是默认值。
>>> def taxMe(cost,rate=0.0825): ... return cost+ (cost * rate) ... >>> taxMe(100) 108.25 >>> >>> taxMe(100, 0.05) 105.0
但记住:所有必需的参数都要在默认参数之前。如果没有按正确的顺序给出参数,就会产生一个语法错误。
>>> def taxMe2(rate=0.0825, cost): ... return cost * (1.0 + rate) ... SyntaxError: non-default argument follows default argument
重要警告: 默认值只被赋值一次。这使得当默认值是可变对象时会有所不同,比如列表、字典或者大多数类的实例。例如,下面的函数在后续调用过程中会累积(前面)传给它的参数:
def f(a, L=[]): L.append(a) return L print f(1) print f(2) print f(3) 这将会打印: [1] [1, 2] [1, 2, 3]
如果你不想在随后的调用中共享默认值,可以像这样写函数:
def f(a, L=None): if L is None: L = [] L.append(a) return L
关键字参数:我们使用名称(关键字)而不是位置来指定函数的参数。
调用函数的时候,传递的参数都是根据位置来跟函数定义里的参数表匹配的(普通的参数称为位置参数),比如funcB(100, 99)和funcB(99, 100)的执行结果是不一样的。有的时候,如果参数太多顺序不太好记,因此使用参数名提供参数的方式来解决。即在调用函数时使用形参名=实参名的方式来传递参数,如funcB(a=100, b=99)和funcB(b=99, a=100),其结果都是一样的。
关键字参数特点:
一是,使用函数容易,因为我们不需要担心参数的顺序。
二是,如果其他参数有默认参数值,我们可以只给我们想赋值的参数赋值。
例如:
def func(a, b=5, c=10): print(‘a为‘, a, ‘和b为‘, b, ‘和c为‘, c) func(3, 7) func(25, c=24) func(c=50, a=100) 输出: a为3 和b为7 和c为10 a为25 和b为5 和c为24 a为100 和b为5 和c为50
它是如何工作的:
名为func的函数中有一个参数没有默认参数值,后面两个参数有默认参数值。
第一次使用func(3, 7),参数a得到值3,参数b得到值7,参数c得到默认值10。
第二次使用func(25, c=24),参数a按照参数的位置得到值25,然后参数c按照参数名,也就是参数关键字,得到值24,变量b得到默认值5。
第三次使用func(c=50, a=100),我们为所有给定的值使用了参数关键字。注意,我们为参数c指定值是在参数a之前,尽管在函数定义中a在c前。
我的理解:关于默认参数和关键字参数
默认参数是定义函数时候的一个形参,用在定义函数的时候。
关键字参数是调用函数时的一个实参,用在调用函数的时候。
可变参数:
带一个星号 * 的参数:
在不确定有多少参数的情况下,就需要带*的参数来接受多余的参数,例如:
def funcD(a, b, *c): print a print b print "length of c is: %d " % len(c) print c #调用funcD(1, 2, 3, 4, 5, 6)结果是 1 2 length of c is: 4 (3, 4, 5, 6)
我们看到,前面两个参数被a、b接受了,剩下的4个参数,全部被c接受了,c在这里是一个tuple。我们在调用funcD的时候,至少要传递2个参数,2个以上的参数,都放到c里了,如果只有两个参数,那么c就是一个empty tuple。
带两个星号 ** 的参数:
如果一个函数定义中的最后一个形参有 ** (双星号)前缀,所有正常形参之外的其他的关键字参数都将被放置在一个字典中传递给函数,比如:
def funcF(a, **b): print a for x in b: print x + ": " + str(b[x]) #调用funcF(100, c=‘你好‘, b=200),执行结果 100 c: 你好 b: 200
大家可以看到,b是一个dict对象实例,它接受了关键字参数b和c。
我的理解:关于可变参数
我们在调用实参的时候有时候会带多个参数,多余的非关键字参数则被一个星号的形参接收,成为一个元组,关键字参数,因为有一个等号,所以有两个值,则需要被两个星号的形参接收,成为一个字典。
匿名函数lambda
参考:http://www.cnblogs.com/linyawen/archive/2011/10/01/2196957.html
一个完整的lambda“语句”代表了一个表达式,这个表达式的定义体必须和声明放在同一行。我们现在来演示下匿名函数的语法:
lambda [arg1[, arg2, ... argN]]: expression
lambda语句中,冒号前是参数,可以有多个,用逗号隔开,冒号右边的返回值。
例如:
def f(x): return x**2 print f(4) #Python中使用lambda的话,写成这样: g = lambda x : x**2 print g(4)
默认参数也能够在lambda参数中使用,就像在def中使用一样。
>>>x = (lambda a = "fee", b = "fie", c = "foe": a + b +c) >>>x("wee") ‘weefiefoe‘
Lambda特点:
1. 使用Python写一些执行脚本时,使用lambda可以省去定义函数的过程,让代码更加精简。
2. 对于一些抽象的,不会别的地方再复用的函数,有时候给函数起个名字也是个难题,使用lambda不需要考虑命名的问题。
3. 使用lambda在某些时候让代码更容易理解。
内建函数
filter()
filter(bool_func,seq):此函数的功能相当于过滤器。调用一个布尔函数bool_func来迭代遍历每个seq中的元素;返回一个使bool_seq返回值为true的元素的序列。
>>> filter(lambda x : x%2 == 0,[1,2,3,4,5]) [2, 4]
map()
map(func,seq1[,seq2...]):将函数func作用于给定序列的每个元素,并用一个列表来提供返回值;如果func为None,func表现为身份函数,返回一个含有每个序列中元素集合的n个元组的列表。
>>> map(lambda x : None,[1,2,3,4]) [None, None, None, None] >>> map(lambda x : x * 2,[1,2,3,4]) [2, 4, 6, 8] >>> map(lambda x : x * 2,[1,2,3,4,[5,6,7]]) [2, 4, 6, 8, [5, 6, 7, 5, 6, 7]] >>> map(lambda x,y: x + y, [1,3,5],[2,4,6]) [3, 7, 11] >>> map(lambda x, y: (x+y, x-y), [1,3,5], [2,4,6]) [(3, -1), (7, -1), (11, -1)] >>> map(lambda x : None,[1,2,3,4, [5,6,7]]) [None, None, None, None, None]
reduce
reduce(func,seq[,init]):func为二元函数,将func作用于seq序列的元素,每次携带一对(先前的结果以及下一个序列的元素),连续的将现有的结果和下一个值作用在获得的随后的结果上,最后减少我们的序列为一个单一的返回值:如果初始值init给定,第一个比较会是init和第一个序列元素而不是序列的头两个元素。
>>> reduce(lambda x,y : x + y,[1,2,3,4]) 10 >>> reduce(lambda x,y : x + y,[1,2,3,4],10) 20 >>> reduce(lambda x,y: x*y,[1,2,3,4]) 24
全局变量与局部变量
局部变量
你在函数定义中声明的变量,他们与在函数外使用的其它同名变量没有任何关系,即变量名称对函数来说是局部的。这叫变量的范围。所有变量都有它们被声明的块的范围,从名称定义的点开始。
局部变量定义举例:
x = 50 def func(x): print(‘x等于‘, x) x = 2 print(‘局部变量x改变为‘, x) func(x) print(‘x一直是‘, x) 输出: x等于50 局部变量x改变为2 x一直是50
它是如何工作的:
第一次,我们使用函数体中第一行打印变量x的值,Python使用在主块中,函数定义上声明的实参。
接下来,我们给x赋值为2,变量为x对我们的函数来说是局部变量,因此在函数中当我们改变x的值时,在主块中定义的变量x不受影响。
最后调用的print函数,显示在主块中定义的变量x,因此证实,它不受在前面调用函数的局部变量的影响。
如果将全局变量的名字声明在一个函数体内的时候,全局变量的名字能被局部变量给覆盖掉。
使用全局声明
如果你想给在顶层的程序(即未在任何类型的范围如函数或类之中)定义的变量赋值,那么你必须告诉Python,变量不是局部的,而是全局的。我们使用global语句,没有global语句赋值给一个在函数外定义的变量是不可能的。
您可以使用这些在函数外定义的变量的值(假设在函数内没有同名的变量)。然而,这并不鼓励,应该避免,因为这使程序的读者不清楚变量是在哪里定义的,使用 global 语句就非常清楚,变量定义在一个最外的块中。
使用全局变量的例子:
x = 50 def func(): global x print(‘x的值是‘, x) x = 2 print(‘全局变量x改为‘, x) func() print(‘x的值是‘, x) #输出: x的值是50 全局变量to改为2 x的值是2
它是如何工作的:
global语句用来声明x是全局变量,当我们在函数内给x赋值时,它的改变映射到我们在主块中使用的x的值。
用同样的global语句可以指定多个全局变量,比如: global x, y, z