2

Python 2.7 でクラス プロパティに問題があり、解決策を見つけることができましたが、理解できません。

次の考案されたコードでは、各歌が、言及された曜日の歌詞を含む独自の辞書を持つことを期待しています。

class Song:
  name = ""
  artist = ""
  # If I comment this line and uncomment the one in the constructor, it works right
  week = {}
  def set_monday( self, lyric ):
    self.week[ "Monday" ] = lyric;

  .
  . # silly, I know
  .

  def set_friday( self, lyric ):
    self.week[ "Friday" ] = lyric;

  def show_week( self ):
    print self.week

  def __init__(self, name, artist):
    self.name = name
    self.artist = artist

    # Uncomment the line below to fix this
    # self.week = {}

def main():
  songs = {}

  friday_im_in_love = Song( "Friday I'm in Love", "the Cure" )
  friday_im_in_love.set_monday( "Monday you can fall apart" )
  friday_im_in_love.set_tuesday( "Tuesday can break my heart" )
  friday_im_in_love.set_wednesday( "Wednesday can break my heart" )
  friday_im_in_love.set_thursday( "Thursday doesn't even start" )
  friday_im_in_love.set_friday( "Friday I'm in love" )
  songs[ "Friday I'm in Love" ] = friday_im_in_love

  manic_monday = Song( "Manic Monday", "the Bangles" )
  manic_monday.set_monday( "Just another manic Monday" )
  songs[ "Manic Monday" ] = manic_monday

  for song in songs:
    # This shows the correct name and artist
    print songs[song].name + " by " + songs[song].artist
    # The dictionary is incorrect, though.
    songs[song].show_week()

if __name__ == '__main__':
   main()

上記のコードを実行すると、出力は次のようになります。

Manic Monday by the Bangles
{'Friday': "Friday I'm in love", 'Tuesday': 'Tuesday can break my heart', 'Thursday': "Thursday doesn't even start", 'Wednesday': 'Wednesday can break my heart', 'Monday': 'Just   another manic Monday'}
Friday I'm in Love by the Cure
{'Friday': "Friday I'm in love", 'Tuesday': 'Tuesday can break my heart', 'Thursday': "Thursday doesn't even start", 'Wednesday': 'Wednesday can break my heart', 'Monday': 'Just another manic Monday'}

どちらの辞書も、私が期待するようには見えません。コードに戻ると、week = {}一番上にコメントself.week={}を付けて、コンストラクターでコメントを外すと、辞書が期待どおりに表示されます。

Manic Monday by the Bangles
{'Monday': 'Just another manic Monday'}
Friday I'm in Love by the Cure
{'Friday': "Friday I'm in love", 'Tuesday': 'Tuesday can break my heart', 'Thursday': "Thursday doesn't even start", 'Wednesday': 'Wednesday can break my heart', 'Monday': 'Monday you can fall apart'}

どうしてこれなの?

name = ""およびartist = ""行は (おそらく) 不要であることは認識していますが、機能するため、質問する必要があります。なぜ週の辞書に載っていないのですか?

4

2 に答える 2

4

name = "" と artist = "" の行は (おそらく) 不要だと思いますが、機能するので、質問する必要があります。なぜ週の辞書に載っていないのですか?

コードは不要であるため、正確に機能します。ただし、は不要であるため無関係であるため、まったく「機能」しないため、「正常に機能」しません。

その中に週辞書を設定すると、同じメカニズムが作動するため、クラスに行__init__を残しても機能します。week = {}

これをもう少し詳しく見てみましょう。

# If I comment this line and uncomment the one in the constructor, it works right
week = {}

Python は非常に単純なルールに従いclassます。ブロック内に記述されたものは、個々のオブジェクトではなく、クラスに属します。という名前のオブジェクトに何かをアタッチするにselfは、その の 1 つに代入しますself.attributes。この点で、__init__特別ではありません。自動的に呼び出され、特定の目的を持つ場合がありますが、それ以外の場合は、他のメソッドと同じようにオブジェクトと対話します。(したがって、selfでもパラメーターが必要です__init__。)

__init__で、次のことを行います。

self.name = name
self.artist = artist

これにより、クラス内のオブジェクトを非表示にする属性がクラスの各オブジェクトにアタッチされます (すべてのオブジェクトが__init__呼び出されるため) 。属性がルックアップされると、それらはオブジェクトだけでなくクラスでもルックアップされますが (オブジェクトで見つからない場合)、それらが割り当てられると、それらは単にあなたがそれを割り当てると言ったものに割り当てられますに。(属性を変更するには、メソッド内であっても を使用します。)SongSong.whatever = 42

この問題は、クラスに属性を作成し、インスタンスに属性を割り当てない場合に発生します。__init__繰り返しますが、特別ではないことに注意してください。後でクラスの新しい属性を作成できます。

さて、__init__は特別ではないので、 内のサンプル関数の 1 つの作業を行うとしましょう__init__:

self.week["Friday"] = "gotta get down"

違いがわかりますか?week["Friday"]属性名ではありません。weekは。したがって、このような新しい属性を作成することはできません。代わりに、として参照される既存のオブジェクトを変更しています。オブジェクトには1つがないため、クラス内の1つを見つけます。そして、もう一度見上げると、 が異なっていたとしても、が 1 つしかないため、その変化が見られます。self.weekself.weekselfSongSong.week

既存のオブジェクトを変更するものに置き換えた場合self.name = name、同じ動作が見られます。しかし、実際にはそれを行うことはできませんself.name: の初期値は''文字列であり、Python 文字列はそれらをインプレースで変更する方法を提供しません。文字列を保持する変数に再代入するときは、まさにそれを行います: 再代入。変数が古いオブジェクトの名前ではなくなり、新しいオブジェクトの名前になり始めます。self.name代入によってのみ影響を与えることができるため、Song.name明示的に を参照しない限り影響を与えることはできませんSong.name

__init__簡単な解決策は、属性を次のように設定することです。

self.week = {}
于 2012-04-10T03:06:23.043 に答える
0

文字列は不変です。それらを変更することはできません。再バインドするだけです。

辞書は可変です。それらは変更でき、誰もが変更を見ることができます

代わりにselfwithinの属性に割り当てて作成します。__init__()

于 2012-04-10T02:25:19.453 に答える