2
class Ball:
  a = []
  def __init__(self):
    pass

  def add(self,thing):
    self.a.append(thing)

  def size(self):
    print len(self.a)

for i in range(3):
  foo = Ball()
  foo.add(1)
  foo.add(2)
  foo.size()

我希望回报:

2
2
2

但我得到:

2
4
6

为什么是这样?我发现通过在init中执行 a=[] ,我可以绕过这种行为,但我不太清楚为什么。

4

3 回答 3

4

多哈

我才知道为什么。

在上述情况下,a 是类属性,而不是数据属性——所有 Balls() 共享这些属性。注释掉 a=[] 并将其放入init块意味着它是一个数据属性。(而且,那时我无法使用 foo.a 访问它,无论如何我都不应该这样做。)看起来类属性就像类的静态属性一样,它们被所有实例共享。

哇。

不过有一个问题:CodeCompletion 很烂。在 foo 类中,我不能做 self.(variable),因为它不是自动定义的——它是由函数定义的。我可以定义一个类变量并用数据变量替换它吗?

于 2008-11-21T03:27:46.577 回答
2

您可能想要做的是:

class Ball:
  def __init__(self):
    self.a = []

如果你使用 just a = [],它会在函数中创建一个局部变量,__init__当函数返回时它会消失。分配给self.a它使其成为您所追求的实例变量。

对于半相关的问题,请参阅如何更改未来调用者的默认参数值

于 2008-11-21T03:47:25.070 回答
1

“我可以定义一个类变量并用数据变量替换它吗?”

不,它们是不同的东西。一个类变量只存在一次——在类中。

你可以——为了巧妙地完成代码——从一些类变量开始,然后在你编写完你的类之后删除这些代码行。但每次你忘记做那件事,什么好事都不会发生。

更好的是尝试不同的 IDE。 Komodo Edit的代码完成似乎是明智的。

如果你有这么多的变量名称很长以至于代码完成实际上很有帮助,也许你应该让你的类更小或使用更短的名称。严重地。

我发现当你到达一个代码完成比烦人更有帮助的地方时,你已经超过了“把它全部放在我的大脑中”的复杂性阈值。如果这门课不适合我的大脑,那就太复杂了。

于 2008-11-21T11:20:14.313 回答