Python 閉包(Closure)


Python  閉包 (Closure)

這里介紹一下python 的閉包

 

基本概念

閉包(closure)是函數式編程的重要的語法結構。

函數式編程的一個特點就是,允許把函數本身作為參數傳入另一個函數,還允許返回一個函數!

Python對函數式編程提供部分支持。由於Python允許使用變量,因此,Python不是純函數式編程語言。

 

閉包(closure)是函數式編程的重要的語法結構。函數式編程是一種編程范式 (而面向過程編程和面向對象編程也都是編程范式)。

在面向過程編程中,我們見到過函數(function);在面向對象編程中,我們見過對象(object)。

函數和對象的根本目的是以某種邏輯方式組織代碼,並提高代碼的可重復使用性(reusability)。

閉包也是一種組織代碼的結構,它同樣提高了代碼的可重復使用性。

 

不同的語言實現閉包的方式不同。Python以函數對象為基礎,

為閉包這一語法結構提供支持的 (我們在特殊方法與多范式中,已經多次看到Python使用對象來實現一些特殊的語法)。

Python一切皆對象,函數這一語法結構也是一個對象。

在函數對象中,我們像使用一個普通對象一樣使用函數對象,比如更改函數對象的名字,或者將函數對象作為參數進行傳遞。

 

函數對象的作用域

和其他對象一樣,函數對象也有其存活的范圍,也就是函數對象的作用域。

函數對象是使用def語句定義的,函數對象的作用域與def所在的層級相同。

比如下面代碼,我們在next函數的隸屬范圍內定義的函數test,就只能在test的隸屬范圍內調用。

def test():

    def next():
        print('next')

    print('test')

test()

# 執行結果  
> test

 

再看下面代碼

def test():

    def next():
        print('next')
    next()
    print('test')
    next()
test()

# 執行結果
> next
> test
> next

 

引入閉包

函數是一個對象,所以可以作為某個函數的返回結果。

def hello(greet):

    def setName(name):
        print(greet,name)
    return setName

Hello = hello("Good Morning")

Hello('Yang')

print(dir(Hello))

print(Hello.__closure__)

print(Hello.__closure__[0].cell_contents)

print(Hello.__name__)

print(id(Hello))

Hellob = hello("Good Afternoon")

Hellob('Yang')
print(Hello.__name__)

print(id(Hellob))

# 執行結果
#> Good Morning Yang
#> ['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
#> (<cell at 0x0000026D9A8078B8: str object at 0x0000026D9A966370>,)
#> Good Morning
#> setName
#> 1779595040560
#> Good Afternoon Yang
#> setName
#> 1779595040696

 

閉包只是在表現形式上跟函數類似,但實際上不是函數。

從代碼的結果中可以看到,閉包在運行時可以有多個實例,不同的引用環境變量(這里就是greet變量)和相同的函數(這里就是setName)組合可以產生不同的實例。

一個函數和它的環境變量合在一起,就構成了一個閉包(closure)。在Python中,所謂的閉包是一個包含有環境變量取值的函數對象。環境變量取值被保存在函數對象的__closure__屬性中。

__closure__里包含了一個元組(tuple)。這個元組中的每個元素是cell類型的對象。我們看到第一個cell包含的就是Good Morning,也就是我們創建閉包時的環境變量greet的取值。

 

Python中怎么創建閉包

 

在Python中創建一個閉包可以歸結為以下三點:

  • 閉包函數必須有內嵌函數
  • 內嵌函數需要引用該嵌套函數上一級中的變量
  • 閉包函數必須返回內嵌函數

通過這三點,就可以創建一個閉包

 

閉包實例

 

def closureFun():
    '''閉包'''
    a = 5
    def add(x):        # 1 閉包函數必須有內嵌函數
        return x + a   # 內嵌函數需要引用該嵌套函數上一級中的變量 a
    return add         # 閉包函數必須返回內嵌函數
print(locals())

c = closureFun()   # 實例化函數 closureFun  返回 函數add
sum = c(6)         # 調用add ,並傳參 ,此時返回 x + a = 6 + 5 = 11

print(sum) # 11

print(globals())

 

Python中的內建函數locals()和globals()可以用來查看不同namespace中定義的元素。

 

總結

本文介紹了如何通過Python創建一個閉包,以及Python創建的閉包是如何工作的。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM