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

zeb*_*bra 21 python class list

我已经定义了一个类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
Run Code Online (Sandbox Code Playgroud)

这是我的调试测试代码:

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)
Run Code Online (Sandbox Code Playgroud)

并输出:

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']
Run Code Online (Sandbox Code Playgroud)

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

1
pre:  []
post:  ['Ace of Base']
Run Code Online (Sandbox Code Playgroud)

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

Vau*_*ato 38

您不希望在类中声明成员,而只是在__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
Run Code Online (Sandbox Code Playgroud)

如果你有类似的课程

class A:
  x=5
Run Code Online (Sandbox Code Playgroud)

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

>>> a=A()
>>> print a.x
5
Run Code Online (Sandbox Code Playgroud)

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

>>> print A.x
5
Run Code Online (Sandbox Code Playgroud)

它甚至可以正常工作:

>>> a1=A()
>>> a2=A()
>>> a1.x=6
>>> print a1.x
6
>>> print a2.x
5
Run Code Online (Sandbox Code Playgroud)

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

>>> print A.x
5
Run Code Online (Sandbox Code Playgroud)

当你有一些可以改变的东西时,你才开始看到差异,比如一个清单:

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]
Run Code Online (Sandbox Code Playgroud)