如何在Python OOP中打印“实例化”变量?

时间:2017-06-07 19:27:05

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

我正在学习使用Python3编写的“用艰难的方式学习Python”一书。作者用这个例子介绍了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很有趣。作者建议我们应该将代码“垃圾”,“破解”和“捶打”一下。

我试图打印对象为“instanced”的变量名称(不确定“instanced”是否为正确的单词,也许正确的单词是“实例化”)。为了尝试这一点,我在类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中可行吗?我怎么能这样做?

4 个答案:

答案 0 :(得分:5)

令人困惑的是,一个对象实际上没有名字!假设我们使用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。您可以输入代码,查看正在创建的变量和对象。

答案 1 :(得分:1)

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

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

然后,您可以存储{id : 'your_name_here'}的地图。之后,如果您愿意,可以使用对象的uid属性来获取其名称&#34; (给的那个)。

答案 2 :(得分:1)

其他人评论了为什么你想要做的事情是不必要的(并且可能是不受欢迎的)。但事实并非如此,这是不可能的。毕竟,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

当然,这仅适用于您在全局范围内定义Song的内容(例如,在某些功能中)。

答案 3 :(得分:0)

你做不到。变量的名称不是实例的一部分,实例不知道它。就它而言,它根本没有名称,或许多,或者它可能是列表的一部分左右。

像这样:

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

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

或者这个:

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

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

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

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

等等。我希望这会让它更清晰一些。实例存在于其名称之外。