前言:函數名是一個特性的變量,能夠做爲容器的元素,也能夠做爲函數的參數,也能夠當作返回值。python
閉包定義:閉包
內層函數對外層函數(非全局)變量的引用,這個內層函數就能夠成爲閉包app
在Python中咱們用__closure__
來檢查函數是不是閉包函數
def func1(): name = '張三' def func2(): print(name) # 可以訪問到外層做用域的變量 func2() print(func2.__closure__) # (<cell at 0x1036c7438: str object at 0x10389d088>,) func1() print(func1.__closure__) # None
前言:軟件設計原則:開閉原則,又稱開放封閉原則工具
def create_people(): print('女媧真厲害,捏個泥吹口氣就成了人!') def a(func): def b(): print('灑點水') func() return b ret = a(create_people) ret()
經過裝飾器語法等同於設計
def a(func): def b(): print('灑點水') func() return b @a # 裝飾器語法糖的做用就是上述函數ret() def create_people(): print('女媧真厲害,捏個泥吹口氣就成了人!') create_people()
裝飾帶返回值的函數,即return出被裝飾函數的執行結果code
def foo(func): # 接收的參數是一個函數名 def bar(): # 定義一個內層函數 print("這裏是新功能...") # 新功能 r = func() # 在內存函數中拿到被裝飾函數的結果 return r # 返回被裝飾函數的執行結果 return bar # 定義一個有返回值的函數 @foo def f1(): return '嘿嘿嘿' # 調用被裝飾函數 ret = f1() # 調用被裝飾函數並拿到結果 print(ret)
裝飾帶參數的函數orm
def func1(func): # 接收的參數爲一個函數名 def inner(*args, **kwargs): # 這裏須要定義和被裝飾函數相同的參數 print("新功能") # 新功能 ret = func(*args, **kwargs) #被裝飾的函數和參數 print("新功能") return ret return inner # 定義一個須要倆個參數的函數 @func1 def func(a, b): return a + b ret = func(3, 5) print(ret)
帶參數的裝飾器 即在裝飾器外在寫一層函數,從而使其帶參數內存
def d(a=None): # 定義一個外層函數,給裝飾器傳參數 def func1(func): # 接收的是一個函數名 def inner(*args, **kwargs): # 被裝飾的函數,和參數 if a: print(f"歡迎來到{a}") #添加新功能 else: print("歡迎來到王者榮耀") func(*args, **kwargs) return inner return func1 # @d("英雄聯盟") # def func(st): # print(st) # func("敵軍還有三十秒到達戰場") # 歡迎來到英雄聯盟 # 敵軍還有三十秒到達戰場 @d() def func(st): print(st) func("敵軍還有三十秒到達戰場") # 歡迎來到王者榮耀 # 敵軍還有三十秒到達戰場
裝飾器修復技術作用域
定義:被裝飾的函數最終都會失去原本的__doc__等信息, Python給咱們提供了一個修復被裝飾函數的工具。
from functools import wraps #導入 print(f1.__doc__) print(f1.__name__)
多個裝飾器裝飾同一函數
from functools import wraps def wrapper2(func): @wraps(func) def inner(*args, **kwargs): r = func(*args, **kwargs) return f"<2>{r}</2>" return inner def 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 a print(func("Hello World!!")) #<2><1>Hello World!!</1></2>
def foo1(func): print("d1") def inner1(): print("inner1") return "<i>{}</i>".format(func()) return inner1 def 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) ==> inner1 ret = f1() # 調用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 = a self.mode = "裝飾" def __call__(self, *args, **kwargs): if self.mode == "裝飾": self.func = args[0] # 默認第一個參數是被裝飾的函數 self.mode = "調用" return self # 當self.mode == "調用"時,執行下面的代碼(也就是調用使用類裝飾的函數時執行) if self.a: print("歡迎來到{}頁面。".format(self.a)) else: print("歡迎來到首頁。") 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('張三')
裝飾類
# 定義一個類裝飾器 class D(object): def __call__(self, cls): class Inner(cls): # 重寫被裝飾類的f方法 def f(self): print('Hello 張三.') return Inner @D() class C(object): # 被裝飾的類 # 有一個實例方法 def f(self): print("Hello world.") if __name__ == '__main__': c = C() c.f()