2013-06-27 275 views
1

我刚开始学习python,对于为什么我能够做到这一点,我很困惑。会有人请解释为什么这个工程: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

我试过这种方法,它并没有为我工作(如预期) - 既不cli.foo也不cli.foo2被定义为。 –

+0

@AMADANON:这有点奇怪。 [它适用于我](http://键盘。org/U5XOZL5c),以及OP和其他。 – icktoofay

+0

它已被编辑/修复 - 我仍然在我的终端窗口中剪切和粘贴:) –

回答

3

smarter person than me

一个主要原则是,有没有这样的事,作为一个声明。也就是说,你永远不会声明“这个类有一个方法foo”或“这个类的实例有一个属性栏”,更不用说在这里存储对象的类型。您只需定义一个方法,属性,类等,并添加它。正如JBernardo所指出的,任何方法都可以做同样的事情。任意限制创建名称为__init__的方法的新属性没有多大意义。有时候存储函数__init__这个函数实际上并没有这个名字(例如装饰器),这样的限制会打破这个限制。

现在,这并不普遍。内建类型忽略了这一功能作为优化。通过__slots__,您也可以在用户定义的类上阻止此操作。但这仅仅是一个空间优化(不需要为每个对象使用字典),而不是正确的事情。

如果你想要一个安全网,太糟糕了。 Python不提供它,你不能合理地添加一个,最重要的是,它会被接受该语言的Python程序员避开(阅读:几乎所有你想要使用的语言)。测试和纪律,仍然需要很长时间才能确保正确性。如果可以避免并自动测试,请不要使用自由来弥补__init__以外的属性。我很少有一个AttributeError或逻辑错误,因为这样的诡计,而那些发生的事情,几乎全部都被测试抓住了。

+0

我想我会接受这是正常的行为,然后继续前进。 – Ripster

0

这是python对象的预期行为,您可以在创建它们时添加属性等。你可以,但是,这样做限制行为:

class foo(): 
    __slots__ = [] 
    @property 
    def hello(self): 
     return "hello world" 

__slots__变量就是让你的类不变的,所以你不能属性添加到它,否则蟒蛇类典型的表现就像你在你的问题中描述的一种方式

另一种选择是覆盖设置和删除属性,这样

def __setattr__(self, *args): 
    raise TypeError 
def __delattr__(self, *args): 
    raise TypeError 
+0

即使在添加'__slots__ = []'后,我也能够正常运行代码。不知道我是否误解了插槽应该如何工作? – Ripster

+0

@Ripster它应该按原样工作,所以我应该发布的其他解决方案 – Stephan