我正在学习使用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中可行吗?我怎么能这样做?
答案 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"])]
现在它本身没有名称,但是存在一个名称包含歌曲引用的列表。
等等。我希望这会让它更清晰一些。实例存在于其名称之外。