函数(参数,作用域,返回函数,匿名函数,偏函数)
函数参数:
python 中的函数参数类型有 必须参数,关键字参数,默认参数,可变参数,组合参数
必须参数
即形参和实参按照顺序一一对应
关键字参数
函数调用使用关键字确定传入的参数值,允许实参和形参的顺序不一致,因为 python 解释器能够用参数名匹配参数值
代码:
1 #!/usr/bin/python3 2 3 def personinfo(age, name): 4 print('年龄:', age) 5 print('名称:', name) 6 return 7 8 personinfo(21, '小萌') 9 print('-------------------') 10 personinfo(name = '小萌', age = 21) 11 print('-------------------') 12 personinfo(age = 21, name = '小萌')
默认参数
和 c++ 中一致
若要更改某一个默认参数值,又不想传入其它默认参数,且该默认参数的位置不是第一个,则可以通过参数名更改想要更改的默认参数值
代码:
1 #!/usr/bin/python3 2 3 def gel(a = 1, b = 2, c = 3): 4 print(a, b, c) 5 return 6 7 gel() 8 gel(10) 9 gel(b = 10) 10 11 ''' 12 输出: 13 1 2 3 14 10 2 3 15 1 10 3 16 '''
可变参数
加了 * 的变量名会存放所有未命名的变量参数。如果变量参数再函数调用时没有指定参数,就是一个空元组。
代码:
1 #!/usr/bin/python3 2 3 def personinfo(arg, *var): 4 print(arg) 5 for indx in var: 6 print(indx, end = ' ') 7 print() 8 return 9 10 personinfo(2, 'fd', 'aa')
用 ** 处理可变的关键字参数:
1 other = {'city' : 'beijing', 'hoby' : 'coding'} 2 3 def personinfo(name, number, **kw): 4 print('名称:', name, '学号: ', number, '其它:', kw) 5 6 personinfo('gel', 3366, city = other['city'], hoby = other['hoby']) 7 personinfo('gel', 3366, **other)#等效于上一条语句
组合参数
在编程中上述四种参数可以组合使用。注意定义参数的顺序是必须参数、默认参数、可变参数和关键字参数
代码:
1 #!/usr/bin/python3 2 3 def exp(p1, p2, df = 0, *vart, **kw): 4 print(p1, p2, df, vart, kw) 5 6 exp(1, 2) 7 exp(1, 2, c = 3) 8 exp(1, 2, 3, 'a', 'b') 9 exp(1, 2, 3, 'abc', x = 9) 10 11 # 输出: 12 # 1 2 0 () {} 13 # 1 2 0 () {'c': 3} 14 # 1 2 3 ('a', 'b') {} 15 # 1 2 3 ('abc',) {'x': 9}
变量作用域:
局部变量
和c++中一致,局部变量只能在定义它的函数中使用
全局变量
在函数体内可以直接使用全局变量,但在函数体中更改变量的值并不会更改全局变量的值。这是因为调用函数时创建了新的命名空间,它作用于该函数代码块。
代码:
1 #!/usr/bin/python3 2 3 x = 50 4 def func(x): 5 print('全局x=', x) 6 x = 2 7 print('局部x=', x) 8 9 func(x) 10 print('全局x=', x) 11 12 输出: 13 全局x= 50 14 局部x= 2 15 全局x= 50
注意:函数中使用某个变量时,如果该变量名既有全局变量又有局部变量,默认使用局部变量的值
要在函数中修改全局变量的值需要使用 global 关键字
代码:
1 #!/usr/bin/python3 2 3 x = 50 4 def func(): 5 global x 6 x = 2 7 print('局部x=', x) 8 9 func() 10 print('全局x=', x) 11 12 # 输出: 13 # 局部x= 2 14 # 全局x= 2
注意:不能对形参使用 global 关键字
global 声明必须在函数中对应参数使用之前
返回函数:
代码:
1 #!/usr/bin/python3 2 3 def sum_late(*args): 4 def calc_sum(): 5 ax = 0 6 for n in args: 7 ax += n 8 return ax 9 return calc_sum 10 11 print(sum_late(1, 2, 3, 4))#输出对应的函数地址 12 calc_sum = sum_late(1, 2, 3, 4) 13 print(calc_sum()) 14 15 #每次调用都会返回一个新的函数,即使传入相同的参数也是如此 16 f1 = sum_late(1, 2, 3) 17 f2 = sum_late(1, 2, 3) 18 print('if f1 == f2?', f1 == f2) 19 20 # 输出: 21 # <function sum_late.<locals>.calc_sum at 0x05804108> 22 # 10 23 # if f1 == f2? False
注意:每次调用都会返回一个新的函数,即使传入相同的参数也是如此
闭包
如果在一个内部函数里对外部函数(不是在全局作用域)的变量进行引用,内部函数就被认为是闭包
注意:返回闭包时,返回函数不要引用任何循环变量或后继会发生变化的变量,否则很容出错:
1 #!/usr/bin/python3 2 3 def count(): 4 fs = [] 5 for i in range(1, 4): 6 def f(): 7 return i * i 8 fs.append(f) 9 return fs 10 11 f1, f2, f3 = count() 12 print(f1()) 13 print(f2()) 14 print(f3()) 15 16 #输出并不是我们预期的1, 4, 9 17 # 输出: 18 # 9 19 # 9 20 # 9
显然,上面出错的原因是加入 fs 后的函数并没有立即离开 for 循环(i 的作用域),因此会收到 i 的后续影响。
要修改使其正确的话我们可以再套一个函数隔开 i 的作用域即可:
1 #!/usr/bin/python3 2 3 def count(): 4 def f(x): 5 def g(): 6 return x * x 7 return g 8 9 fs = [] 10 for i in range(1, 4): 11 fs.append(f(i)) 12 return fs 13 14 f1, f2, f3 = count() 15 print(f1()) 16 print(f2()) 17 print(f3()) 18 19 # 输出: 20 # 1 21 # 4 22 # 9
匿名函数:
lambda 函数拥有自己的命名空间,不能访问自有参数列表之外或全局命名空间的参数
lambda 函数的语法只包含一个语句
python 中 lambda 不能有 return 语句,但其实 : 后面部分即为返回值,:之前部分可以看作是参数,且可以只用默认值
两个数求和:
1 #!/usr/bin/python3 2 3 sum = lambda x, y : x + y 4 print(sum(1, 2)) 5 print(sum(2, 3)) 6 # 输出: 7 # 3 8 # 5
和 filter 一起使用:
1 def func(x): 2 return x > 3 3 4 l1 = [1, 2, 3, 4, 5] 5 6 f_list = filter(func, l1) 7 print([item for item in f_list]) 8 9 print([item for item in filter(lambda x : x > 3, l1)]) 10 11 # 输出: 12 # [4, 5] 13 # [4, 5]
python3 开始 filter 返回迭代器(之前是返回列表)
如果需要将迭代器改成列表可以:
filter_list = [item for item in a_file_object]
偏函数:
类似于 c++ bind 的一个东西:http://www.cnblogs.com/geloutingyu/p/8335230.html
1 #!/usr/bin/python3 2 3 from functools import partial 4 5 def mod(n, m): 6 return n % m 7 8 mod_by_100 = partial(mod, 100) 9 10 print(mod(100, 7)) 11 print(mod_by_100(7)) 12 # 输出: 13 # 2 14 # 2