python函数
python函数
- 什么是函数
- 函数语法
- 调用函数
- 函数参数
- 形参与实参
- 传参
- 指定参数传参
- 参数默认值
- 可变参数
- 参数解包
- 参数设定是顺序
- 函数返回值
- 返回多个值
- 高阶函数
- 函数作为参数
- 函数作为返回值
- 闭包
- 装饰器
- 匿名函数
什么是函数
函数就是代码抽象的方式
函数语法
# 使用def关键字
def fun(x): # fun函数名,x函数参数,形参
# 代码块
return x # x 返回值,在没有return是返回None
# 在调用函数时传入的参数位实参
fun(10) # 10 为实参
参数
- 位置参数:普通参数在函数参数位置的最前面
- 默认参数:一般在位置参数后,可变参数前
- 可变参数:能够传入任意多个参数,在函数内部以tuple类型存在,形参名-->*args 约定
- 关键字参数:传入的参数必须带参数名,参数值与参数名组成字典dict的形式,在函数参数位置的最后,形参名-->**kwargs 约定
- 命名关键字参数:传入参数时需要携带形参名,命名关键字参数在星号 (*) 后面 如 def fun(a, b, *, c, d)这里c,d 位命名关键字参数,当存在可变参数时不需要加星号(*)
def fun(a,b,*args,c,d,**kwargs):
print(a,b,args,c,d,kwargs)
fun(1,2,3,4,5,c=6,d=7,e=8,f=9) # -->1,2,(3,4,5),6,7,{'e':8,'f':9}
-
传参
- 位置传参:一般参数在调用函数时按位置传入参数
- 指定参数传参:通过指定形参名进行参数传递,此时参数不在按位置传入,参数传递时也可以不用按定义时的位置排列(一般不推荐)
def fun1(a,b,c): print('a=',a,'b=',b,'c=',c) fun1(c=1,a=2,b=3) #-->a= 2,b= 1,c= 3 参数名传参 fun1(1,2,3) #-->a= 1,b= 2,c= 3 位置传参
-
参数默认值
- 在定义函数时,将形参赋予默认值,该值一般位常用值,在调用函数一般不用再传入参数
- 在定义函数时赋予默认值的参数在位置参数后,在默认参数后面又可变参数时,传入多个参数时会被重新赋值,
def fun3(a,b,c=9): print(a,b,c) fun3(1,2) # 不传入第三个参数-->1,2,9 fun3(1,2,4) # 传入第三个参数-->1,2,4
-
参数传递时的解包
- 当传入参数是列表元组或字典时
- 时用*或**来解包参数
li = [1,2,3,4,5] di = {'a':10,'b':20,'c':30,'d':40} def fun4(*args,**kwargs): print(args,kwargs) fun4(*li,**di)
-
参数传递顺序
- 位置参数 默认参数 可变参数 命名关键字参数 关键字参数
-
当实参中有可变对象时且有默认值时
- 列表
# 第二个参数位列表,且赋予了默认值 def fun5(x,li=[]): li.append(x) return li r1 = fun5(1) print(r1) # -->[1] r2 = fun5(2) print(r2) # -->[1, 2] r3 = fun5(3) print(r3) #-->[1, 2, 3] # 每一次调用函数都会改变li的值,函数的调用会影响到之后函数的使用 # 我们需要在调用函数时给予判断,清空参数的值, def fun55(x,li=[]): if li: li = [] li.append(x) return li # 或则在传入参数时对默认参数进行传参 fun5(1,[])
函数的返回值
- 不写return时:返回值为None
- 返回一个值:就是该值
- 返回多个值:此时会打包成一个元组,
# 在返回多个值时我们可能需要对返回值进行解包
# 元组的解包,
# 确定元组元素个数,确定需要的值
tup = (1,2,3,4)
# 解包
a,b,c,d = tup #-->a=1,b=2,c=3,d=4
a,b,*c=tup #-->a=1,b=2,c=(3,4)
a,*b,c=tup # -->a=1,b=(2,3),c=4
*a,b,c=tup #-->a=(1,2),b=3,c=4
a,*b=tup #-->a=1,b=(2,3,4)
高阶函数
函数作为参数和返回值
- 在python中函数既可以作为参数也可以作为返回值
- 函数作为参数,将函数作为参数传入另一个函数,
def add_y(x,y):
return x+y
def my_fun(x, y, f):
my_sum = f(x,y)
return my_sum
my_fun(1,3,add_y)
- 函数作为返回值
- 在调用外层函数时,需要用参数接受返回的函数,此时返回函数并没用被调用,我们需要用接受的参数来调用该返回函数
def my_fun1(*args):
def my_fun2():
r = 0
for i in args:
r+=i
return r
return my_fun2
rr = my_fun1(1,2) #-->my_fun2
ru = rr() #--> 3
-
闭包
-
内部函数使用外部函数的变量名所指向的变量值
-
但内部函数使用该变量名重新赋值时,会重新在内部函数开辟内存空间指向新的值,避免使用赋值运算
# 外部函数中的变量i为可变,该参数可以在内部函数中进行改变, def w(): i = 0 def f(): i = 1 return ('f->i',id(i)) print('w->i',id(i)) return f a = w() # w->i 140722978922864 print(a()) # ('f->i', 140722978922896)
-
当该变量赋值的是可变参数是,内部函数时用该变量的方法进行运算时能够改变该变量的值,不要使用赋值运算
# 外部函数中的变量i为可变,该参数可以在内部函数中进行改变, def w(): i = [] # 变量i执行列表 def f(n): i.append(n) # 在内部函数中对变量i进行添加元素 return i,id(i) print(id(i)) return f a = w() # 2903060140424 print(a(1)) # ([1], 2903060140424) print(a(2)) # ([1, 2], 2903060140424)
-
返回函数不要引用任何循环变量,或者后续会发生变化的变量
# 内部函数使用外部函数的变量时,外部函数的变量值发生变化时 def w(): fs = [] for i in range(1, 4): def f(): return i*i fs.append(f) # 将函数添加到列表中 return fs # 返回的是函数组成的列表 a,b,c = w() print(a(),b(),c()) # 结果是 9, 9, 9 # 此时列表中函数所用的参数i的变量值全是3,不是1,2,3 # 处理 def w(): fs = [] def f(i): def f1(): return i*i return f1 # 返回函数 for i in range(1, 4): fs.append(f(i)) # 此时调用f()函数得到结果,绑定参数i return fs # f返回函数列表 a,b,c = w() print(a(),b(),c()) # -->1, 4, 9
-
-
通过闭包可以创建一个只有当前函数函数能够访问的变量,将一些私有数据藏到闭包中
# 一次线性函数,将a,b参数放在外部函数中 def w(): a,b = 3,2 # 将内部函数使用的变量a,b放在外部函数中, def f(x): return a*x+b # 这是 return f s = w() s(1)
函数变量的作用域
-
函数内部的参数只能在函数内部使用,在函数外部无法取得该变量
-
函数内部可以使用函数外部的变量,但是在函数内部使用该变量名赋值时则是函数内部重新开辟的内存空间,与外部的变量无关
i = 1 def f(): i = 0 print(id(i)) print(id(i)) # -->140722973155728 f() # -->140722973155696 print(id(i)) # -->40722973155728
-
当要在函数内部改变外部的变量是需要使用global关键字声明,
i = 1 def f(): global i i = 0 print(i,id(i)) print(i,id(i)) # --> 1 140722973155728 f() # -->0 140722973155696 print(i,id(i)) # -->0 140722973155696
-
查看函数内部的变量是用locals()
-
查看全局的变量使用globals()
内置的高阶函数
-
map(fun, iter) -->fun(x), 将iter中的每个参数传递给fun函数并返回一个值
map(fun, iter) ---> for i in iter: fun(i)
-
reduce(fun, seq)-->fun(x,y),seq序列,将序列中的前两个值传递给函数,该函数返回一个值,该返回值作为参数再次传递给该函数,并按顺序去序列的下一个值作为fun函数的参数,以此进行计算
from functools import reduce reduce(fun,[x1,x2,x3,x4,x5,...]) ---> fun(fun(fun(fun(x1,x2),x3),x4),x5)
-
filter(fun,seq) -->过滤序列,fun函数是过滤规则,seq是序列,在fun接受seq传入的参数时,符合函数fun规则时保留,不符合时删除,filter函数返回一个迭代器
def fun(n): if n % 2 == 0: return n li = [1, 2, 3, 4, 5, 6, 7] s = filter(fun, li) print(list(s)) # -->[2, 4, 6]
-
sorted(seq, key=fun,reverse=False) -->接受一个可排序的序列,通过key指定的函数处理后排序,reverse是否反转
li = [1,-2,3,4,-5,6,-8] sorted(li, key=abs)
匿名函数
-
在不定义函数名的时候使用函数,使用lambda 关键字
-
语法 lambda 变量:语句,返回值为语句执行结果
# 求平方 f = lambda x:x*x
生成器
-
一边循环一边计算的机制,称为生成器:generator
-
节省内存,惰性计算
-
在列表生成式中将[ ]改成( ),
L = [i*i for i in range(i)] g = (i*i for i in range(i))
-
在函数中包含yield语句,在执行函数时,执行到yield语句时返回该值,此时函数会执行yield的下一条语句,知道循环结束或遇到return语句
def fun(): i, j = 1, 1 while True: yield j i,j = j,i+j a = fun() for i in range(10): print(next(a)) # --> 1,2,3,5,8,13,21,34,55,89