可以设置Python对象的任何属性

时间:2011-05-02 20:34:16

标签: python class object properties

例如,此代码是Python:

a = object()
a.b = 3

抛出AttributeError: 'object' object has no attribute 'b'

但是,这段代码:

class c(object): pass
a = c()
a.b = 3

很好。当类x没有该属性时,为什么我可以分配属性b?如何让我的类只定义属性?

5 个答案:

答案 0 :(得分:12)

object类型是用C编写的内置类,不允许您向其添加属性。它已被明确编码以防止它。

在自己的类中获得相同行为的最简单方法是使用__slots__属性来定义要支持的确切属性的列表。 Python将为这些属性保留空间,不允许任何其他属性。

class c(object):
    __slots__ = "foo", "bar", "baz"

a = c()

a.foo = 3  # works
a.b   = 3  # AttributeError

当然,这种方法有一些注意事项:你不能腌制这样的对象,而且期望每个对象都具有__dict__属性的代码会破坏。 “更多Pythonic”的方式是使用另一张海报所示的自定义__setattr__()。当然,有很多方法可以解决这个问题,并且无法设置__slots__(除了子类化和将属性添加到子类之外)。

一般来说,这不是你应该在Python中真正想做的事情。如果你的类的用户想要在类的实例上存储一些额外的属性,那么就没有理由不让它们出现,实际上你可能想要的原因很多。

答案 1 :(得分:3)

您可以像这样覆盖__setattr__魔法的行为。

class C(object):
    def __setattr__(self, name, value):
        allowed_attrs = ('a', 'b', 'c')
        if name not in allowed_attrs:
            # raise exception
            # or do something else
            pass
        self.__dict__[name] = value

当然,这只会阻止您设置a.b(点形式)等属性。您仍然可以使用a.__dict__[b] = value设置属性。在这种情况下,您也应该覆盖__dict__方法。

答案 2 :(得分:2)

Python通常允许您在任何对象上设置任何属性。这是object类的行为不同的特殊情况。还有一些在C中实现的模块,其行为类似。

如果希望您的对象的行为如此,那么您可以定义一个__setattr__(self, name, value)方法,如果您尝试设置一个不在其上的成员,则明确执行raise AttributeError() “核准清单”(见http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/389916

答案 3 :(得分:0)

创建object实例没有任何功能。因此,明确禁用在基本object类型的实例上设置属性。您必须将其子类化才能创建属性。

提示:如果您希望将简单对象用作存储属性的内容,则可以通过使用lambda创建匿名函数来实现。作为对象的函数也能够存储属性,因此这是完全合法的:

>>> a = lambda: None
>>> a.b = 3
>>> a.b 
3

答案 4 :(得分:-1)

这是因为当你说a.b = 3时,它会在表示b的变量中创建一个变量。例如,

class a: pass
print a.b

返回AttributeError: class a has no attribute b

但是这段代码,

class a: pass
a.b = 3
print a.b

返回3,因为它将a的b值设置为3。