我读过python中的repr()函数。我想做一些实验,并想在对象内部评估rep()的输出,看看它会产生什么结果。所以我写了以下代码:
class no :
def __init__(self,a) :
self.a = a
self.b = eval(repr(self))
k = no(2)
print(k.b.a)
我预计在调用init时,对象已经创建。因此,考虑在一个已经创建的对象中创建一个相同类的新对象。
然而,行中:
k = no(2)
我收到一个运行时错误:
Traceback (most recent call last):
File "classofpy.txt", line 54, in <module>
k = no(2)
File "classofpy.txt", line 52, in __init__
self.b = eval(repr(self))
File "<string>", line 1
<__main__.no object at 0x0385F690>
^
然而,我不明白为什么当调用init时,对象已经创建好了,它却抱怨对象不存在。
但是更换时:
self.b = eval(repr(self))
通过
self.b = self
一切都很好。
这种行为背后的原因可能是什么?尽管在语义上都是
self.b = self
以及self.b=eval(repr(self))
意思相同。我想我在这里的细节可能是错的,比如,self.b=eval(repr(self))在内存布局方面可能有其他含义,可能与创建副本对象的含义不同,但这正是我发布这个问题的目的。
那么为什么
self.b = eval(repr(self))
产生运行时错误?
(此外,了解语言设计者如何考虑允许或限制此类任务将是非常有见地的)
- 如果您想让这样的东西发挥作用,您需要定义一个
__repr__
,它可以生成一个有效的、eval
可用的字符串。正如您所看到的,默认的repr
只生成<qualified.classname object at 0xmemoryaddress>
,这不是有效的Python代码,因此不能是eval
-ed - 即使你这样做,这也是一个疯狂的设计,因为即使你自己可以
eval
,你也只是创建了一个无限循环,在这个循环中,每个实例都试图创建一个相同的子实例,它创建了一个子实例,创建了一子实例,等等,无限
不要这样做。可以随意定义一个有用的__repr__
,但不要在自己的__init__
中尝试eval
。
需要明确的是,self.b = self
与self.b = eval(repr(self))
不是一回事。前者只是创建了一个参考循环(在某些情况下,这本身就是一个问题,但通常不会致命)。后者是在当前对象的基础上创建一个全新的对象,考虑到当前对象正在构建过程中,这在许多情况下都是一个坏主意,即使它没有导致无限递归的对象构建。