1. 程式人生 > >閉包函數與裝飾器

閉包函數與裝飾器

格式 發現 引用 內存地址 type 不定長參數 示例 dex 問題

閉包函數

定義

  在函數內定義了一個內部函數,該內部函數只對外部作用域變量的引用,不對全局作用域變量的引用的函數被成為閉包函數。

代碼示例

1 def foo():
2     fun = "我是外部變量"
3     def bar(): # 指的是bar函數為閉包函數,而不是foo()函數為閉包函數
4         print(fun)
5     return bar
6 
7 fun = "幹擾測試" # 這裏的fun是全局變量,但是執行a函數,打印的結果始終是bar函數的外部變量 fun。
8 a = foo()
9 a()

裝飾器

定義

  裝飾函數的工具(函數)

特點

  在不改變被裝飾函數的源代碼和調用方式的前提下,為被裝飾的函數增加新的功能。

裝飾器的基本格式

 1 def foo(fun): #foo為裝飾器名字,fun為被裝飾函數的名字
 2     def run(*args,**kwargs): #使用不定長參數可以解決被裝飾函數有五參數的問題
 3         pass
 4         ret = fun(*args,**kwargs)#如何定義的就如何執行。有的被裝飾函數有返回,因此要把運行被裝飾函數的返回值保存下來
 5         pass
 6         return ret #返回運行被裝飾函數的返回值,代碼結束。
 7     return run
 8 # @foo3 
 9 # @foo2
10 @foo #一個函數可以被多個裝飾器裝飾,最下面的裝飾起會最先被運行,越往上就靠後執行 11 def test1(): # 被裝飾函數無形參,無返回值類型 12 pass 13 14 15 @foo 16 def test2(a): # 被裝飾函數有形參類型 17 print(a) 18 pass 19 20 21 @foo 22 def test3(a): # 被裝飾函數有形參有返回值類型 23 pass 24 return a 25 26 27 @foo 28 def test4(a,b,c,d): # 被裝飾函數有多個形參類型 29
pass

無參裝飾器

  特點:@裝飾器名字後面沒有括號,只需傳入被裝飾函數的名字,無需傳入其他的參數的裝飾起被成為無參裝飾器。

代碼示例

def foo(fun):
    def bar(*args,**kwargs):
        print("這是前奏")
        ret = fun(*args,**kwargs)
        print("這是結尾")
        return ret
    return bar

@foo # 實際上是執行了 "index = foo(index)",這一步的最終結果是把bar的內存地址賦值給index變量,這樣以後只要執行index(),實際上去執行bar()。
def index():
    print("我是index頁面")

# index = foo(index)
index()

裝飾器的實質

  裝飾器對被裝飾函數功能添加的實質是把被裝飾函數的內存地址替換為另一個函數的內存地址,以後只要執行裝飾函數的函數()名實際上執行替換過函數的地址。而裝飾器函數內部一方面執行了原來被裝飾函數的函數體,同時也新添加了部分代碼,從而實現了對被裝飾函數功能的添加。

有參裝飾器

  特點:在@裝飾器名後面有(形參),要滿足在傳入被裝飾函數內存地址的同時,還需要傳入一個變量。

def timer2(auth_type): #1:什麽也不做
    def timer(fun):
        def bar(*arg, **kwargs):
            if auth_type == "file":
                name = input("name:")
                pwd = input("pwd:")
                if name == "root" and pwd == "admin":
                    ret = fun(*arg, **kwargs)
                    return ret
                else:
                    print("滾去登錄")
            else:
                print("還不會玩")
        return bar
    return timer

@timer2(auth_type="file") #只要有了(),就是一個函數,首先執行的就是timer2()這個函數,此時執行的結果為@timer,同時拿到了一個auth_type="file"的變量,然後再去執行 ---->index = timer(index) #發現要去執行timer2函數
def index():
    # time.sleep(random.randrange(1,3))
    print("這裏是index頁面")
index()


@timer2(auth_type="file")
def foo(a,b):
    print(a,b)
foo(1,2)


@timer2(auth_type="file")
def boo(a):
    print(a)

boo(456)

閉包函數與裝飾器