中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何正確的使用Python閉包

發布時間:2021-06-01 16:22:50 來源:億速云 閱讀:136 作者:Leah 欄目:開發技術

如何正確的使用Python閉包?很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

一、Python 中的作用域規則和嵌套函數

每當執行一個函數時,就會創建一個新的局部命名空間,它表示包含函數體內分配的函數參數和變量名的局部環境。我們可以將名稱空間看作一個字典,其中鍵是對象名稱,值是對象本身。

解析名稱時,解釋器首先搜索本地命名空間。如果不存在匹配,則搜索全局名稱空間,該名稱空間是定義函數的模塊。如果仍然沒有找到匹配項,則在引發 NameError 異常之前最終檢查內置名稱空間。下圖說明了這一點:

如何正確的使用Python閉包

讓我們考慮下面的例子:

age = 27
def birthday(): 
  age = 28
birthday()
print(age)  # age will still be 27
>>
27

當變量在函數內部賦值時,它們總是綁定到函數的本地名稱空間; 因此,函數體中的變量 age 指的是一個包含值28的全新對象,而不是外部變量。可以使用全局語句更改此行為。下面的示例強調了這一點:

age = 27
name = "Sarah"
def birthday(): 
  global age       # 'age' is in global namespace 
  age = 28
  name = "Roark"
birthday()         # age is now 28. name will still be "Sarah"

Python 也支持嵌套函數定義(函數內部的函數):

def countdown(start):
  # This is the outer enclosing function
  def display():
    # This is the nested function
    n = start
    while n > 0:
      n-=1
      print('T-minus %d' % n)
 
  display()
# We execute the function
countdown(3)
>>>
T-minus 3
T-minus 2
T-minus 1

二、定義閉包函數

在上面的示例中,如果函數 countdown()的最后一行返回了 display 函數而不是調用它,會發生什么情況?這意味著該函數的定義如下:

def countdown(start):
  # This is the outer enclosing function
  def display():
    # This is the nested function
    n = start
    while n > 0:
      n-=1
      print('T-minus %d' % n)
  return display
# Now let's try calling this function.
counter1 = countdown(2)
counter1()
>>>
T-minus 2
T-minus 1

使用值2調用 countdown()函數,并將返回的函數綁定到名稱 counter1。在執行 counter1()時,它使用最初提供給 countdown ()的 start 值。因此,在調用 counter1()時,盡管我們已經執行了 count1()函數,但仍然記住這個值。

這種將一些數據(本例中為2)附加到代碼的技術在 Python 中稱為閉包。

即使變量超出范圍或函數本身從當前名稱空間中移除,也會記住封閉范圍中的這個值。我們可以嘗試下面的代碼來確認:

>>> del countdown
>>> counter1()
T-minus 2
T-minus 1
>>> countdown(2)
Traceback (most recent call last):
...
NameError: name 'countdown' is not defined

三、何時使用閉包?

當一個類中實現的方法很少(大多數情況下只有一個方法)時,閉包可以提供一個替代的、更優雅的解決方案。此外,如果我們希望根據延遲或延遲計算的概念編寫代碼,閉包和嵌套函數特別有用。下面是一個例子:

from urllib.request import urlopen
def page(url): 
  def get(): 
    return urlopen(url).read() 
  return get

在上面的示例中,page ()函數實際上并不執行任何計算。相反,它只是創建并返回一個函數 get () ,該函數在調用 web 頁面時獲取頁面內容。因此,在 get ()中執行的計算實際上被延遲到計算 get ()時程序中的某個后續點。例如:

>>> url1 = page("http://www.google.com") 
>>> url2 = page("http://www.bing.com") 
>>> url1
<function page.<locals>.get at 0x10a6054d0>
>>> url2
<function page.<locals>.get at 0x10a6055f0>
  
>>> gdata = url1()     # Fetches http://www.google.com 
>>> bdata = url2()     # Fetches http://www.bing.com
>>>

可以找到閉包函數中包含的值。

所有函數對象都有一個 _closure_ 屬性,如果它是一個閉包函數,那么這個屬性將返回一組單元格對象。根據上面的例子,我們知道 url1和 url2是閉包函數。

>>> page.__closure__       # Returns None since not a closure
>>> url1.__closure__
(<cell at 0x10a5f1250: str object at 0x10a5f3120>,)

單元格對象具有存儲關閉值的屬性 cell_contents。

>>> url1.__closure__[0].cell_contents
'http://www.google.com'
>>> url2.__closure__[0].cell_contents
'http://www.bing.com'

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

固原市| 醴陵市| 舟曲县| 吐鲁番市| 鄂州市| 侯马市| 双流县| 萝北县| 隆昌县| 苗栗市| 棋牌| 孟津县| 德昌县| 尼玛县| 南投县| 廊坊市| 如皋市| 拜泉县| 温州市| 深州市| 塔城市| 中江县| 金阳县| 蓬溪县| 霍邱县| 包头市| 紫阳县| 梅州市| 宣城市| 鄯善县| 临邑县| 浑源县| 十堰市| 阿合奇县| 商水县| 孟村| 罗源县| 天峻县| 锡林郭勒盟| 青川县| 三穗县|