【问题标题】:How to print the "instantiated" variable in Python OOP?如何在 Python OOP 中打印“实例化”变量?
【发布时间】:2017-11-09 07:33:39
【问题描述】:

我正在用 Python3 学习“Learn Python the Hard Way”一书。作者通过这个例子介绍了OOP的概念:

class Song (object):

    def __init__(self,lyrics):
        self.lyrics = lyrics

    def sing_me_a_song(self):
        for line in self.lyrics:
            print (line)


happy_bday = Song(["Happy birthday to you", "I don't want to get sued","So I'll stop right there"])

bulls_on_parade = Song(["They rally around the family","With pockets full of shells"])

happy_bday.sing_me_a_song()

bulls_on_parade.sing_me_a_song()

OOP 对我来说有点有趣。作者建议我们应该对上面的代码进行一点“trash”、“break”和“thrash”。

我试图打印对象“实例化”的变量名称(不确定“实例化”是否是正确的词,也许正确的词是“实例化”)。为了尝试,我在类 Songs() 中添加了以下方法:

class Song (object):

    def __init__(self,lyrics):
        self.lyrics = lyrics

    def sing_me_a_song(self):
        for line in self.lyrics:
            print (line)

    def name_of_var(self):
        print (Song)

    def name_of_var_2(self):
        print (object)

    def name_of_var_3(self):
        print (self)

    def name_of_var_3(self):
        print (self)

我使用了作者提供的对象示例:

happy_bday = Song(["Happy birthday to you", "I don't want to get sued","So I'll stop right there"])

bulls_on_parade = Song(["They rally around the family","With pockets full of shells"])

happy_bday.sing_me_a_song()

bulls_on_parade.sing_me_a_song()

最后,我尝试做:

print(Song(["They rally around the family","With pockets full of shells"]))

print (happy_bday.name_of_var())

print (happy_bday.name_of_var_2())

print (happy_bday.name_of_var_3())

print (happy_bday.__init__(happy_bday))

我无法实现我的目标。使用上面我得到的方法:

<__main__.Song object at 0x7f4b784f3da0>
<class '__main__.Song'>
None
<class 'object'>
None
<__main__.Song object at 0x7f4b784f3d30>
None
None
pedr

我的目标是创建一些我会做的方法:

print (happy_bday.__some__method())

程序会返回:

happy_bday

也许这在 Python 中是不可能的……如果我没记错的话,你可以在 Lisp/Racket 中做这种事情(但我不是 100% 确定)。这在 Python 中可能吗?我该怎么做?

【问题讨论】:

  • 没有简单的方法可以在运行时找出变量的“名称”。无论如何,这不是变量应该的工作方式。但如果你真的需要它:你可以看看locals()globals()
  • 如果这本书说你应该这样做,我强烈建议你再找一本书。
  • 对象不知道它们被分配到的变量。无论如何,这是你的工作来跟踪它。
  • @ChristianDean,实际上,这本书只是建议我们应该稍微“玩”一下这段代码,以便熟悉 OOP。我对“玩”的态度是一种不寻常和奇怪的方式。这本书没有建议我在上面尝试过什么。
  • 所以,为了清楚起见,变量没有实例化对象被实例化。变量被分配给

标签: python python-3.x oop instance-variables


【解决方案1】:

让你感到困惑的是,一个对象实际上并没有名字!假设我们使用 Song 构造函数创建了一首 Song,并将其放入名为 happy_bday 的变量中:

happy_bday = Song(["Happy birthday to you", "I don't want to get sued","So I'll stop right there"])

这将创建一个 Song 对象,该对象位于“堆”上,即计算机中的一个内存区域。它还创建了一个名为happy_bday 的变量,引用您刚刚创建的 Song 对象。不过,Song 对象本身并不知道这一点。

其实如果你跑

happy_bday2 = happy_bday

您将创建另一个变量happy_bday2,它引用完全相同的 Song 对象。事实上,如果你现在运行这条线

happy_bday.lyrics[0] = "Happy Birthday To You"

为了增加一些大小写,happy_bday2 的歌词也会改变。这是因为即使您有两个单独的变量,它们实际上只是引用内存中完全相同的对象的两种方式。

希望,现在您可以清楚为什么不能询问 Song 对象引用的是什么变量了;可能有多个变量引用它,或者根本没有变量(毕竟,你可以写Song(["some lyrics"]).var_name(),在这种情况下,应该打印出什么?)。

如果您想对此进行可视化,这里有一个名为 PythonTutor 的出色工具:http://pythontutor.com。您可以输入您的代码,并查看正在创建的变量和对象。

【讨论】:

    【解决方案2】:

    对象不与名称相关联,而是与引用相关联。

    如果您确实需要某种方法来识别对象,请允许为每个对象生成唯一 ID 并将其存储为参数。哎呀,你甚至可以self.uid = id(self)

    然后,您可以存储{id : 'your_name_here'} 的地图。稍后,如果您愿意,可以使用对象的uid 属性来获取其“名称”( 提供的名称)。

    【讨论】:

      【解决方案3】:

      其他人评论了为什么您想要做的事情是不必要的(并且可能是不受欢迎的)。但实际上这不是不可能的。毕竟,globals() 是全局范围内的对象及其引用的字典,并且是为此类自省而设计的。因此,您可以为您的类定义一个方法,该方法返回该类实例的所有标识符的名称。例如:

      class Song():
          def __init__(self,lyrics):
              self.lyrics = lyrics
          def sing_me_a_song(self):
              for line in self.lyrics:
                  print (line)
      
          def names_of_var(self):
             for k in globals().keys():
                  if globals()[k] == self:
                      print(k)
      
      In [32]: happy_bday = Song(["Happy birthday to you", "I don't want to get sued","So I'll stop right there"])
      In [33]: happy_bday2 = happy_bday
      In [34]: happy_bday.names_of_var()
      happy_bday
      happy_bday2
      

      当然,这仅在您在全局范围内定义 Songs 时才有效(例如,在某些函数内)。

      【讨论】:

        【解决方案4】:

        你不能那样做。您的变量的名称不是实例的一部分,并且实例不知道它。就它而言,它根本没有名字,或者很多,或者它可能是一个列表的一部分。

        像这样:

        >>> print(Song(["Line", "Line"]).some_method())
        

        在这种情况下,创建实例,调用方法,然后再次丢弃实例。它从来没有名字。它应该打印什么?

        或者这个:

        >>> name1 = name2 = Song(["Line", "Line"])
        >>> name1.some_method()
        

        现在实例由两个名称引用,name1 和 name2。

        >>> name1  = [Song(["Line"])]
        

        现在它本身没有名称,但存在一个名称列表,其中包含对歌曲的引用。

        等等。我希望这使它更清楚一点。实例与其名称不同。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-04-16
          • 1970-01-01
          • 2015-12-01
          • 1970-01-01
          • 2015-02-08
          • 2017-04-11
          • 2018-03-10
          • 1970-01-01
          相关资源
          最近更新 更多