2013-06-21 112 views
0

我在Python 2.7倍在python中动态设置实例属性/ memoized属性?

class Example(object): 
    a = None 
    b = None 
    c = None 

现有示例类和现有的实例

anInstance = Example() 
anInstance.a = 100 
anInstance.b = 200 
anInstance.c = 300 

我已经重构/清理一些代码,而且它现在已经知道,anInstance.c是一个昂贵的操作这很少使用。

在一个完美的世界里,我只想做:

class Example(object): 
    _c = None 
    @property 
    def c(self): 
     if self._c is not None: 
      self._c = DO EXPENSIVE STUFF HERE 
     return self._c 

的问题是,我不能改变class Example现在。 [所以quickfix将它设置为一个函数,并将每个obj.c更改为obj.c()]

据我所知,没有任何方法可以动态分配属性/记忆,除非我改变对象。这种理解是否正确?我期待在这里失望,我只是想要确认。

+0

当然,如果'obj.c'不是一个属性,那么它将在'Example .__ init__'中计算,在这种情况下,您必须修改'Example'?否则,为什么要使它成为一个财产改变什么? – katrielalex

+0

这是来自处理用户状态的webapp的一部分代码。 __init__只是设置占位符值。只有少数的请求才能有条件地计算出这个状态;这个特定的属性需要更少的次数。我没有写/设计这部分。我正在尝试修复它。尽管我想把所有的东西都拿出来,但这不是一种选择。 –

回答

4

你可以在事后改变Python类:

@property 
def c(self): 
    if self._c is None: 
     self._c = DO EXPENSIVE STUFF HERE 
    return self._c 

Example.c = c 
Example._c = None 

现在你已经添加了一个属性c到类,以及添加_c属性。

当然,您可能需要覆盖该类上假定可以分配给self.c的任何现有方法。

动态添加或替换对象属性的过程通常称为Monkey Patching

+0

当然,如果可以修改实例化'Example'的代码,最好从'Example'继承并创建子类实例。 – Marcin

+0

@Marcin:在这一点上,你需要修改引入'Example'的代码。 –

+0

如果不修改monkeypatching,则不能修改。如果创建'Example'实例的地方数量有限,那么只需要修改这些实例即可。 – Marcin