2016-01-11 21 views
1
class MyClass(object): 
    class_var = [] 
    def __init__(self, i_var): 
     self.i_var = i_var 

a = MyClass(2) 
a.hit = 1 
print a.hit 

如我们所见,hit作为初始化后的一个实例变量被添加到a。 允许以这种方式定义实例变量的好理由是什么?而且,危险吗?为什么Python允许在初始化后添加实例变量?

+1

在python中,你也可以动态地添加函数方法。这里是你可能会感兴趣的东西[what-is-a-metaclass-in-python](http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python)答案“类和对象“给出了一个安静的好概况! – keksnicoh

回答

4

允许以这种方式定义实例变量的好理由是什么?

我认为需要注意的是self__init__函数内部是完全一样在该实例上的任何其他方法self是很重要的。这与班级以外的a相同。 __init__方法的神奇之处在于当被调用时,而没有其他东西(这是所有真正的python魔术方法)。要让__init__以某种方式“冻结”对象,将会违背python中一直采用的方式。

所以,我会说“好理由”是因为它使事情非常一致。

而且,危险吗?

是的。有可能。

故意添加方法的实践/属性实例被称为猴修补(也被称为偶尔冲鸭) - 它真的不应该这样做,除非你没有其他任何选项。

无意中的做法将方法/属性添加到实例称为创建错误(我们已经完成了它:-)。

幸运的是,有工具可以帮助您防止这些类型的错误。 Linters是最常见的。我个人使用pylint来帮助我警告我这些类型的错误。

在linter和使用常识(见上面有关不Monkey Scatch)之间,由于python的意识形态的这部分,我很少遇到难以追踪的bug。

我想如果你在后面的实例方法中添加更多的属性,它不是鸭子冲 - 但你可能不应该这样做。 。 。

2

“为什么?”没有好的答案。题。这是Python思想体系的一部分。 Python结合了来自几种不同编程范例的元素,以适应不同的编码风格。你可以编写功能性的,纯粹的面向对象的,结构化的(如果你年老而不是非常明亮),或者甚至是事件驱动,如果你想变得更加花哨和异步。它本质上并不危险,但是像许多其他语言一样,它允许你用自己的脚来拍摄自己(也可能是其他开发团队的成员)。

相关问题