Python 基礎(chǔ)教程

Python 流程控制

Python 函數(shù)

Python 數(shù)據(jù)類(lèi)型

Python 文件操作

Python 對(duì)象和類(lèi)

Python 日期和時(shí)間

Python 高級(jí)知識(shí)

Python 參考手冊(cè)

Python 閉包

在本文中,您將了解什么是Python閉包,如何定義閉包,以及使用閉包的原因。

嵌套函數(shù)中的非局部變量

在了解閉包是什么之前,我們必須首先了解什么是嵌套函數(shù)和非局部變量。

在另一個(gè)函數(shù)內(nèi)部定義的函數(shù)稱(chēng)為嵌套函數(shù)。嵌套函數(shù)可以訪問(wèn)封閉范圍的變量。

在Python中,默認(rèn)情況下,這些非本地變量是只讀的,并且我們必須將它們明確聲明為非本地變量(使用nonlocal關(guān)鍵字)才能進(jìn)行修改。

以下是訪問(wèn)非局部變量的嵌套函數(shù)的示例。

def print_msg(msg):
# 這是外部封閉函數(shù)

    def printer():
# 這是嵌套函數(shù)
        print(msg)

    printer()

# 我們執(zhí)行這個(gè)函數(shù)
# 輸出: Hello
print_msg("Hello")

我們可以看到嵌套函數(shù)printer()能夠訪問(wèn)封閉函數(shù)的非局部變量msg。

定義閉包函數(shù)

在上面的示例中,如果函數(shù)print_msg()的最后一行返回了printer()函數(shù)而不是調(diào)用它,將會(huì)發(fā)生什么? 這意味著功能定義如下。

def print_msg(msg):
# 這是外部封閉函數(shù)

    def printer():
# 這是嵌套函數(shù)
        print(msg)

    return printer  # 這變了

# 現(xiàn)在,讓我們嘗試調(diào)用此函數(shù)。
# 輸出: Hello
another = print_msg("Hello")
another()

這很不尋常。

print_msg()函數(shù)用字符串調(diào)用,"Hello"返回的函數(shù)綁定到另一個(gè)名稱(chēng)。在調(diào)用時(shí)another(),盡管我們已經(jīng)完成了print_msg()函數(shù)的執(zhí)行,但仍然記得該消息。

這種將一些數(shù)據(jù)("Hello")附加到代碼上的技術(shù)在Python中稱(chēng)為閉包。

即使變量超出范圍或函數(shù)本身已從當(dāng)前命名空間中刪除,也會(huì)記住封閉范圍中的這個(gè)值。

嘗試在Python Shell中運(yùn)行以下命令以查看輸出。

>>> del print_msg
>>> another()
Hello
>>> print_msg("Hello")
Traceback (most recent call last):
...
NameError: name 'print_msg' is not defined

閉包的條件?

從上面的實(shí)例可以看出,在Python中,當(dāng)嵌套的函數(shù)在其封閉的范圍內(nèi)引用一個(gè)值時(shí),我們有一個(gè)閉包。

以下幾點(diǎn)總結(jié)了在Python中創(chuàng)建閉包必須滿足的條件。

  • 我們必須有一個(gè)嵌套函數(shù)(函數(shù)在函數(shù)內(nèi)部)。

  • 嵌套函數(shù)必須引用在封閉函數(shù)中定義的值。

  • 封閉函數(shù)必須返回嵌套函數(shù)。

何時(shí)使用閉包?

那么,閉包有什么用呢?

閉包可以避免使用全局值,并提供某種形式的數(shù)據(jù)隱藏。它還可以為該問(wèn)題提供面向?qū)ο蟮慕鉀Q方案。

當(dāng)在一個(gè)類(lèi)中實(shí)現(xiàn)的方法很少(大多數(shù)情況下是一個(gè)方法)時(shí),閉包可以提供另一種更優(yōu)雅的解決方案。但是,當(dāng)屬性和方法的數(shù)量變大時(shí),最好實(shí)現(xiàn)一個(gè)類(lèi)。

這是一個(gè)簡(jiǎn)單的示例,其中閉包可能比定義類(lèi)和創(chuàng)建對(duì)象更可取。

def make_multiplier_of(n):
    def multiplier(x):
        return x * n
    return multiplier

# 3的乘數(shù)
times3 = make_multiplier_of(3)

# 5的乘數(shù)
times5 = make_multiplier_of(5)

# 輸出: 27
print(times3(9))

# 輸出: 15
print(times5(3))

# 輸出: 30
print(times5(times3(2)))

Python中的裝飾器也大量使用了閉包。

最后,最好指出可以找到封閉在封閉函數(shù)中的值。

所有函數(shù)對(duì)象都有一個(gè)__closure__屬性,如果它是一個(gè)閉包函數(shù),則該屬性返回單元格對(duì)象的元組。參考上面的示例,我們知道times3和times5是閉包函數(shù)。

>>> make_multiplier_of.__closure__
>>> times3.__closure__
(<cell at 0x0000000002D155B8: int object at 0x000000001E39B6E0>,)

單元格對(duì)象具有存儲(chǔ)關(guān)閉值的屬性cell_contents。

>>> times3.__closure__[0].cell_contents
3
>>> times5.__closure__[0].cell_contents
5

                                                                                                                                                                                                   

丰满人妻一级特黄a大片,午夜无码免费福利一级,欧美亚洲精品在线,国产婷婷成人久久Av免费高清