我是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
。虽然我只是不记得,但有一个例子 - 或确认没有这样的事情 - 将是一个完美的答案。
答案 0 :(得分:5)
您已完美地总结了语义。它的工作方式是这样的:
查找对象的属性必须返回对象属性,怎么可能不会?
查找对象上的属性必须找到一个类属性,如果它不存在于对象上,因为它是对象获取方法的方式,以及在方法上定义的任何其他内容。类。
在对象上设置属性必须创建一个对象属性。
因为在Python中没有声明,创建属性的唯一方法是实际设置它,所以#3必须在对象上设置属性。
如果没有你描述的行为,我就没有办法做1到4的工作。
我不确定如何用其他语言来描述这一点。你说,"如何以OO术语来思考这个问题。"不要陷入假设某种其他语言定义" OO。对象定位在所有语言中都有所不同。
已添加:您说,
我已经预料到xa的赋值应该改变Foo.a(因为那是它所提到的那个)或者在赋值之前引用xa应该是错误(例如,"没有实例属性' a'。")。
由于Python没有声明,因此在分配属性之前,属性不会以任何方式存在。如果分配给对象上的属性没有创建对象属性,您将如何创建对象属性?也就是说,通过没有x
属性的类的示例,以及该类的实例,o.x = 17
会做什么?