如何在Python中为实例分配属性?

10
使用 Python,我们可以通过以下两种方法之一设置实例的属性:
>>> class Foo(object):
    pass

>>> a = Foo()
>>> a.x = 1
>>> a.x
1
>>> setattr(a, 'b', 2)
>>> a.b
2

您也可以通过属性装饰器来分配属性。

>>> class Bar(object):
    @property
    def x(self):
        return 0


>>> a = Bar()
>>> a.x
0

我的问题是,如何给一个实例分配属性?

我的直觉是尝试这样做...

>>> class Doo(object):
    pass

>>> a = Doo()
>>> def k():
    return 0

>>> a.m = property(k)
>>> a.m
<property object at 0x0380F540>

...但是,我得到了这个奇怪的属性对象。类似的实验得出了类似的结果。我猜这些属性在某些方面更接近于类而不是实例,但是我不知道内部运作得足够好,无法理解这里发生了什么。

4个回答

7
可以在类创建后动态地添加属性:
class Bar(object):
    def x(self):
        return 0

setattr(Bar, 'x', property(Bar.x))

print Bar.x
# <property object at 0x04D37270>
print Bar().x
# 0

然而,您无法在实例上设置属性,只能在类上设置。您可以使用实例来执行此操作:

class Bar(object):
    def x(self):
        return 0

bar = Bar()

setattr(bar.__class__, 'x', property(bar.__class__.x))

print Bar.x
# <property object at 0x04D306F0>
print bar.x
# 0

请参考如何动态向类添加属性?获取更多信息。


1
我非常确定他们需要这个是每个实例的。你提出的方案会影响所有实例。 - Ross Patterson
啊!比我早一分钟!!:) +1 - rubik
3
我知道,答案里已经说了。无法给实例添加属性。请参考我所链接的线程。 - agf

5

属性使用描述符,这些描述符仅适用于类,因此适用于所有实例。但是,您可以在类上使用描述符的组合,该组合将查询每个实例函数。

>>> class Foo(object):
...     @property
...     def x(self):
...         if 'x' in self.__dict__:
...             return self.__dict__['x'](self)
... 
>>> a = Foo()
>>> def k(self):
...     return 0
... 
>>> a.__dict__['x'] = k
>>> a.x
0

1
您可以直接将属性分配给类对象:
>>> class Foo(object):
    pass    
>>> a = Foo()
>>> a.__class__
__main__.Foo    
>>> setattr(a.__class__, 'm', property(lambda self: 0))
>>> a.m
0 
>>> a.m = 24
AttributeError: can't set attribute

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接