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

时间:2011-08-19 06:45:09

标签: python attributes properties instance variable-assignment

使用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 个答案:

答案 0 :(得分:4)

可以在已经创建的类中动态添加属性:

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

有关详细信息,请参阅How to add property to a class dynamically?

答案 1 :(得分:3)

属性使用descriptors,它只适用于类,因此 对于所有情况。但是你可以使用描述符的组合 一个可以查询每个实例函数的类。

>>> 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

答案 2 :(得分: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

答案 3 :(得分:0)

这里我们采用了@ agf的解决方案,并使用lambda函数来定义类属性。

class A(object):
    pass

a = A()
a.__class__.f = property(lambda self: 57)
a.f  # 57

以下帖子提供了更多背景信息:https://crosscompute.com/n/jAbsB6OIm6oCCJX9PBIbY5FECFKCClyV/_/Assign%20a%20class%20property%20to%20an%20instance