使用按实例级别而不是按类定义的属性

Qas*_*imK 1 python properties python-2.6

我想要实现的是这样的:

class object:
    def __init__(self):
        WidthVariable(self)

        print self.width
        #Imagine I did this 60frames/1second later
        print self.width

#output:
>>0
>>25
Run Code Online (Sandbox Code Playgroud)

我想要发生的事情(如上所述):WidthVariable创建类时,它将变量添加width到对象实例。该变量的行为类似于常规属性,但是在这种特殊情况下,它是只读的(仅fget设置了变量)。另外,fget调用定义的函数WidthVariable决定width返回什么。

但是,我不知道该怎么做!我使用常规属性进行了尝试,但发现它们仅适用于类,而不适用于每个实例-请注意,我使用的代码应与上述代码尽可能相似(即,__init__of中的代码WidthVariable应设置width变量,而无其他地方) 。而且,self.width不能成为函数,因为我没有self.width()想要的名字self.width(因为它与我拥有的其余设计保持一致)。

需要说明的是,完整的代码如下所示:

class MyObject:
    def __init__(self)
        WidthVariable(self)
        print self.width

class WidthVariable:
    def __init__(self, object)
        object.width = property(self.get_width)

    def get_width(self):
        value = #do_stuff
        return value #The Value

#output:
>>25 #Whatever the Value was
Run Code Online (Sandbox Code Playgroud)

Ale*_*lli 5

正如@Jonathan所说,由于描述符(包括属性)是按类而不是按实例的,因此获取不同的按实例描述符的唯一方法是使每个实例都具有自己的类。就元编程而言,这是很浅且容易的;-)...:

class Individualistic(object_or_whatever_bases):
  def __init__(self, whatever_args):
    self.__class__ = type('GottaBeMe', (self.__class__, object), {})
    # keep rocking...!-)
Run Code Online (Sandbox Code Playgroud)

我还object明确添加了它,因为它是2.*使类成为新类型所必需的(在Python中,您确实说的是!)。不再使用传统类,它们在属性和其他方面都不正确(并且为了向后兼容,它们不能-在Python 3中,传统类最终被淘汰,因此每个类都是新样式,没有要求再显式继承自对象!)。

现在,放置的任何描述符self.__class__.__dict__将只影响此一个实例,而不会影响其他实例。有一些开销(每个GottaBeMe类,因此每个实例都有自己的__dict__,等等),但是没有什么太可怕了。

现在,满足原始请求所需要做的就是更改:

class WidthVariable:
    def __init__(self, object)
        object.width = property(self.get_width)
Run Code Online (Sandbox Code Playgroud)

(还应object合理地重命名arg以避免踩踏内置模块,并使类变为新样式,因为您应始终使每个类都变为新样式;-),以便:

class WidthVariable(object):
    def __init__(self, obj)
        obj.__class__.width = property(self.get_width)
Run Code Online (Sandbox Code Playgroud)

如您所见,没有什么黑魔法般的!-)