例如,这段代码是Python:
a = object()
a.b = 3
投 AttributeError: 'object' object has no attribute 'b'
但是,这段代码:
class c(object): pass
a = c()
a.b = 3
很好。当类x没有该属性时,为什么我可以分配属性b?如何让我的类只定义属性?
例如,这段代码是Python:
a = object()
a.b = 3
投 AttributeError: 'object' object has no attribute 'b'
但是,这段代码:
class c(object): pass
a = c()
a.b = 3
很好。当类x没有该属性时,为什么我可以分配属性b?如何让我的类只定义属性?
该 object
type是一个用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中真正想做的事情。如果你的类的用户想要在类的实例上存储一些额外的属性,那么没有理由不让它们,实际上你可能想要的原因很多。
你可以覆盖的行为 __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]
=值。在这种情况下,你应该覆盖 __dict__
方法也是。
Python通常允许您在任何对象上设置任何属性。这是一个特例 object
阶级行为不同。在C中也实现了一些类似的模块。
如果你 想 你的对象表现得像这样,你可以定义一个 __setattr__(self, name, value)
显式执行a的方法 raise AttributeError()
如果您尝试设置不在“已批准列表”上的成员(请参阅 http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/389916)
创建一个 object
实例没有任何功能。因此,在基础的实例上设置属性 object
类型明确禁用。您必须将其子类化才能创建属性。
提示:如果您想要一个简单的对象用作存储属性的东西,您可以通过创建一个匿名函数来实现 lambda
。作为对象的函数也能够存储属性,因此这是完全合法的:
>>> a = lambda: None
>>> a.b = 3
>>> a.b
3
这是因为当你说的时候 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。