簡體   English   中英

對Python閉包感到困惑

[英]Confused about Python closures

在Mark Lutz的“學習Python第5版”中 - (ISBN:9781449355739,第17章:“范圍”,第518頁,側欄:“你為什么要關心:自定義開放”) - 如下圖所示:

import builtins

def makeopen(id):
    original = builtins.open
    def custom(*kargs, **pargs):
        print('Custom open call %r:' % id , kargs, pargs)
        return original(*kargs, **pargs)
    builtins.open = custom

makeopen('spam')
F = open('script2.py')

makeopen('eggs')
F = open('script2.py')

預期產量:

Custom open call 'spam': ('script2.py',) {}
Custom open call 'eggs': ('script2.py',) {} 

實際產量:

Custom open call 'spam': ('script2.py',) {}
Custom open call 'eggs': ('script2.py',) {} 
Custom open call 'spam': ('script2.py',) {}

我對閉包的理解是它們應該返回多個每次調用的可變數據(即,像其他語言中的實例變量)。

那么為什么“垃圾郵件”會被打印兩次?

我已經使用PyCharm調試器逐步完成了代碼,但我仍然不理解它。

是因為變量original指向內置范圍中的對象而不是封閉范圍?

更新:

我認為問題是在第二次調用makeopen() ,變量original遞歸指向custom() 也許它原本打算作為一個“功能”:/ ...但我傾向於認為這是一個可怕的例子。

這是一個按預期工作的解決方案:

import builtins

def makeopen(id):
    def custom(*kargs, **pargs):
        print('Custom open call %r:' % id , kargs, pargs)
        return builtins.open(*kargs, **pargs)
    return custom

file = 'script2.py'

f = makeopen('spam')
f(file)

g = makeopen('eggs')
g(file)

注意:上述解決方案實際上並沒有改變builtins.open ,而是充當包裝器。

makeopen('spam')open是一個打印“垃圾郵件”然后打開文件的功能。 makeopen('eggs')open現在是一個打印“eggs”的函數,然后調用打印“spam”然后打開文件的函數。

您已經在越來越多的層中連續打包open函數,最終得到:

print("eggs")
↳ print("spam")
  ↳ open(...)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM