用python

时间:2019-02-10 19:02:25

标签: python python-3.x object repr

我了解了python中的repr()函数。我想到进行实验并想到评估对象内部内部repr()的输出以查看其产生的结果。 所以我写了下面的代码:

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))

产生运行时错误?

(此外,了解语言设计者如何考虑允许或限制这种分配是很有见地的)

1 个答案:

答案 0 :(得分:4)

  1. 如果您希望使用类似的方法,则需要定义a __repr__来生成有效的eval可用字符串。如您所见,默认的repr只会生成<qualified.classname object at 0xmemoryaddress>,它不是有效的Python代码,因此无法进行eval编辑。
  2. 即使您这样做也是一个疯狂的设计,因为即使您自己eval,您也已经创建了一个无限循环,其中每个实例都试图创建一个相同的子实例,从而创建了一个子实例。完全相同的子实例,这将无限期地创建相同的子实例等。

不要这样做。随时定义一个有用的__repr__,但不要尝试eval用自己的__init__对其进行编辑。

请注意,self.b = selfself.b = eval(repr(self))是同一件事。前者只是在创建一个参考周期(在某些情况下,它本身就是一个问题,但通常不是致命的)。后者是基于当前对象创建一个全新的对象,鉴于当前对象正在构建中,即使在没有导致无限递归对象构建的情况下,在许多情况下这也不是一个好主意。 / p>