3

我是 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。虽然我只是不记得了,但有可能,一个例子 - 或者确认没有这样的事情 - 将是一个完美的答案。

4

1 回答 1

5

您已经完美地总结了语义。它是这样工作的,因为:

  1. 在对象上查找属性必须返回对象属性,怎么可能不呢?

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

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

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

如果没有您描述的行为,我看不出有一种方法可以使 1 到 4 工作。

我不确定如何用其他语言来描述这一点。你说,“如何用面向对象的术语来思考这个问题。” 不要陷入假设某些其他语言“定义”OO 的陷阱。在所有语言中,面向对象的方式都不同。

补充:你说,

我本来希望对 xa 的赋值应该改变 Foo.a (因为这就是它所指的那个点)或者在赋值之前引用 xa 应该是一个错误(例如,“没有实例属性'一个'。”)。

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

于 2012-12-24T17:19:58.310 回答