Python閉包的延遲繫結

2021-09-29 01:45:33 字數 1992 閱讀 7648

1. 什麼是閉包, 閉包必須滿足以下3個條:

2. 閉包的優點

def

add(a)

:def

add(b)

:return a + b

return add

ad(2)(

2)# 計算2+2的值, 用類實現的話, 相對麻煩

# 閉包使用nonlocal

deftester

(start)

: state = start

defnested

(label)

:nonlocal state

print

(label, state)

state +=

1return nested # 結合nonlocal使用的話還能實現意想不到的效果, 初始情況下給start傳入不同的值, 會儲存到不同的物件

deftest

(start)

:global state

state = start

defnest

(label)

:global state

print

(label, state)

state +=

1return nest # global的話初始情況下給start無論傳入什麼值, 操作的始終都是乙個物件, 達不到類實現的效果

# 類實現nonlocal的效果

class

myclass

:def

__init__

(self, start)

: self.start = start

defnest

(self, label)

:print

(label, self.start)

self.start +=

1

3. 閉包的延遲繫結
def

multipliers()

:return

[lambda x : i*x for i in

range(4

)]print

([m(2)

for m in multipliers()]

)# 列印結果是[6, 6, 6, 6], 而不是[0, 2, 4, 6]

# 原因: i不僅僅控制著迴圈次數, 而且還在為i*x的i提供引用的值, 當python直譯器執行的時候, 呼叫multipliers()的時候, 只會先定義lambda匿名函式, 但是卻會直接執行後面的for迴圈, 當lambda被呼叫的時候, i已經指向了4, 這就是延遲繫結的特性(python中非區域性變數繫結的是記憶體位址, 區域性變數繫結的是值)

4. 延遲繫結的解決辦法

方法一:

def

multipliers()

:return

[lambda x, i=i: i*x for i in

range(4

)]print

([m(2)

for m in multipliers()]

)# 列印結果是[0, 2, 4, 6]

# python直譯器在定義函式時, 遇到關鍵字引數, 就必須初始化引數, 此時後面的for迴圈每迴圈一次, 前面的關鍵字引數i就需要找一次引用物件, for迴圈每迴圈一次結果i都會被i這個關鍵字引數指向, 這個指向的是值, 不是空間

方法二: python生成器

deff1(

):for i in

range(4

):yield

lambda x: x * i

print

(list

((m(2)

for m in f1())

))# list()中是()這個是生成器的推導式(這種方法可以簡單的呼叫上面的函式內部的生成器)

總結: 延遲繫結只是一種現象, 一種特徵, 並不是本質

Python 知識點 閉包延遲繫結

在乙個函式內部定義另乙個函式,外部的函式為外函式,內部的函式為內函式,內函式裡運用了外函式的臨時變數,並且外函式的返回值是內函式的引用。這就形成了乙個閉包。通常情況下,乙個函式執行結束後,函式內部的所有東西都會被釋放掉,區域性變數也會消失。但是如果外函式在結束時發現自己的臨時變數會在內函式中用到時,...

Python的閉包的後期繫結問題

def multi return lambda x i x for i in range 4 print m 3 for m in multi 正確答案是 9,9,9,9 而不是 0,3,6,9 產生的原因是python的閉包的後期繫結導致的,這意味著在閉包中的變數是在內部函式被呼叫的時候被查詢的,...

python 閉包 python 閉包

閉包 因為python中函式也可以當作物件,所以如果出現當我們返回乙個函式,而該函式含有外部變數的時候就形成了閉包。閉包的特點 是個巢狀函式 可以獲得非區域性的變數 將函式當作物件返回 看乙個例子會更易理解 def make printer msg msg hi there def printer ...