1

我刚开始学习 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 
4

2 回答 2

3

来自比我更聪明的人

一个主要原则是没有声明这样的东西。也就是说,你永远不会声明“这个类有一个方法 foo”或“这个类的实例有一个属性 bar”,更不用说声明要存储在那里的对象的类型了。您只需定义一个方法、属性、类等,它就会被添加。正如 JBernardo 指出的那样,任何__init__方法都做同样的事情。将新属性的创建任意限制为 name 的方法没有多大意义__init__。有时存储一个__init__实际上没有该名称的函数(例如装饰器)很有用,而这样的限制会破坏这一点。

现在,这并非普遍正确。内置类型省略了此功能作为优化。通过__slots__,您还可以在用户定义的类上防止这种情况。但这仅仅是空间优化(不需要每个对象都有字典),而不是正确性。

如果你想要一个安全网,那么,太糟糕了。Python 没有提供一个,而且你不能合理地添加一个,最重要的是,拥抱该语言的 Python 程序员会避开它(阅读:几乎所有你想与之合作的人)。测试和纪律,对于确保正确性还有很长的路要走。__init__ 如果可以避免的话,不要随意编造属性,做自动化测试。由于这样的诡计,我很少AttributeError遇到逻辑错误,而且在发生的那些错误中,几乎所有错误都被测试捕获了。

于 2013-06-27T04:23:47.987 回答
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
于 2013-06-27T04:23:55.970 回答