Python之路 閉包

2022-01-16 11:11:49 字數 3383 閱讀 4138

我們要給定乙個x,要求一條直線上x對應的y的值。公式是y = kx+b。

我們需要用k,b來確定這條直線,則我們實現的函式應該有3個引數:

def

line(k, b, x):

print(k * x +b)

line(1, 3, 4)

line(1, 3, 5)

line(1, 3, 6)

可以看到,我們每次修改x都要重新傳入k和b。

我們也可以用全域性變數來實現:

k = 1b = 3

defline(x):

print(k * x +b)

line(4)

line(5)

line(6)

k和b為全域性變數,但如果我們想要另外一條不同的直線時,則還需要重新定義k和b的值,同樣不合理。而且全域性變數會暴露給其他不相關的函式,容易造成衝突,或**混亂。

用物件導向來實現:

class

line(object):

def__init__

(self, k, b):

self.k =k

self.b =b

defcreate_y(self, x):

print(self.k * x +self.b)

l1 = line(1, 3)

l1.create_y(4)

l1.create_y(5)

l1.create_y(6)

用類和物件來實現肯定是可以的,但是這麼乙個簡單的功能使用物件導向比較浪費資源。

def

line(k, b):

defcreate_y(x):

print(k * x +b)

return

create_y

l1 = line(1, 3)

l1(4)

l1(5)

l1(6)

從以上**可以直觀的看到,閉包有以下幾個條件:

1.在乙個外函式中定義了乙個內函式。

2.內函式裡運用了外函式的臨時變數。

3.並且外函式的返回值是內函式的引用。

乙個函式結束的時候,會把自己的臨時變數都釋放給記憶體,之後變數都不存在了。一般情況下,確實是這樣的。但是閉包是乙個特別的情況。外部函式發現,自己的臨時變數會在將來的內部函式中用到,自己在結束的時候,返回內函式的同時,會把外函式的臨時變數和內函式繫結在一起。所以外函式已經結束了,呼叫內函式的時候仍然能夠使用外函式的臨時變數。

def

line(k, b):

multi = 10;

defcreate_y(x):

print((k * x + b) *multi)

return

create_y

l1 = line(1, 3)

l1(4)

l1(5)

l1(6)

假設外層函式中有乙個multi變數,這個變數可以提供給內層函式訪問,但是如果內層函式想修改這個multi變數怎麼辦呢?

在python3.x中,我們可以使用nonlocal關鍵字來實現:

def

line(k, b):

multi = 10;

defcreate_y(x):

nonlocal multi

multi = 5

print((k * x + b) *multi)

return

create_y

l1 = line(1, 3)

l1(4)

l1(5)

l1(6)

這個nonlocal類似與global的作用,但是global是用於修改全域性變數,而nonlocal是用於修改閉包中的外層臨時變數。

如果在python2.x中,則不存在nonlocal關鍵字,我們可以通過將multi變為可變型別資料來實現:

def

line(k, b):

#python2.x中將multi變為列表

multi = [10]

defcreate_y(x):

#可以對外層函式的列表進行修改

multi[0] = 5

print((k * x + b) *multi[0])

return

create_y

l1 = line(1, 3)

l1(4)

l1(5)

l1(6)

函式(包含匿名函式):只是功能**,不包含資料。

物件:包含資料和功能實現。

閉包:包含資料和功能實現。資料指外層函式接收到的引數以及他的區域性變數,功能指內層函式的功能。

當函式、匿名函式、物件和閉包做為實參傳遞時,他們有什麼區別????

1.函式和匿名函式被當做實參傳遞時,傳遞的是功能的引用,可以通過該引用呼叫他們實現的功能。但資料需要另外提供。

2.閉包被當做實參傳遞時,其實傳遞了資料+功能。例如:

def

line(k, b):

#python2.x中將multi變為列表

multi = [10]

defcreate_y(x):

#可以對外層函式的列表進行修改

multi[0] = 5

print((k * x + b) *multi[0])

return

create_y

deffunction(func):

func(5)

function(line(1, 3))

我們可以看到,閉包line被傳入function,實際上帶著資料k=1,b=3。

而如果是普通函式:

def

line_norm(k, b, x):

print(k * x +b)

deffunction(func):

func(1, 3, 5)

function(line_norm)

這裡的k=1,b=3是function函式自己提供的。

3.物件被當做實參傳遞時,該物件中的成員屬性作為資料,成員方法作為方法,都被傳遞給function函式。

class

line(object):

def__init__

(self, k, b):

self.k =k

self.b =b

defcreate_y(self, x):

print(self.k * x +self.b)

line1 = line(1, 3)

deffunction(inst):

inst.create_y(5)

function(line1)

python之路 閉包函式

閉包 def func name eva definner print name 閉包函式 內部函式包含對外部作用域而非全域性作用域名字的引用,該內部函式成為閉包函式。函式內部定義的函式稱為內部函式 由於有了作用域的關係,我們就不能拿到函式內部的變數和函式了。如果我們就是想拿怎麼辦呢?返回呀!我們都...

python 閉包 python 閉包

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

Python自由之路(五)Pyhton 閉包

如果在乙個內部函式裡,對在外部作用域 但不是在全域性作用域 的變數進行引用,那麼內部函式就被認為是閉包 closure 閉包在函式式程式設計中是乙個重要的概念。語法上看比較簡單,但是用處卻是相當廣泛的。在python 2.1版本以前,只有全域性域和區域性作用域,而在2.1以後的版本中我們可以使用靜態...