装饰器语法糖运用
裝飾器語(yǔ)法糖運(yùn)用
前言:函數(shù)名是一個(gè)特性的變量,可以作為容器的元素,也可以作為函數(shù)的參數(shù),也可以當(dāng)做返回值。
閉包定義:
內(nèi)層函數(shù)對(duì)外層函數(shù)(非全局)變量的引用,這個(gè)內(nèi)層函數(shù)就可以成為閉包
在Python中我們用__closure__來(lái)檢查函數(shù)是否是閉包
- def func1():name = '張三'def func2():print(name) # 能夠訪問(wèn)到外層作用域的變量func2()print(func2.__closure__) # (<cell at 0x1036c7438: str object at 0x10389d088>,)func1() print(func1.__closure__) # None
裝飾器
前言:軟件設(shè)計(jì)原則:開(kāi)閉原則,又稱開(kāi)放封閉原則
- 指對(duì)擴(kuò)展代碼的功能是開(kāi)放的,但對(duì)修改源代碼是封閉的,
- def create_people():print('女媧真厲害,捏個(gè)泥吹口氣就成了人!')def a(func):def b():print('灑點(diǎn)水')func()return bret = a(create_people) ret()
通過(guò)裝飾器語(yǔ)法等同于
- def a(func):def b():print('灑點(diǎn)水')func()return b@a # 裝飾器語(yǔ)法糖的作用就是上述函數(shù)ret() def create_people():print('女媧真厲害,捏個(gè)泥吹口氣就成了人!')create_people()
裝飾帶返回值的函數(shù),即return出被裝飾函數(shù)的執(zhí)行結(jié)果
- def foo(func): # 接收的參數(shù)是一個(gè)函數(shù)名def bar(): # 定義一個(gè)內(nèi)層函數(shù)print("這里是新功能...") # 新功能r = func() # 在內(nèi)存函數(shù)中拿到被裝飾函數(shù)的結(jié)果return r # 返回被裝飾函數(shù)的執(zhí)行結(jié)果return bar# 定義一個(gè)有返回值的函數(shù) @foo def f1():return '嘿嘿嘿'# 調(diào)用被裝飾函數(shù) ret = f1() # 調(diào)用被裝飾函數(shù)并拿到結(jié)果 print(ret)
裝飾帶參數(shù)的函數(shù)
- def func1(func): # 接收的參數(shù)為一個(gè)函數(shù)名def inner(*args, **kwargs): # 這里需要定義和被裝飾函數(shù)相同的參數(shù)print("新功能") # 新功能ret = func(*args, **kwargs) #被裝飾的函數(shù)和參數(shù)print("新功能") return retreturn inner# 定義一個(gè)需要倆個(gè)參數(shù)的函數(shù) @func1 def func(a, b):return a + bret = func(3, 5) print(ret)
帶參數(shù)的裝飾器 即在裝飾器外在寫一層函數(shù),從而使其帶參數(shù)
- def d(a=None): # 定義一個(gè)外層函數(shù),給裝飾器傳參數(shù)def func1(func): # 接收的是一個(gè)函數(shù)名def inner(*args, **kwargs): # 被裝飾的函數(shù),和參數(shù)if a:print(f"歡迎來(lái)到{a}") #添加新功能else:print("歡迎來(lái)到王者榮耀") func(*args, **kwargs)return innerreturn func1# @d("英雄聯(lián)盟") # def func(st): # print(st) # func("敵軍還有三十秒到達(dá)戰(zhàn)場(chǎng)")# 歡迎來(lái)到英雄聯(lián)盟# 敵軍還有三十秒到達(dá)戰(zhàn)場(chǎng)@d() def func(st):print(st) func("敵軍還有三十秒到達(dá)戰(zhàn)場(chǎng)") # 歡迎來(lái)到王者榮耀 # 敵軍還有三十秒到達(dá)戰(zhàn)場(chǎng)
裝飾器修復(fù)技術(shù)
定義:被裝飾的函數(shù)最終都會(huì)失去本來(lái)的__doc__等信息, Python給我們提供了一個(gè)修復(fù)被裝飾函數(shù)的工具。
- from functools import wraps #導(dǎo)入 print(f1.__doc__) print(f1.__name__)
多個(gè)裝飾器裝飾同一函數(shù)
- from functools import wrapsdef wrapper2(func):@wraps(func)def inner(*args, **kwargs):r = func(*args, **kwargs)return f"<2>{r}</2>"return innerdef wrapper1(func):@wraps(func)def inner(*args, **kwargs):r = func(*args, **kwargs)return f"<1>{r}</1>"return inner@wrapper2 @wrapper1 def func(a):return aprint(func("Hello World!!")) #<2><1>Hello World!!</1></2>
- def foo1(func):print("d1")def inner1():print("inner1")return "<i>{}</i>".format(func())return inner1def foo2(func):print("d2")def inner2():print("inner2")return "<b>{}</b>".format(func())return inner2@foo1 @foo2 def f1():return "Hello Andy"# f1 = foo2(f1) ==> print("d2") ==> f1 = inner2 # f1 = foo1(f1) ==> print("d1") ==> f1 = foo1(inner2) ==> inner1ret = f1() # 調(diào)用f1() ==> inner1() ==> <i>inner2()</i> ==> <i><b>inner1()</b></i> ==> <i><b>Hello Andy</b></i> print(ret)
類裝飾器
- class D(object):def __init__(self, a=None):self.a = aself.mode = "裝飾"def __call__(self, *args, **kwargs):if self.mode == "裝飾":self.func = args[0] # 默認(rèn)第一個(gè)參數(shù)是被裝飾的函數(shù)self.mode = "調(diào)用"return self# 當(dāng)self.mode == "調(diào)用"時(shí),執(zhí)行下面的代碼(也就是調(diào)用使用類裝飾的函數(shù)時(shí)執(zhí)行)if self.a:print("歡迎來(lái)到{}頁(yè)面。".format(self.a))else:print("歡迎來(lái)到首頁(yè)。")self.func(*args, **kwargs)@D() def index(name):print("Hello {}.".format(name))@D("電影") def movie(name):print("Hello {}.".format(name))if __name__ == '__main__':index('張三')movie('張三')
裝飾類
- # 定義一個(gè)類裝飾器 class D(object):def __call__(self, cls):class Inner(cls):# 重寫被裝飾類的f方法def f(self):print('Hello 張三.')return Inner@D() class C(object): # 被裝飾的類# 有一個(gè)實(shí)例方法def f(self):print("Hello world.")if __name__ == '__main__':c = C()c.f()
轉(zhuǎn)載于:https://www.cnblogs.com/yuncong/p/9886555.html
總結(jié)
- 上一篇: 浏览器差异总结,可以用此判断浏览器版本(
- 下一篇: 解决 Microsoft Excel h