作为python类的一个成员列出,为什么要在该类的所有实例中共享其内容?

2024-09-24 04:26:35 发布

您现在位置:Python中文网/ 问答频道 /正文

我定义了一个类Listener,并创建了一个Listener对象字典。每个监听者都有一个id来识别他们,还有一个他们所听的artists列表,artists = []。向artists列表中添加某些内容会为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的精妙之处吗?为什么这是输出,我怎样才能得到想要的输出呢?谢谢!


Tags: oftheselfidbasepostpreace
2条回答

Is this a subtlety of Python I'm not understanding?

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

Each listener has an id to identify them

是的,因为您将一个附加到__init__中的每个实例。这与属于该类的id无关,只是当您通过实例查找id时,将找到该实例自己的id,隐藏属于该类的实例。

and a list of artists they listen to, artists = []

但是,当您通过类查找artists时,会找到类artists,因为实例没有。

Adding something to the artists list adds it for all instances of the Listener class

不;它将添加到类本身中,这是在实例中找不到对象时查找它们的地方。

请记住,如果您稍后在实例上进行类似self.artists = []的直接赋值,则该实例将获得隐藏类列表的自己的列表。其他实例不会,因为该代码没有在其他实例上运行。

您不希望在类内声明成员,而只希望在__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]

相关问题 更多 >