2012-03-17 2 views
12

クラスListenerを定義し、Listenerというオブジェクトの辞書を作成しました。各リスナーには、それを識別するためのidと、聞き取るartistsのリスト、artists = []があります。 artistsリストに何かを追加すると、参照されるインスタンスではなく、Listenerクラスのすべてのインスタンスに追加されます。これは私の問題です。Pythonクラスのメンバーとしてリストすると、クラスのすべてのインスタンスでそのコンテンツが共有されるのはなぜですか?

次のようにリスナークラスが定義されています。ここでは

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の微妙なことですがわからないのですか?なぜこれが出力され、代わりに希望の出力を得ることができますか?ありがとう!

あなたはメンバーがクラス内で宣言さが、ちょうど __init__方法で設定されたくない

答えて

24

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] 
4

をこれは私が理解していないよパイソンの繊細ですか?

これは微妙なことではありません。この問題を混乱させる他の言語とは異なり、Pythonではクラス内に宣言したものはすべてクラスに属します。クラスはオブジェクト(他のすべてと同じように)であるため、物を添付するための完全に有効な場所であるため、これは当然です。したがって、これらのメソッドはクラスに属しています(それぞれのインスタンスに何らかの形で魔法のようにコピーされるのではなく)。

各リスナーには、それらを識別するためにidを持って

はい、あなたは__init__内の各インスタンスに1を添付しているため。これはとは関係ありませんidがクラスに属しています - ただし、インスタンスを介してidを検索すると、そのインスタンスに属するidがクラスに属していません。

、彼らは耳を傾けるアーティストのリスト、アーティスト= []

あなたがクラスを経由してartistsを検索すると、インスタンスにはないので、しかし、クラスのartistsが、発見されます1つ持っている。アーティストリストに何かを追加する

は、リスナークラスのすべてのインスタンスのためにそれを追加します

ません。クラス自体にが追加されました。は、インスタンス内に見つからない場合に検索されます。

インスタンスにself.artists = []のような直接割り当てを行った場合、そのインスタンスはクラスのリストを隠す独自のリストを取得することに注意してください。そのコードは他のインスタンスで実行されなかったため、他のインスタンスは実行されませんでした。

関連する問題