Оценка объекта внутри себя в Python - PullRequest
0 голосов
/ 10 февраля 2019

Я читал о функции repr () в python.Я думал о том, чтобы что-то экспериментировать, и думал об оценке вывода 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 голосов
/ 10 февраля 2019
  1. Если вы хотите, чтобы что-то подобное работало, вам нужно определить a __repr__, который создает действительную, eval пригодную для использования строку.По умолчанию repr, как вы видели, просто выдает <qualified.classname object at 0xmemoryaddress>, что не является допустимым кодом Python и, следовательно, не может быть eval -ed.
  2. Это безумный дизайн, даже если вы это делаете, потому что даже если вы можете eval сами, вы только что создали бесконечный цикл, где каждый экземпляр пытается создать идентичный подэкземпляр, который создаетидентичный подэкземпляр, который создает идентичный подэкземпляр и т. д. и т. д. до бесконечности.

Не делайте этого.Не стесняйтесь определять полезный __repr__, но не пытайтесь eval добавить его в свой собственный __init__.

Для ясности, self.b = self это не то же самоевещь как self.b = eval(repr(self)).Первый просто создает ссылочный цикл (в некоторых контекстах проблема сама по себе, но, как правило, не смертельная).Последнее создает совершенно новый объект на основе текущего объекта, что, учитывая, что текущий объект находится в процессе конструирования, было бы плохой идеей во многих контекстах, даже если это не привело к бесконечно рекурсивному построению объекта.

...