为什么python类属性的语义在赋值给实例后会发生变化?

时间:2012-12-24 17:12:10

标签: python class attributes

我是Python的新手,对我看到的一些行为感到困惑。如果我定义

class Obj():
    a = 1
    b = 2

然后创建一个实例

x = Obj()
一切都很好:

print(Obj.__dict__)
print(x.__dict__)
print(x.a,Obj.a)

产生

{'a': 1, '__module__': '__main__', 'b': 2, '__doc__': None}
{}
(1, 1)

但如果我

x.a = 20

我得到了

{'a': 1, '__module__': '__main__', 'b': 2, '__doc__': None}
{'a': 20}
(20, 1)

我理解,最初,a是类变量Foo.a,最初没有实例变量a。我也明白,那时候。 x.a仅指Obj.a。我也明白,当我分配给x.a时,我创建一个实例变量x.a掩盖类变量Obj.a。但是,虽然我知道这(至少部分地)与Python的其他分配声明一致,但我很困惑为什么允许这样的类?天真的,我原本预计到x.a的作业应该改变Foo.a(因为那是它所提到的那一点)或在作业之前提到x.a应该是一个错误(例如,“没有实例属性'a'。”)。

为什么允许这种行为。什么 - 对于我们这些刚接触Python的人来说 - 这种行为是否与其他OO范例相对应?

换句话说:我无法想到你可以说x.a的任何地方,并且意味着Obj.a,然后在下一行说x.a = ...并且没有平均值Obj.a。虽然我只是不记得,但有一个例子 - 或确认没有这样的事情 - 将是一个完美的答案。

1 个答案:

答案 0 :(得分:5)

您已完美地总结了语义。它的工作方式是这样的:

  1. 查找对象的属性必须返回对象属性,怎么可能不会?

  2. 查找对象上的属性必须找到一个类属性,如果它不存在于对象上,因为它是对象获取方法的方式,以及在方法上定义的任何其他内容。类。

  3. 在对象上设置属性必须创建一个对象属性。

  4. 因为在Python中没有声明,创建属性的唯一方法是实际设置它,所以#3必须在对象上设置属性。

  5. 如果没有你描述的行为,我就没有办法做1到4的工作。

    我不确定如何用其他语言来描述这一点。你说,"如何以OO术语来思考这个问题。"不要陷入假设某种其他语言定义" OO。对象定位在所有语言中都有所不同。

    已添加:您说,

      

    我已经预料到xa的赋值应该改变Foo.a(因为那是它所提到的那个)或者在赋值之前引用xa应该是错误(例如,"没有实例属性' a'。")。

    由于Python没有声明,因此在分配属性之前,属性不会以任何方式存在。如果分配给对象上的属性没有创建对象属性,您将如何创建对象属性?也就是说,通过没有x属性的类的示例,以及该类的实例,o.x = 17会做什么?