Python类词典有什么不同?

时间:2012-04-10 02:22:49

标签: python oop class dictionary

我在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 = ""行(可能)是不必要的,但由于他们工作,我必须要问:因为名称和艺术家字符串属性似乎有效精简“初始化”在构造函数之外;为什么不是周词典?

2 个答案:

答案 0 :(得分:4)

  

我意识到name =“”和artist =“”行是(可能)不必要但是因为它们确实有效,我必须要问:因为名称和艺术家字符串属性似乎在构造函数之外工作得很好“初始化”;为什么不是周词典?

代码正好,因为它们是不必要的。但是,并不“正常”,因为它们根本不“工作”因为它们是不相关的,因为它们是不必要的。

如果您在__init__中设置周词典,即使您在班级中留下week = {}行也会有效,因为相同的机制会启动。

让我们更仔细地看一下:

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

Python遵循一个非常简单的规则:在class块内编写的内容属于类,而不属于单个对象。要将某些内容附加到名为self的对象,请指定其中一个self.attributes。在这方面,__init__并不特别;它可以自动调用并具有特定目的,但它与对象的交互方式与任何其他方法相同。 (因此即使在self中也需要__init__参数。)

__init__中,您可以:

self.name = name
self.artist = artist

这会将属性附加到类的每个对象(因为每个对象都被__init__调用),隐藏类中的那个。当属性查找时,会在类和对象中查找它们(如果在对象中找不到它们),但是当它们被分配时 ,它们被简单地分配给你说要分配给它的东西。 (要修改Song属性,即使在方法内也可以使用Song.whatever = 42。)

在类中创建属性时也会出现问题,并且也不会为实例分配属性。请注意,__init__并不特殊;您可以稍后创建该类的新属性。

现在,由于__init__并不特殊,我们假设我们在__init__内执行其中一个示例函数的工作:

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

你看到了区别吗? week["Friday"]不是属性名称; week是。所以我们无法创建像这样的新属性。相反,我们修改 现有对象,该对象被查找为self.week。哪个在类中找到一个,因为该对象没有。当我们再次查看self.week时,即使selfSong不同,我们也会看到此更改,因为只有一个Song.week

如果我们用修饰现有对象的东西替换self.name = name,那么我们会看到相同的行为。但是,我们不能实际执行此操作:self.name的初始值为'',这是一个字符串,Python字符串提供无法修改它们就地。当您重新分配给包含字符串的变量时,您可以这样做:重新分配。您导致变量不再是旧对象的名称,并开始成为新对象的名称。由于我们只能通过分配影响self.name,因此除非我们明确提及Song.name,否则我们无法影响Song.name

简单的解决方案是在__init__中设置属性:

self.week = {}

答案 1 :(得分:0)

字符串是不可变的;你不能改变它们,只能重新绑定它们。

字典是可变的;它们可以更改,每个人都可以看到更改

通过在self内分配__init__()的属性来创建它们。

相关问题