如何在Python中为实例赋值属性?

10 投票
4 回答
6623 浏览
提问于 2025-04-16 23:56

在使用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 个回答

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

想了解更多信息,可以查看 如何动态地给类添加属性?

撰写回答