引言
- 将一段代码集中到一块,起一个名字,下次可以根据这个名字再次使用这个代码块。
- 作用:
调用方法
funName(arg1, arg2, arg3…) # 形参和实参一一对应 funName(arg2=v2, arg3=v3, arg1=v1) # 指明形参的名称,不用严格按照形参顺序
<a name="ed38d877"></a>## 不定长参数```python# 1. 利用元组的拆包装包def mySum(*args):print(type(args)) # <class 'tuple'>print(args) # (1, 2, 3, 4)print(*args) # 拆包操作 1, 2, 3, 4for v in args:# todo ..."""装包,将传入的参数装入一个元组中,args就成了一个元组对象拆包,将一个元组中的元素拆分出来,*args就成了参数序列"""# 2. 利用字典的键值对def myInfo(**args):print(type(args)) # <class 'dict'># todo ...myInfo(name="MetaTian", age=21)
默认参数
"""调用某些函数时,可以省略某些参数,采用定义函数时指定的值若不省略,则以调用时传入的值为准"""def sorted(iterable, reverse=False):passnew_list = sorted([1, 3, 2, 5])new_list = sorted([1, 3, 2, 5], True)
返回值
- 返回语句标志着函数的结束,一个函数最好只有一处返回语句
如果想返回多个数据,可以把数据包装成一个集合,整体返回(列表,元组,字典…)
def funName():data = {}# todo...return data
偏函数
对于一个默认值较多的函数,有时我们需要重复用到其中的部分默认值,每次指定默认值比较麻烦。
- 可以将其中的默认值先赋值好,然后封装成一个新的函数,这就是偏函数。 ```python import functools numStr = “100010” res = int(numStr, base=2) print(res) # 34
int2 = functools.partial(int, base=2) # 重新封装,构成偏函数 print(int2(numStr)) # 34
<a name="be10e9dd"></a># 高阶函数- 一个函数的参数可以是另外一个函数```pythondef calculate(a, b, cal_fun):print(cal_fun(a, b))def sum(a, b):return a + bdef sub(a, b):return a - bcalculate(2, 3, sum) # 5calculate(2, 3, sub) # -1
匿名函数
lambda表达式- 没有名字的函数 ```python “”” lambda arguments: expression 冒号前面是参数,后面是要返回的表达式 “”” res = (lambda x, y : x + y)(1, 2) print(res) # 3
fun = lambda x, y : x + y print(fun(2, 3)) # 5
更多的是配合 map(), reduce()等函数进行使用
<a name="0edb4c85"></a># 闭包- 在函数嵌套定义的前提下- 内层函数引用了外层函数的变量- 外层函数把内层函数当做返回值```pythondef line_config(content, length):define line():print(content * length)return lineline1 = line_config("-", 5);line2 = line_config("*", 6)line1(); # -----line2(); # ******
作用域问题:内层函数要修改外层函数的变量,要使用nonlocal进行声明,否则变量属于内层函数。
def test():num = 10def test2():nonlocal num # test中的 num被修改num = 666return test2
当内层函数使用外层的变化量时,注意值的情况 ```python def test(): funs = [] for i in range(1, 4):
def test2():print(i)funs.append(test2)
return funs
“””
函数在运行时才会去确定变量的值
运行时,索引 i 的值因定义时迭代完成,不再发生变化
细节请参考迭代器部分
“””
myFuns = test()
myFuns0 # 3
myFuns1 # 3
myFuns2 # 3
<a name="e97bc1e5"></a># 装饰器- 在调用目标函数之前,对这个函数对象进行**装饰**(增加一些其他功能)。- 函数的**名字不能改变**。- 函数体内部的**代码不能发生改变**。<a name="568d18bd"></a>## 使用案例```pythondef check(func):def inner():print("登录验证...")func()return inner # 返回装饰后的函数# 在 fss()和 ftp()执行之前,都会送入 check()进行包装@check # 只要python解释器执行到了这行代码就会进行装饰执行def fss():print("发说说")# 上面三行等价于 fss = check(fss)@checkdef ftp():print("发图片")# 上面三行等价于 ftp = check(ftp)# 主业务逻辑如下:flag = 1if flag == 1:fss() # 登录验证...else: # 发说说ftp()
多个装饰器的调用顺序
def one(func):print('----1----')def two():print('----2----')func()return twodef a(func):print('----a----')def b():print('----b----')func()return b@one@adef demo():print('----3----')demo()# 运行结果 //从下到上装饰,从上到下执行,分析略----a--------1--------2--------b--------3----
对带有参数的函数进行装饰
def zsq(funcs):def inner(*args, **kwargs): # 装包print("-" * 5)func(*args, **kwargs) # 拆包return inner@zsqdef fun1(n1, n2, n3):print(n1, n2, n3)@zsqdef fun2(n):print(n)fun1(1, 2, n3=8) # 1 2 8fun2(3) # 3
对带有返回值的函数进行装饰
def zsq(funcs):def inner(*args, **kwargs): # 装包print("-" * 5)res = func(*args, **kwargs) # 拆包return res@zsqdef fun1(n1, n2, n3):return sum(n1, n2, n3)fun1(1, 2, 3)
带有参数的装饰器
def getzsq(char):def zsq (func):def inner():print(char * 5)func()return innerreturn zsq@getzsq("*")def f(): # *****print("666") # 666@getzsq("-")def f1(): # -----print("666") # 666
生成器
- 是一个特殊的迭代器
- 特性:
- 惰性计算数据,节省内存
- 能够记录状态,通过
next()函数,访问下一个状态
- 使用方式
```python
生成器表达式,不是元组推导,没有元组推导式
l = (i for i in range(1, 10000000) if i % 2) print(type(l)) print(next(l)) # 1 print(next(l)) # 3 for i in l: print(i) # 循环打印出所有满足条件的值
生成器函数
def test(): for i in range(1, 9): yield i g = test() print(next(g)) # 1 print(next(g)) # 2 ```
