python - Python 类字典有什么不同?

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

最佳答案

I realize the name = "" and artist = "" lines are (probably) unnecessary but since they do work, I must ask: Since the name and artist string properties appear to work fine "initialized" outside the constructor; why doesn't the week dictionary?

代码之所以有效,是因为它们是不必要的。然而,这些行并不能“正常工作”,因为它们根本不能“工作”,因为它们是无关紧要的,因为它们是不必要的。

如果您在 __init__ 中设置了周字典,即使您在类中保留 week = {} 行,它也会起作用,因为相同的机制将会启动.

让我们更仔细地看看这个:

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

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

在您的 __init__ 中,您执行以下操作:

self.name = name
self.artist = artist

这会将一个属性附加到类的每个对象(因为每个对象都会调用 __init__),从而隐藏类中的对象。当查找属性时,会在类和对象中查找它们(如果在对象中找不到它们),但是当分配属性时,它们只是被分配给您所说的分配给的事物。 (要修改 Song 属性,您可以使用 Song.whatever = 42,即使在方法内部也是如此。)

当您在类中创建属性并且从未将属性分配给实例时,就会出现问题。请再次注意,__init__ 并不特殊;您可以稍后创建该类的新属性。

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

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

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

如果我们将 self.name = name 替换为修改现有对象的内容,那么我们会看到相同的行为。然而,我们实际上不能这样做:self.name的初始值为'',它是一个字符串,而Python字符串无法就地修改它们。当您重新分配给包含字符串的变量时,您实际上就是这样做的:重新分配。您使变量不再是旧对象的名称,而是开始作为新对象的名称。由于我们只能通过赋值来影响 self.name,因此我们无法影响 Song.name,除非我们显式引用 Song.name

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

self.week = {}

关于python - Python 类字典有什么不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10082352/

相关文章:

java - 如何创建公共(public)类的新对象

python 如何从其他类访问变量

java - 从 memcached 中删除的对象的事件监听器

python - 如何使用 spaCy 从数据框列创建标记化单词列表?

c# - 保存派生类的集合实例的基类

PHP 7 返回类型提示

c++ - 类方法会增加类实例的大小吗?

php - fatal error : Undefined class constant

python - 如何计算沿插值路径的均匀距离(Python2.7)?

Python 多维列表 - IndexError : list index out of range