2012-02-05 59 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