2010-04-25 77 views
1
>>> class Abcd: 

...  a = '' 
...  menu = ['a', 'b', 'c'] 
... 
>>> a = Abcd() 
>>> b = Abcd() 
>>> a.a = 'a' 
>>> b.a = 'b' 
>>> a.a 
'a' 
>>> b.a 
'b' 

这都是正确的,每个对象都有自己的“A”,但是......Python。奇怪的类属性的行为

>>> a.menu.pop() 
'c' 
>>> a.menu 
['a', 'b'] 
>>> b.menu 
['a', 'b'] 

这怎么可能发生? 以及如何使用列表作为类属性?

+0

你肯定不是第一次遇到这样的。我记得第一次碰到这个问题:花了我几天的时间才弄清楚问题所在。一旦你了解它是有道理的,但我个人认为这真的很不直观。 – 2010-04-25 07:48:25

+0

@musicfreak:我真的不明白为什么人们会为此感到困惑。通过查看任何教程中的任何OO示例,您都可以了解这一点。为什么有人宁愿浪费“时间”,而不是投入几个小时来阅读教程,这超出了我的想象。 – nikow 2010-04-25 11:56:04

+0

-1:有很多重复的。 – nikow 2010-04-25 11:57:03

回答

7

这是因为您初始化menu属性的方式是将所有实例设置为指向同一个列表,而不是具有相同值的不同列表。

相反,使用类的__init__成员函数初始化值,从而创建一个新的列表,并指派该列表的财产类的特定实例:

class Abcd: 
    def __init__(self): 
     self.a = '' 
     self.menu = ['a', 'b', 'c'] 
+0

但是,简单的字符串属性和列表属性之间的区别? 为什么? – Eugene 2010-04-25 07:23:41

+1

因为它是参考和值之间的差异。如果你做了'a.menu = ['a','b']',那么'b.menu'将保持不变 - 但你不是,你正在改变由'a指向*的列表*。 menu'。 – Amber 2010-04-25 07:28:50

4

class-objects教程,并注意使用self

使用实例的属性,而不是类属性(也,新式类):

>>> class Abcd(object): 
...  def __init__(self): 
...   self.a = '' 
...   self.menu = ['a','b','c'] 
...   
>>> a=Abcd() 
>>> b=Abcd() 
>>> a.a='a' 
>>> b.a='b' 
>>> a.a 
'a' 
>>> b.a 
'b' 
>>> a.menu.pop() 
'c' 
>>> a.menu 
['a', 'b'] 
>>> b.menu 
['a', 'b', 'c'] 
>>> 
+0

您可能想要注意,所有类都是Python 3.0+行中自动添加新类的类。 – 2010-04-25 07:24:08

0

因为在Python变量只是 “标签”

两个Abcd.menu和a.menu引用同一个列表对象。

你的情况,你应该标签分配给新的对象

不修改对象就地。

您可以运行,而不是

a.menu = a.menu[:-1] 

a.menu.pop() 

感觉不一样