如何在 Python OOP 中打印 "instantiated" 变量?

How to print the "instantiated" variable in Python OOP?

我正在和 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"上面的代码一点点。

我试图打印对象为 "instanced" 的变量名(不确定 "instanced" 是否是正确的词,也许正确的词是 "instantiated")。为了尝试这一点,我在 class 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

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

print (happy_bday.__some__method())

程序会 return:

happy_bday

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

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

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

然后,您可以存储{id : 'your_name_here'}的地图。以后,如果你愿意,你可以使用对象的 uid 属性来获取它的 "name"( 给的那个)。

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

像这样:

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

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

或者这样:

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

现在实例由两个名称引用,名称 1 和名称 2。

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

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

等等。我希望这能让它更清楚一点。实例与它们的名字不同。

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

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

这将创建一个 Song 对象,它位于 "the heap," 您计算机的内存区域中。它还会创建一个名为 happy_bday 的变量,该变量 引用 您刚刚创建的 Song 对象。但是 Song 对象本身并不知道这一点。

事实上,如果你运行

happy_bday2 = happy_bday

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

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

要添加一些大写字母,happy_bday2 的歌词也会更改。那是因为即使你有两个独立的变量,它们实际上只是引用内存中完全相同对象的两种方式。

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

如果您想将其可视化,可以在此处找到一个名为 PythonTutor 的好工具:http://pythontutor.com。您可以输入您的代码,并查看正在创建的变量和对象。

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

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

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