2015-10-14 74 views
1

我有一個裝飾器,它只是緩存返回值(在我的示例中稱爲@cached),我希望將它與@property結合使用。這通常工作正常。我遇到的問題出現在我嘗試使用由@cached添加的expire屬性。獲取python屬性的屬性

def cached(f): 
    cache = [None] 

    def inner(*args, **kwargs): 
     if cache[0]: 
      cache[0] = f(*args, **kwargs) 
     return cache[0] 

    def expire(): 
     cache[0] = None 

    inner.expire = expire 
    return inner 

class Example(object): 
    @property 
    @cached 
    def something_expensive(self): 
     print("expensive") 
     return "hello" 


e = Example() 
e.something_expensive 
e.something_expensive.expire() 

我如何才能訪問expire函數?在被@property取代之後添加到該功能中。我明白爲什麼這不起作用我對解決該問題的方式感興趣。

一些限制:

  • 我不能改變@cached裝飾它在圖書館,我不控制
  • 我真的不想刪除@property,因爲我想在我的單元測試到期,他們做我的代碼更好用。

一個解決方案,我認爲是相當糟糕的是(因爲在現實中,我有很多的屬性,我想做到這一點的):

class Example(object): 
    @cached 
    def _something_expensive(self): 
     return "hello" 

    @property 
    def something_expensive(self): 
     return self._something_expensive() 

回答

2

您可以使用類字典訪問:

type(e).__dict__['something_expensive'].fget.expire() 

一般而言e.something_expensive相當於:

type(e).__dict__['something_expensive'].__get__(e, type(e)) 

有關詳細信息讀了起來:Descriptor HowTo Guide

注意,expiry功能你不從外部功能cached功能None設置cache裏面,你只需創建一個新的局部變量。您可能需要做這樣的事情:

def expire(): 
    del cache[:] 
    cache.append(None) 

在Python 3中使用nonlocal關鍵字更新cache更簡單。

+0

非常感謝,我感謝幫助。緩存=無是一個打字錯誤的修復 – Nick