2012-02-05 56 views
2
class A: 
    def f(self): 
    print('f') 
    def g(self): 
    print('g') 
    def h(self): 
    print('h') 

x = A() 
y = A() 
x.f = x.g # creates a new attribute 'f' for x 
x.f() # 'g'; resolves at the instance attribute level to call instance method 'g' 
y.f() # 'f'; instance methods are unaffected 
A.f = A.h # redefines instance method 'f' to print 'h' 
x.f() # 'g'; still resolves at the attribute level to call instance method 'g' 
y.f() # 'h'; instance method 'f' now prints 'h' 
A.g = A.h # redefines instance method 'g' to print 'h' 
x.f() # 'g'; still calls the old instance method 'g' because it kept the link to it 
y.f() # 'h' 

我的理解是否正確?替換實例方法

我想通過以下方式來使用:

class Attributes: 
    def __init__(self, params, cache_field = None): 
     # ... 
     self.cache_field = cache_field 
     if cache_field is None: 
     # I hope I'm setting instance attribute only 
     self.check_cache = self.check_external_cache 
     else: 
     self.check_cache = self.check_internal_cache 
     self.internal_cache = {} 

    def check_internal_cache(self, record): 
     return self.internal_cache[record.id] 

    def check_external_cache(self, record): 
     return record[self.cache_field] 

    def calculate_attributes(self, record): 
     try: 
     return self.check_cache(record) # I hope it will resolve to instance attribute 
     except KeyError: 
     # calculate and cache the value here 
     # ... 

將這工作是否正確?這樣做可以嗎?最初我希望節省時間,與每次致電calculate_attributes時檢查self.cache_field;但我不再確定它會節省時間。

回答

3

我認爲這裏的基本思想是正確的,並有一些小的更正。首先,

A.f = A.h # redefines instance method 'f' to print 'h' 

這應該讀方法,而不是實例方法。你在這裏改變課程。第二,這不符合任何在這裏定義的變量:

if cache is None: 

我想也許你的意思cache_field

一般來說,在__init__中設置實例屬性是完全正常和可接受的。這並不重要,這是一種方法,而不是某種其他類型的對象 - 與self.foo = 'bar'的說法沒有什麼不同。

此外,有時這取決於,但一般來說,設置init中的方法確實比每次調用check_cache時測試cache_field都快。

+2

我會補充一點,我也認爲它可以接受重新分配一個實例方法,即使在__init__之外。一個例子是使用實例方法作爲處理程序的通用回調,但回調可以根據狀態進行更改。 – jdi 2012-02-05 04:11:42

+0

是的,它是'cache_field',而不是'cache'。更新......是否有任何鏈接總結了改變方法的良好用例(在__init__之內或之外)? – max 2012-02-05 04:13:32

+0

有一點需要記住的是,這會創建一個影響對象生命週期的引用循環。 – yak 2012-02-05 07:38:03