列出作为python类的成员,为什么它的内容在类的所有实例之间共享?

时间:2012-03-17 16:13:19

标签: python

我已经定义了一个类Listener并创建了一个Listener个对象的字典。每位听众都有id来识别他们,以及他们收听的artists列表,artists = []。向artists列表添加内容会为Listener类的所有实例添加内容,而不是引用的实例。这是我的问题。

Listener类定义如下:

class Listener:
    id = ""
    artists = []

    def __init__(self, id):
        self.id = id

    def addArtist(self, artist, plays):
        print self.id # debugging...
        print "pre: ", self.artists
        self.artists.append(artist)
        print "post: ", self.artists

这是我的调试测试代码:

def debug():
    listeners = {}
    listeners["0"] = Listener("0")
    listeners["1"] = Listener("1")

    listeners["0"].addArtist("The Beatles", 10)
    listeners["0"].addArtist("Lady Gaga", 4)
    listeners["1"].addArtist("Ace of Base", 5)

输出:

0
pre:  []
post:  ['The Beatles']
0
pre:  ['The Beatles']
post:  ['The Beatles', 'Lady Gaga']
1
pre:  ['The Beatles', 'Lady Gaga']
post:  ['The Beatles', 'Lady Gaga', 'Ace of Base']

我的预期输出是最终addArtist("Ace of Base", 5)调用将导致输出

1
pre:  []
post:  ['Ace of Base']

这是Python的一个微妙之处,我不理解?为什么这是输出,我如何获得所需的输出呢?谢谢!

2 个答案:

答案 0 :(得分:34)

您不希望在类中声明成员,只需在__init__方法中设置:

class Listener:
    def __init__(self, id):
        self.id = id
        self.artists = []

    def addArtist(self, artist, plays):
        print self.id # debugging...
        print "pre: ", self.artists
        self.artists.append(artist)
        print "post: ", self.artists

如果您有类似

的课程
class A:
  x=5

然后x是该类的成员,而不是该类的实例的成员。这可能会令人困惑,因为python允许您通过实例访问类成员:

>>> a=A()
>>> print a.x
5

但您也可以通过课程本身访问它:

>>> print A.x
5

这甚至可以正常运行:

>>> a1=A()
>>> a2=A()
>>> a1.x=6
>>> print a1.x
6
>>> print a2.x
5

但实际发生的事情是你在a1实例中添加了一个新的x,而不是类成员,它仍然具有原始值:

>>> print A.x
5

当你有一些可以改变的东西时,你才开始看到差别,比如列表:

class A:
  l=[]

>>> a1=A()
>>> print a1.l
[]
>>> a2=A()
>>> print a2.l
[]
>>> a1.l.append(5)
>>> print a1.l
[5]
>>> print a2.l
[5]
>>> print A.l
[5]

答案 1 :(得分:3)

  

这是Python的一个微妙之处,我不理解?

它不是微妙的,它很简单;与混淆问题的其他语言不同,在Python中,您在类中声明的所有内容都属于该类。这是很自然的,因为类是对象(就像其他所有东西一样),因此是一个非常有效的附加东西的地方。因此,所有这些方法都属于该类(而不是以某种方式神奇地复制到每个实例),数据属性也是如此。

  

每位听众都有一个id来识别他们

是的,因为您在__init__中为每个实例附加一个。这与属于该类的id没有关系 - 除了当您通过实例查找id时,实例自己的id将是发现,隐藏属于该类的那个。

  

和他们听的艺术家名单,艺术家= []

但是,当您通过课程查找artists时,会找到“artists”类,因为该实例没有。{/ p>

  

向艺术家列表添加内容会为Listener类的所有实例添加

没有;它将添加到类本身,这是在实例中找不到它们的地方。

请记住,如果您稍后在某个实例上进行了self.artists = []之类的直接分配,那么该实例将获得隐藏该类列表的自己的列表。其他实例不会,因为该代码没有在其他实例上运行。