为什么 Python 允许在初始化后添加实例变量?

Why does Python allow instance variables to be added after initialization?

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中。 允许以这种方式定义实例变量的充分理由是什么?还有,危险吗?

我觉得正好符合''we are all responsible users''的python原则。看这里:http://docs.python-guide.org/en/latest/writing/style/

What's a good reason to allow defining instance variable in such a way?

我认为重要的是要注意 __init__ 函数中的 self 与该实例的任何其他方法中的 self 完全相同。它也与 class 之外的 a 相同。 __init__ 方法的魔力在于 when 它被调用而不是其他(all python魔术方法)。 __init__ "freeze" 对象以这样或那样的方式将违背 python.

中一直做事的方式

所以,我会说 "good reason" 是因为它使事情非常一致。

And, is it dangerous?

是的。可以。

有意将methods/attributes添加到实例的做法称为 Monkey Patching(有时也称为 Duck Punching)1 -- 除非你没有任何其他选择,否则真的不应该这样做。

无意 将 methods/attributes 添加到实例的做法被称为制造错误(我们都这样做过 :-)。

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

在 linter 和使用常识之间(参见上面关于非 Monkey Patching 的内容),由于 python 的意识形态的这一部分,我很少遇到 hard-to-track 错误。

1我想如果你在后面的实例方法中添加更多的属性,那不是鸭子打孔——但你可能不应该这样做那要么。 . .

"why?" 问题没有好的答案。这是 python 意识形态的一部分。 Python 合并了来自几种不同编程范例的元素以适应不同的编码风格。您可以编写函数式的、纯面向对象的、结构化的(如果您年纪大而且不是很聪明),或者如果您想要更加花哨和异步,甚至可以编写事件驱动的。它本身并不危险,但就像许多其他语言的优点一样,它确实会让你搬起石头砸自己的脚(也可能是开发团队的其他成员)。