1. 程式人生 > 實用技巧 >Python中的延遲繫結

Python中的延遲繫結

延遲綁定出現在閉包問題中。下面我們看一個閉包的例子:

def gen_mul(n):
    def mul(x):
        return n*x
    return mul

double = gen_mul(2)
double_value = double(6)

print(double_value)

可以看出滿足閉包的幾點:

  • 有內部函式
  • 內部函式引用了外部函式中的自由變數
  • 內部函式被返回

閉包的優點:

  • 可以避免使用全域性變數
  • 可以持久化變數,達到靜態變數的作用

閉包的缺點:

  • 可能會消耗大量的記憶體

  • 可能會導致記憶體洩漏

現在我們來看看另一個會引出延遲繫結的例子:

def multipliers():
    return [lambda x : x*i for i in range(4)]

print([m(2) for m in multipliers()])

上邊的例子會輸出[6,6,6,6],而不是我們預期的[0,2,4,6]。

這就是延遲繫結導致的結果。具體過程我們可以來分析下:
執行第三行時,會先執行multipliers函式,然後執行函式中的列表解析式。在每一次迭代的時候都會生成一個匿名函式(這裡只是定義)作為元素。然後回到第三行,遍歷返回的列表中的匿名函式,傳入引數2並執行。此時函式類似於這樣:

def noname(x):
    
return i * x

這裡的原因就是在python中,相對而言的區域性變數繫結的是值,非區域性變數繫結的是空間,而不是值得本身,在上面得例子中,for迴圈得i,相對於lambda函式而言,是全域性變數,所以繫結得是空間,最終導lambda函式執行得時候,讀取得是最後儲存i的值,解決辦法是通過函式的預設賦值,達到儲存臨時變數的作用。