函数
一、函数参数传值
形参:函数在定义的时候给定的参数
实参:函数在运行时赋给的参数:
1 def func(i):#i为定义时的参数,为形参 2 pass 3 func(name)#name为运行时的参数,为实参,实参与形参的名字可以相同
传值方式:
位置传值:按照定义时的顺序,用实参给形参赋值
1 def func(x,y,z): 2 print("x->",x) 3 print("y->",y) 4 print("z->",z) 5 func(1,2,3) 6 7 #按顺序将值一一赋给形参 8 x-> 1 9 y-> 2 10 z-> 3
关键字传值:形参1 = xxx,形参2 = xxx
1 def func(x,y,z): 2 print("x->",x) 3 print("y->",y) 4 print("z->",z) 5 func(x = 1,z = 2,y = 3)#将x赋值为1,y赋值为3,z赋值为2 6 #关键字传参,没有位置对应关系 7 8 9 x-> 1 10 y-> 3 11 z-> 2
混合传值:要注意混合传值时,关键字传值必须放到位置传值的右边
1 def func(x,y,z): 2 print("x->",x) 3 print("y->",y) 4 print("z->",z) 5 func(1,2,z = 3) 6 ‘‘‘关键字传值,必须在最右边,并且不能对已经有位置传参的形参进行传值‘‘‘ 7 8 9 10 x-> 1 11 y-> 2 12 z-> 3
万能的传值方式(可变长参数传值方式):
*args:传值接受后组成元组(位置处传值)
**kwargs:传值后组成字典(用于关键字传值)
使用参数时遍历即可
def func(*args,**kwargs): print(args) print(kwargs) func(1,2,3,x = 4,y = 5) (1, 2, 3) {‘x‘: 4, ‘y‘: 5}
二、函数的作用域问题
有下面一段简单代码:
1 name = "sunqi" 2 def foo(): 3 name = "tony" 4 print(name) 5 foo()
打印输出为“tony”,为什么是tony而不是sunqi?
直接的说是因为python在寻找变量时,是找离它最近的。就是先从函数本地内部开始找,然后去函数外面找,最后再去python内置函数中找。
例如这个输出打印,就是因为先找到了“tony”然后就用他来做为name输出。
那么就有全局变量,和本地变量的区别了
定义在程序最外边的就是全局变量,比如name =“sunqi”
定义在函数内部的变量就是局部变量也叫本地变量,比如name = “tony”
当全局变量与局部变量重名时,本地本地变量会在内部作用域中替换全局变量。从下面的例子就可以看出来,内部变量并没有修改全局变量的值
1 name = "sunqi" 2 def foo(): 3 name = "tony" 4 print(name) 5 foo() 6 print(name) 7 8 9 10 11 tony 12 sunqi
当我们要使用并修改全局变量时就需要声明global 属性
1 name = "sunqi" 2 def foo(): 3 global name 4 name = "tony" 5 print(name) 6 foo() 7 print(name) 8 9 10 tony
11 tony
可以看出全局变量已经被修改
我们来看一下下边的例子
1 name = [1,2,3,4] 2 dic = {"name":"sunqi","age":18} 3 def foo(): 4 name = [23,44,5,] 5 print(name) 6 foo() 7 print(name) 8 9 10 [23, 44, 5] 11 [1, 2, 3, 4]
和上边的例子一样,foo函数并没有对局部变量产生任何影响
1 name = [1,2,3,4] 2 dic = {"name":"sunqi","age":18} 3 def foo(): 4 name.append(7) 5 dic["age"] = 10 6 print(name) 7 print(dic.items()) 8 foo() 9 print(name) 10 print(dic.items()) 11 12 13 [1, 2, 3, 4, 7] 14 dict_items([(‘name‘, ‘sunqi‘), (‘age‘, 10)]) 15 [1, 2, 3, 4, 7] 16 dict_items([(‘name‘, ‘sunqi‘), (‘age‘, 10)])
例子中列表和字典局均为全局变量,foo函数引用的也是全局变量,但是为声明global。却修改了列表和字典。
原因是,既然没有声明global属性,就不能对全局变量进行赋值,但是对于可修改的全局变量来说,可以修改他们的内部元素。
比如字典,列表。
1 def foo(): 2 count = 0 3 def boo(): 4 nonlocal count 5 count+=1 6 print(count) 7 boo() 8 print(count) 9 foo() 10 11 12 13 1 14 1
nonlocal用于声明非全局变量的外部变量,当不需要对上层变量进行修改时不必声明nonlocal
上边的例子没有nonlocal的话会报错:计数前未声明
1 def foo(): 2 count = 0 3 def boo(): 4 5 print(count) 6 boo() 7 print(count) 8 foo() 9 10 11 0 12 0
三、高阶函数
函数就是变量,可以被当做返回值,也可以作为参数传给另一个函数
1 def foo(): 2 count = 0 3 def boo(): 4 print(count) 5 print(boo) 6 return boo 7 f = foo() 8 print(f) 9 10 11 <function foo.<locals>.boo at 0x0000020248CC4AE8> 12 <function foo.<locals>.boo at 0x0000020248CC4AE8>
函数被return返回的是函数的地址上面的例子可以通过f()直接运行就相当于运行boo()
函数也可以作为参数传递给另一个函数:
1 #函数作为参数传递 2 num = [1,2,3,4] 3 def add(i,sum = 0): 4 """ 5 sum加法初始值,默认值为零 6 :param sum: 7 :param i: 8 :return: 9 """ 10 sum = sum +i 11 return sum 12 def test(func,num): 13 res = 0 14 for i in num: 15 res = res + func(i) 16 print(res) 17 test(add,num)#add函数作为参数传递给了test函数 18 19 20 10
四、lambda表达式,map,reduce,filter
lambda表达式的意义就是对函数的简洁表示
lambda函数也叫匿名函数
冒号前是参数,冒号后是返回值
lambda函数经常与map,reduce,filter一起使用
map():对一个可迭代对象进行遍历,并交由lambda处理,返回一个与传入的对象长度相同,顺序相同的object对象
reduce():对一个可迭代对象的元素进行遍历并运算,返回一个计算后的值
filter():传入一个可迭代对象,通过设置条件筛选出满足 条件的元素,组成新的object对象,可以用列表转换后遍历输出
1 func = lambda x:x+1 2 print(func(10)) 3 func = lambda x,y,z:(x+1,y+1,z+1) 4 print(func(1,2,3)) 5 func = lambda x:x+"DE" 6 print(func("ABS")) 7 8 9 11 10 (2, 3, 4) 11 ABSDE
1 from functools import reduce 2 3 foo = [2, 18, 9, 22, 17, 24, 8, 12, 27] 4 print(list(map(lambda x: x + 1, foo))) 5 print(reduce(lambda x, y: x + y, foo)) 6 print(list(filter(lambda x: x > 10, foo))) 7 8 9 10 [3, 19, 10, 23, 18, 25, 9, 13, 28] 11 139 12 [18, 22, 17, 24, 12, 27]
明天补充内置函数。