为什么一个类的新实例会与其他实例共享成员?

Why do new instances of a class share members with other instances?

提问人:Rizwan Kassim 提问时间:11/21/2008 最后编辑:S.LottRizwan Kassim 更新时间:11/21/2008 访问量:329

问:

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

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

范围 可变

评论


答:

4赞 Rizwan Kassim 11/21/2008 #1

卫生部

我才明白为什么。

在上面的例子中,a 是一个类属性,而不是一个数据属性——这些属性由所有 Balls() 共享。注释掉 a=[] 并将其放入 init 块意味着它是一个数据属性。(而且,我当时无法使用 foo.a 访问它,无论如何我都不应该这样做。类属性的作用似乎类似于类的静态属性,它们由所有实例共享。

哇。

不过有一个问题:CodeCompletion 像这样很糟糕。在foo班上,我不能做自己。(变量),因为它不是自动定义的,而是由函数定义的。我可以定义一个类变量并将其替换为数据变量吗?

评论

0赞 Matthew Schinckel 11/21/2008
这可能取决于你的编辑......什么编辑器和平台?
0赞 ddaa 11/21/2008
请提出有关代码完成的类/实例属性的新问题。
2赞 Greg Hewgill 11/21/2008 #2

您可能想要做的是:

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

如果只使用 ,它会在函数中创建一个局部变量,该变量在函数返回时消失。赋值 to 使它成为您所追求的实例变量。a = []__init__self.a

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

1赞 S.Lott 11/21/2008 #3

“我可以定义一个类变量并将其替换为数据变量吗?”

不。它们是分开的东西。类变量在类中只存在一次。

为了简化代码完成,你可以从一些类变量开始,然后在编写类后删除这些代码行。但每次你忘记这样做,就不会有任何好事发生。

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

如果你有太多的变量,名字很长,代码完成实际上很有帮助,也许你应该让你的类更小或使用更短的名字。认真地。

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