第一章 函數介紹
函數的好處:
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='\t')
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()