亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

有沒有辦法訪問用裝飾器定義的 Python 函數的命名空間?

有沒有辦法訪問用裝飾器定義的 Python 函數的命名空間?

一只斗牛犬 2021-07-22 18:15:16
假設我使用緩存裝飾器來定義一個新函數,如下所示:def cached(funcy):    cache = dict()    def cache_funcy(x):        if x in cache:            return cache[x]        else:            print cache            result = funcy(x)            cache[x] = result            return result    return cache_funcy@cacheddef triple(x):    return 3*x調用該函數triple四次會產生以下輸出:>>> triple(1){}3>>> triple(2){1: 3}6>>> triple(2)6>>> triple(4){1: 3, 2: 6}12我的理解是該函數triple可以訪問本地調用的字典,cache因為該字典存在于triple定義的名稱空間中。該字典在外部全局范圍內不能直接訪問。是否可以cache通過函數的某種屬性訪問該字典triple?注意:我想知道是否可以在不顯式創建cache屬性的情況下執行此操作,triple例如cache_funcy.cache = cache在cached.
查看完整描述

1 回答

?
catspeake

TA貢獻1111條經驗 獲得超0個贊

實際上,這個 dict 并沒有存儲在函數的本地命名空間中,它是一個自由變量,所以它存儲在函數閉包中。在 Python 2 中,請考慮:


In [1]: def cached(funcy):

   ...:     cache = dict()

   ...:     def cache_funcy(x):

   ...:         if x in cache:

   ...:             return cache[x]

   ...:         else:

   ...:             print cache

   ...:             result = funcy(x)

   ...:             cache[x] = result

   ...:             return result

   ...:     return cache_funcy

   ...:

   ...: @cached

   ...: def triple(x):

   ...:     return 3*x

   ...:


In [2]: triple(1)

{}

Out[2]: 3


In [3]: triple(2)

{1: 3}

Out[3]: 6

現在:


In [5]: triple.func_closure

Out[5]:

(<cell at 0x10e4e7be8: dict object at 0x10e7ec910>,

 <cell at 0x10e7b2590: function object at 0x10e81ede8>)

第一個單元格包含dict,第二個單元格包含正在裝飾的函數(它也是一個自由變量)。因此,您可以使用:


In [6]: triple.func_closure[0].cell_contents

Out[6]: {1: 3, 2: 6}


In [7]: triple.func_closure[0].cell_contents[2] = 'foo'


In [8]: triple(2)

Out[8]: 'foo'

注意,Python 3中函數的屬性有點不同,這里有一個直接的屬性__closure__,所以:


In [4]: triple.__closure__

Out[4]:

(<cell at 0x1026dbc78: dict object at 0x1028d1bd0>,

 <cell at 0x1026dbf48: function object at 0x1028e59d8>)

實際上,在 Python 2 中,自 Python 2.6 起,添加了這些下劃線屬性是為了向前兼容,因此除非您使用的是低于 Python 2.6 的版本,否則該屬性也存在。


因此,出于兼容性原因,您可能應該使用 __closure__


查看完整回答
反對 回復 2021-07-28
  • 1 回答
  • 0 關注
  • 196 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號