我刚开始学习python,我很困惑为什么我能够做到这一点。有人请解释为什么这有效:
class foo():
@property
def hello(self):
return "hello world"
if __name__ == '__main__':
cli = foo()
cli.foo2 = 3
print cli.hello #prints hello world
print cli.foo2 #prints 3
对我来说,我能够创建一个新属性并在原始类中不存在时分配一个值是没有意义的。有没有办法防止这种行为,或者有人至少可以解释这背后的逻辑?
-edit-我很高兴知道这是python中对象的正常行为,而我并没有做错事。它只是感觉不对,因为我通常在VBA和C#中工作。根据其他人在下面的答案中所说的,我认为添加插槽可以防止以这种方式将任何内容添加到课程中,但也许我不理解。
class foo():
@property
def hello(self):
return "hello world"
__slots__ = []
if __name__ == '__main__':
cli = foo()
cli.foo2 = 3
print cli.hello #prints hello world
print cli.foo2 #prints
答案 0 :(得分:3)
一个主要原则是没有宣言这样的东西。也就是说,你永远不会声明“这个类有一个方法foo”或“这个类的实例有一个属性栏”,更不用说关于要存储在那里的对象类型的声明了。您只需定义一个方法,属性,类等,然后添加它。正如JBernardo指出的那样,任何
__init__
方法都会做同样的事情。任意限制创建名为__init__
的方法的新属性是没有多大意义的。并且有时将__init__
函数存储为实际上没有该名称的函数(例如装饰器)是有用的,并且这样的限制会破坏它。现在,这并非普遍适用。内置类型将此功能省略为优化。通过
__slots__
,您还可以在用户定义的类上禁止此操作。但这只是一个空间优化(不需要每个对象的字典),而不是正确的东西。如果你想要一个安全网,那么太糟糕了。 Python没有提供一个,你不能合理地添加一个,最重要的是,它会被拥抱该语言的Python程序员所避开(阅读:几乎所有你想要使用的程序员)。测试和纪律,仍然有很长的路要走,以确保正确性。如果可以避免,则不要使用自由构成
__init__
之外的属性,并进行自动化测试。由于这样的欺骗,我很少有AttributeError
或逻辑错误,并且在那些发生的情况下,几乎所有都被测试捕获。
答案 1 :(得分:0)
这是python对象的预期行为,您可以在创建它们时添加属性等。但是,您可以通过执行以下操作来限制该行为:
class foo():
__slots__ = []
@property
def hello(self):
return "hello world"
这个__slots__
变量是让你的类不可变的一种方法,所以你不能为它添加属性,否则python类通常表现得像你在问题中描述的那样
另一种选择是覆盖设置和删除属性的方法,例如
def __setattr__(self, *args):
raise TypeError
def __delattr__(self, *args):
raise TypeError