第一章 函数介绍
函数的好处:
1.减少代码重复性 (冗余)
2.代码可读性高
3.将功能进行封装(造工具)
def 关键字 ---定义函数
func 函数名 ---和变量规则一样
- ()
- 声明语句结束
def my_len():
函数体
第二章 函数调用
my_len() 函数名 + ()
def my_len():
a = "123dsb"
count = 0
for i in a:
count += 1
print(count)
my_len() # 函数的调用
第三章 函数的返回值
def num():
print(1)
print(2)
return "123","321" #返回的是元组
print(3)
num()
print(num())
return 的内容返回给函数的调用
遇到return,此函数结束,return下面的代码将不会在执行
return 返回多个内容的时候是元组,调用者可以直接使用解构获取多个变量
return不能终止循环,只能终止函数
return没写返回值,或者干脆就没写return,返回的结果都是是None
第四章 函数的参数
参数,也就是函数括号里的内容 函数在调用的时候指定一个具体的变量的值 就是参数
def 函数名(参数):
函数体
形参: 函数定义()里的参数
1. 可用位置参数 默认参数 混合参数
实参: 函数调用()里的就是实参
1. 位置参数 关键字参数 混合参数
传参:将实参传递给形参的过程
位置传参时:::::::::实参要与形参一一对应
1.位置参数
def yue(chat): # chat 形参
print("拿出手机")
print("打开"+chat)
print("找个漂亮的妹子")
print("约不约")
yue("陌陌") # "陌陌"在这里就是实参
2.默认参数
姓名,性别,年龄
def userinfo(name,age,sex="男"): # 位置参数 > 默认参数
print(name,sex,age)
count = 5
while count:
name = input("name:")
sex = input("sex(男性直接回车!):")
age = input("age:")
if sex == "女":
userinfo(name,age,sex)
else:
userinfo(name, age)
count -= 1
3.关键字参数
def func(a,c,b=1): # a,c位置参数 ,b=1 是默认参数
print(a,b,c)
func(a=1,b=5,c=2) # a=1,b=5,c=2 是关键字参数
def func(a,b,c):
print(a,b,c)
func(1,2,c=5) # 混合参数
第五章 三元运算符,枚举
lst =[1,2,3]
def func(b):
return "da" if len(b)>5 else "xiaoyu"
print(fun(lst))
变量 = 条件成立的结果 条件判断 条件不成立 #####只适用于2个参数
def dunc():
lst =[11,22,33]
dic={}
for k,v in enumerate(lst,10): 从第十个开始 默认为0
dic[k]=v
return dic
第六章 形参的动态函数
1.*args(动态位置参数)
def func(a,b,*args): #可以接收多个位置参数 可以解说多个 *在定义函数的时候叫做聚合
print(a,b,args) #返回的是元组
#print(a,b,*args) * 打散
func(1,2,3,4,5)
######位置参数>动态位置参数>默认参数
def func (*args,a=1,b=2)
2.**kwargs(动态关键字参数)
def func(a,b,**kwargs):
print(a,b,kwargs) #返回字典
#print(a,b,*kwargs) #拿到的是key
func(1,2,c=1,d=2)
#1 2 {'c': 1, 'd': 2}
#1 2 c d
3.参数优先级
######位置参数>动态位置参数>默认参数>动态关键字参数
def func(a,b,*args,c=1,d=2,**kwargs):
print(a,b,args,c,d,kwargs,)
func(1,2,5,4,6,c=3,d=4,e="123",f="22")
#1 2 (5, 4, 6) 3 4 {'e': '123', 'f': '22'}
4.万能参数
#万能传参,可以接受所有的
def func(*args,**kwargs):
print(args,kwargs,)
func(1,2,5,4,6,a=1,b=2,c=3)
#(1, 2, 5, 4, 6) {'a': 1, 'b': 2, 'c': 3}
字典和列表打散传入
func(*[1,2,3,4],*[12,2,2,2,2,2],**{1:2,2:3})
5.形参的第四章传参方式,仅限关键字参数
#
def fun(a,*args,sex="男",c,**kwargs):
print(a)
print(args)
print(sex)
print(c)
print(kwargs)
fun(1,3,2,c=4,name="zbb")
第七章 函数的注释
def func1(user,password):
"""
密码加密
:param user: 用户名 str
:param password: 密码 str
:return: 加密的密码 MD5
"""
print(user,password)
print(func1.__doc__)
print(func1.__name__)
第八章 名称空间
1.名称空间分类:
- 全局空间--> 我们直接在py文件中, 函数外声明的变量都属于全局命名空间
- 局部空间--> 在函数中声明的变量会放在局部命名空间
- 内置空间--> 存放python解释器为我们提供的名字, list, tuple, str, int这些都是内置命名空间
2.加载顺序
内置 > 全局空间 >局部空间
取值顺序
局部空间 > 全局空间 >内置
都没有就报错
3,作用域
作用域就是作用范围, 按照生效范围来看分为 全局作用域 和 局部作用域
- 全局作用域: 全局命名空间 + 内置命名空间
- 局部作用域: 局部命名空间
第九章 函数的嵌套
不管在什么位置,只要是函数名+() 就是在调用此函数
函数调用执行后,函数体中开辟的空间就自动销毁了
def func():
print(1)
def f1():
print(2)
return f1()
print(func())
1.函数互相引用
def func():
a = 1
foo()
print(a)
def foo():
b = 2
print(b)
func()
2.global
作用1:在局部作用域中可以更改全局作用域的变量。
a=1
def func():
global a # 声明修改全局变量的值
a += 1
func()
print(a)
global在局部作用域也可以声明一个全局变量。
def func():
global a
a = 3
func()
print(a)
3.nonlocal
nonlocal是python3x新加的功能,与global用法差不多,就是在局部作用域如果想对父级作用域的变量进行改变时,需要用到nonlocal,当然这个用的不是很多,了解即可。
def add_b():
b = 42
def do_global():
b = 10
print(b)
def dd_nonlocal():
nonlocal b
b = b + 20
print(b)
dd_nonlocal()
print(b)
do_global()
print(b)
add_b()
nonlocal :在外层的函数中,修改局部空间的变量值.完全不涉及全局变量,
只修改离它最近的一层,最近的一层没有变量继续向上找,直到找到最外层函数
第十章函数名的使用
函数名是一个变量, 但它是一个特殊的变量, 与括号配合可以执行函数的变量
1.函数名的内存地址
def func():
print("呵呵")
print(func)
结果: <function func at 0x1101e4ea0>
2.函数名可以直接赋值给其他变量
def func():
print("呵呵")
print(func)
a = func # 把函数当成一个值赋值给另一个变量
a() # 函数调用 func()
3.函数名可以当做容器类的元素
def func1():
print("呵呵")
def func2():
print("呵呵")
def func3():
print("呵呵")
def func4():
print("呵呵")
lst = [func1, func2, func3]
for i in lst:
i()
4.函数名可以当做函数的参数
def func():
print("吃了么")
def func2(fn):
print("我是func2")
fn() # 执行传递过来的fn
print("我是func2")
func2(func) # 把函数func当成参数传递给func2的参数fn
5.函数名可以当做函数的返回值
def func_1():
print("这里是函数1")
def func_2():
print("这里是函数2")
print("这里是函数1")
return func_2
fn = func_1()
# 执行函数1. 函数1返回的是函数2, 这时fn指向的就是上面函数2
fn() # 执行func_2函数
6.函数形参可变类型的坑
def extendList(val,list=[]):
list.append(val)
return list
print('list1=%s'% extendList(10))
print('list2=%s'% extendList(123,[]))
print('list3=%s'% extendList('a'))
#一步一步的执行,结果可想
#list1=[10]
#list2=[123]
#list3=[10, 'a']
def extendList(val,list=[]):
list.append(val)
return list
list1 = extendList(10) #执行了
list2 = extendList(123,[])#执行了
list3 = extendList('a')#执行了
print('list1=%s'%list1)
print('list2=%s'%list2)
print('list3=%s'%list3)
#是先执行完所有的 才打印
list1=[10, 'a']
list2=[123]
list3=[10, 'a']
第十一章 f-string字符串格式化
f-strings 是python3.6开始加入标准库的格式化输出新的写法,这个格式化输出比之前的%s 或者 format 效率高并且更加简化
1.举例用法
s= f"我是{'张'}" #填充字符串
print(s)
# s1 =f"你好{s}" #填充变量
# print(s1)
# s1 = f"{12+13}" #填充计算公式
# print(s1)
# a=10
# b=20
# s1 =f"{a if a>b else b}" #填充表达式
# print(s1)
print(f"{{73}}") # {73}
print(f"{{{73}}}") # {73}
print(f"{{{{73}}}}") # {{73}}
m = 21
# ! , : { } ;这些标点不能出现在{} 这里面。
# print(f'{;12}') # 报错
# 所以使用lambda 表达式会出现一些问题。
# 解决方式:可将lambda嵌套在圆括号里面解决此问题。
x = 5
print(f'{(lambda x: x*2) (x)}') # 10
第十二章 迭代器
1.什么叫迭代?
迭代就是一个重复的过程,每次重复都是基于上一次的结果而来
我们接触到的可迭代对象有
str list tuple dic set range 文件句柄等,int,bool这些不能称为可迭代对象
2.查看对象内部方法
查看是否有str.iter__
s1 = 'alex'
print(dir(s1))
#['__add__', '__class__', ' '__iter__', '__le_,.......]
print('__iter__' in dir(s1)) # True
3.优缺点
优点:
1. 使用灵活
- 可以直观的查看里面的数据
缺点:
1.占用内存。
2.可迭代对象不能迭代取值(除去索引,key以外)
2.什么叫迭代器
在python中,内部含有__Iter__方法并且含有__next__方法的对象就是迭代器
f = open('file',encoding='utf-8', mode='w')
print('__iter__' in dir("123")) # True
print('__next__' in dir("123") # False
1.可迭代对象如何转化成迭代器:
l1 = [1, 2, 3, 4, 5, 6]
obj = l1.__iter__()
# <list_iterator object at 0x000002057FE1A3C8>
# 或
obj = iter(l1)
print(obj)
# <list_iterator object at 0x102cc67f0>
2.迭代器取值
可迭代对象是不可以一直迭代取值的(除去用索引,切片以及Key),但是转化成迭代器就可以了,迭代器是利用__next__()进行取值:
l1 = [1, 2, 3,]
obj = l1.__iter__() # 或者 iter(l1)
# print(obj) # <list_iterator object at 0x000002057FE1A3C8>
ret = obj.__next__()
print(ret) #1
ret = obj.__next__()
print(ret) #2
3.while模拟for的内部循环机制:
#这是假的
s = "121234"
count = len(s)
new_s=iter(s)
while count:
print(next(new_s))
count -=1
#异常捕获,不会报错
s = "1234"
new_s=iter(s)
while True:
try:
print(next(new_s))
except StopIteration:
break
#不写下面的
except Exception:
print("是万能的")
break
4.优点缺点
优点:
- 节省内存。 惰性机制
- 迭代器在内存中相当于只占一个数据的空间:因为每次取值都上一条数据会在内存释放,加载当前的此条数据。
缺点:
- 一次性的
- 不能直观的查看里面的数据。
- 取值时不走回头路,只能一直向下取值。
l1 = [1, 2, 3, 4, 5, 6]
obj = iter(l1)
for i in range(2):
print(next(obj)) # 1,2
for i in range(2):
print(next(obj)) #3,4
5.总结
应用:当你的数据量过大,大到足以撑爆你的内存或者你以节省内存为首选因素时,将数据集设置为迭代器是一个不错的选择。
第十二章 递归
- 自己调用自己
- 有明确的终止条件
满足以上条件才是递归
递:
一直执行到结束条件
归
def func():
print(123)
func()
func()
第十三章 生成器
**生成器的本质就是迭代器 **
迭代器都是(内置的)
Python给你提供的已经写好的工具或者通过数据转化得来的,(比如文件句柄,iter([1,2,3])。
生成器是需要我们自己用python代码构建的工具。
1.生成器的创建方式
在python中有三种方式来创建生成器:
- 通过生成器函数
- 通过生成器推导式
- python内置函数或者模块提供(其实1,3两种本质上差不多,都是通过函数的形式生成,只不过1是自己写的生成器函数,3是python提供的生成器函数而已
2.生成器函数
def func():
print(11)
return 22
ret = func()
print(ret)
# 运行结果:
11
22
将函数中的return换成yield,这样func就不是函数了,而是一个生成器函数
def func():
print(11)
yield 22
print(func()) #产生生成器
#yield 也是返回
def func():
print(11)
yield 22
a=func() #只是产生了生成器
print(a.__next__()) #这才是调用
#11
# 22
yield会记录执行位置
一个 yield 对应一个__next__()
next超过yield数量,就会报错,与迭代器一样。
def func():
# print(11)
yield 22
yield 44
a=func()
print(a.__next__())
print(a.__next__())
def zz():
if 3>2:
yield 11
if 2<3:
yield 22
yield 33
a=zz()
print(a.__next__())
print(a.__next__())
print(a.__next__())
3.yield与return的区别:
return 可以写多个但是只执行一次,占用内存。
yield可以写多个执行多次,非常的节省内存,而且还可以保留上次的位置。
yield 可以将循环 临时暂停
4.yield from
在把可迭代对象中的每一个数据作为生成器的结果挨个返回
# 对比yield 与 yield from
def func():
lst = ['卫龙','老冰棍','北冰洋','牛羊配']
yield lst
g = func()
print(g)
print(next(g)) # 只是返回一个列表
def func():
lst = ['卫龙','老冰棍','北冰洋','牛羊配']
yield from lst
g = func()
print(g)
# 他会将这个可迭代对象(列表)的每个元素当成迭代器的每个结果进行返回。
print(next(g))
print(next(g))
print(next(g))
print(next(g))
'''
yield from ['卫龙','老冰棍','北冰洋','牛羊配']
等同于:
yield '卫龙'
yield '老冰棍'
yield '北冰洋'
yield '牛羊配'
小坑
返回的结果是将第一个列表的元素全部返回后,在返回第二个列表
def func():
lst1 = ['卫龙', '老冰棍', '北冰洋', '牛羊配']
lst2 = ['馒头', '花卷', '豆包', '大饼']
yield from lst1
yield from lst2
g = func()
for i in g:
print(i)
# 在函数中将return改写成yield就是一个生成器
# yield 会记录执行位置
# return 和 yield 都是返回,
# return 可以写多个,但是只执行一次,yield可以写多个,还可以返回多次
# 一个__next__() 对应 一个yield
# 生成器可以使用for循环获取值
# yield from -- 将可迭代对象元素逐个返回
# 在函数的内部 yield 能将for循环和while循环进行临时暂停
第十四章 推导式
1.列表推导式
1.循环模式:[变量(加工的变量) for 变量 in iterable]
2.筛选模式: [变量(加工的变量) for 变量 in iterable if 条件]
li = []
for i in range(10):
li.append(i)
print(li)
循环模式
#升级版本推导式
print([i for i in range(20)])
筛选模式
print([i for i in range(20) if i %2 == 0])
2.生成器表达式
循环模式
g = (i for i in range(20))
print(next(g))
print(next(g))
print(list((i for i in range(20))) #转变为列表
筛选模式
g = (i for i in range(20) if i %2 ==1)
for i in g:
print(i)
3.字典推导式
print({i:i+1 for i in range(10)})
print({i:i+1 for i in range(10) if i % 2 == 0})
#{键:值 for循环 加工条件}
4.集合推导式
print({i for i in range(10)})
print({i for i in range(10) if i % 2 == 0})
第十五章 内置函数一(了解)
eval:执行字符串类型的代码,并返回最终结果。千万不能使用
eval('2 + 2') # 4
exec:执行字符串类型的代码。 千万不能使用
for i in [1,2,3]:
print(i)
'''
exec(s)
1
2
3
hash:获取一个对象(可哈希对象:int,str,Bool,tuple)的哈希值。
print(hash(12322))
print(hash('123'))
print(hash('arg'))
print(hash('alex'))
print(hash(True))
print(hash(False))
print(hash((1,2,3)))
#判断时候哈希
help:函数用于查看函数或模块用途的详细说明。
print(help(list))
print(help(str.split))
callable:函数用于检查一个对象是否是可调用的。如果返回True,仍然可能调用失败;但如果返回False,调用对象ojbect绝对不会成功。
name = 'alex'
def func():
pass
print(callable(name)) # False
print(callable(func)) # True
int:函数用于将一个字符串或数字转换为整型。
print(int()) # 0
print(int('12')) # 12
print(int(3.6)) # 3
print(int('0100',base=2)) # 将2进制的 0100 转化成十进制。结果为 4
float:函数用于将整数和字符串转换成浮点数。
complex:函数用于创建一个值为 real + imag * j 的复数或者转化一个字符串或数为复数。如果第一个参数为字符串,则不需要指定第二个参数。。
print(float(3)) # 3.0
print(complex(1,2)) # (1+2j)
bin:将十进制转换成二进制并返回。
oct:将十进制转化成八进制字符串并返回。
hex:将十进制转化成十六进制字符串并返回。
print(bin(10),type(bin(10))) # 0b1010 <class 'str'>
print(oct(10),type(oct(10))) # 0o12 <class 'str'>
print(hex(10),type(hex(10))) # 0xa <class 'str'>
divmod:计算除数与被除数的结果,返回一个包含商和余数的元组(a // b, a % b)。
round:保留浮点数的小数位数,默认保留整数。
pow:求xy次幂。(三个参数为xy的结果对z取余)
print(divmod(7,2)) # (3, 1)
print(round(7/3,2)) # 2.33
print(round(7/3)) # 2
print(round(3.32567,3)) # 3.326
print(pow(2,3)) # 两个参数为2**3次幂
print(pow(2,3,3)) # 三个参数为2**3次幂,对3取余。
bytes:用于不同编码之间的转化。
# s = '你好'
# bs = s.encode('utf-8')
# print(bs)
# s1 = bs.decode('utf-8')
# print(s1)
# bs = bytes(s,encoding='utf-8')
# print(bs)
# b = '你好'.encode('gbk')
# b1 = b.decode('gbk')
# print(b1.encode('utf-8'))
ord:输入字符找当前字符编码的位置
chr:输入当前编码的位置数字找出其对应的字符
# ord 输入字符找该字符编码的位置
# print(ord('a'))
# print(ord('中'))
# chr 输入位置数字找出其对应的字符
# print(chr(97))
# print(chr(20013))
repr:返回一个对象的string形式(原形毕露)。
# %r 原封不动的写出来
# name = 'taibai'
# print('我叫%r'%name)
# repr 原形毕露
print(repr('{"name":"alex"}'))
print('{"name":"alex"}')
all:可迭代对象中,全都是True才是True
any:可迭代对象中,有一个True 就是True
# all 可迭代对象中,全都是True才是True
# any 可迭代对象中,有一个True 就是True
# print(all([1,2,True,0]))
# print(any([1,'',0]))
print(globals()) 查看全局的变量
print(nonlobals()) 查看局部的
第十六章 内置函数二
高阶函数:内置函数中还可以套函数的函数
常见高阶函数:sorted()、filter()、map()、max()、min()、reduce()
1.abs() #绝对值
返回的都是正数
2.enumerate --枚举
可迭代对象","序号的起始值" # 默认的起始值是0
lst =[1,2,3,4,5]
print([ i for i in enumerate(lst)])
#[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)]
print(dict([i for i in enumerate(range(20),1)]))
3.max 求最大值
print(max("123")) #可以列表等
4.min 最小值
print(min("123"))
5.sum 求和
print(sum([1,2,3,10],100))
6.print()
#更换链接符
print(1,2,3,4,sep="*")
#1*2*3*4
print(1,end=' ')
print(1,end="")
print(1)
#1 11
#项文件中添加
print(12345,file=open("1.txt","w",encoding="utf-8"))
print(dict(key=1,a="alex")) #字典的一种写法
7.zip() 拉链
按照最少的进行合并
lst1 =[1,2,3,4,5]
lst2=['a',"w","q","a","b","qwe"]
print(list(zip(lst1,lst2)))
print(dict(list(zip(lst1,lst2)))) #面试题
第十七章 匿名函数
1.匿名函数
lambda 是一行函数
形参可以不写
返回值必须要写
f=lambda x,y:x+y
print(f(1,2))
print(f.__name__) #查看函数的名字
# lambda #关键字 ---定义函数 就是函数名
# x,y 形参
# x+y 返回值 只能返回一个数据类型
一行调用
print((lambda x,y:x+y)(1,2))
lst =list((lambda i:i*i for i in range(6)))
print(lst[2](3))
lst =list((lambda :i*i for i in range(6)))
print(lst[2]())
第十八章 重要内置函数
1.format
print(format(13,">20")) #右对齐
print(format(13,"<20")) #左对齐
print(format(13,"^0")) #左对齐
print(format(13,"b")) #2
print(format(13,"d")) #10
print(format(13,"o")) #8
print(format(13,"x")) #16
2.filter过滤
lst =[1,2,3,4,5]
def fun(s):
return s>3
print(list(filter(fun,lst)))
#fun 过滤条件 lst迭代对象
print(list(filter(lambda x:x,lst)))
3.map()对象映射
print(list(map(lambda x:x+1,[1,2,3,4])))
#对可迭代对象中每个元素进行加工
4.翻转
lst = [1,2,3,4,5]
lst.reverse()
print(lst)
lst1 = list(reversed(lst))
print(lst)
print(lst1)
5.排序sorted
升序
lst = [1,23,34,4,5,213,123,41,12,32,1]
print(sorted(lst)) # 升序
print(lst)
降序
lst = [1,23,34,4,5,213,123,41,12,32,1]
print(sorted(lst,reverse=True)) # 降序
key
dic = {"key":1,"key1":2,"key3":56}
print(sorted(dic,key=lambda x:dic[x],reverse=True)) # key是指定排序规则
print(max([1,2,-33,4,5],key=abs)) # 按照绝对值的大小,返回此序列最小值
6.累计算reduce
累计算
from functools import reduce
# reduce 累计算
print(reduce(lambda x,y:x-y,[1,2,3,4,5]))
第十九章 闭包
1.在嵌套函数中,使用非全局变量 且不是本层的 就是闭包
闭包的作用,保证数据的安全性
例子:
def func():
a = 1
def f1():
def foo():
print(a)
return foo
return f1
# ret = func()
# a = ret()
# a()
func()()()
def func():
avg_lst = [] # 自由变量
def foo(pirce):
avg_lst.append(pirce)
avg = sum(avg_lst) / len(avg_lst)
return avg
return foo
ret = func()
print(ret(150000))
print(ret(160000))
print(ret(170000))
print(ret(150000))
print(ret(180000))
print(ret.__closure__) #判断是否是闭包
闭包的作用:
1. 保证数据的安全性
2. 装饰器
了解:
print(ret.__code__.co_freevars) # 获取的是自由变量
print(ret.__code__.co_varnames) # 获取的是局部变量
第二十章 装饰器
作用在不修改源码及调用方式前提下额外增加一些功能
1.开放原则
1.对扩展是开放的 : 增加新功能
2.对修改是封闭的(修改已经实现的功能)
版本一
测试此函数的执行效率
3.语法
语法糖 -- 甜语法糖必须放在被装饰的函数正上方
标准版(装饰器):
def func(a): #a是要被装饰的函数名
def foo(*args,**kwargs):
"装饰之前的操作"
ret = a(*args,**kwargs)
"装饰之后的操作"
return ret
return foo
@func
def f1(*args,**kwargs):
print(f"这是一个{args}")
return "我可以返回了"
f1(1,2,3,34,4,5)
版本low
import time
def times(fu):
def inner():
start_time=time.time()
fu()
print(time.time() - start_time)
return inner
def foo():
time.sleep(3)
print(12324)
foo = times(foo)
foo()
版本高级
# 高级
import time
def wrapper(f):
def inner(*args,**kwargs):
"被装饰前"
start_time = time.time()
f(*args,**kwargs) # func("alex")
print(time.time() - start_time)
"被装饰后"
return inner # 切记不要加括号
@wrapper # foo = wrapper(foo)
def foo(*args,**kwargs):
print(f"这是{args}函数")
time.sleep(3) #模拟网络延时
# foo = wrapper(foo)
foo("al","su")
第二十一章 带参数的装饰器
装饰器其实就是一个闭包函数,再说简单点就是两层的函数
举例
def auth(argv):
def wrapper(func):
def inner(*args,**kwargs):
func(*args,**kwargs)
return inner
return wrapper
login_dic={
"flag":False,
"username":None
}
def auth(argv):
def wrapper(func):
def inner(*args,**kwargs):
if login_dic["flag"]:
func(*args,**kwargs)
else:
if argv == "QQ":
print("欢迎登陆QQ")
user = input("username")
pwd = input("password")
if user == "zbb" and pwd=="zbb123":
login_dic["flag"] =True
login_dic["username"]=user
func(*args,**kwargs)
else:
print("用户名,密码")
return inner
return wrapper
@auth("QQ")
def foo():
print("qq登录")
# wrapper = auth("QQ")
# foo = wrapper(foo)
foo()
第二十二章 多个装饰器装饰一个参数
def wrapper1(func):
def inner1(*args,**kwargs):
print(1)
func(*args,**kwargs)
print(11)
return inner1
def wrapper2(func): # func == foo
def inner2(*args,**kwargs):
func(*args, **kwargs)
print(22)
return inner2
def wrapper3(func):
def inner3(*args,**kwargs):
print(3)
func(*args, **kwargs)
print(33)
return inner3
@wrapper1 # 1 11
@wrapper3 # 3 33
@wrapper2 # 8 22
def foo():
print(8)
# foo = wrapper2(foo) # foo == inner2
# foo = wrapper3(foo) # inner3 = wrapper3(inner2)
# foo = wrapper1(foo) # inner1 = wrapper1(inner3)
foo()