У меня есть код, который работал в Python 3.6 и не работает в Python 3.8. Кажется, все сводится к вызову super
в подклассе typing.NamedTuple
, как показано ниже:
<ipython-input-2-fea20b0178f3> in <module>
----> 1 class Test(typing.NamedTuple):
2 a: int
3 b: float
4 def __repr__(self):
5 return super(object, self).__repr__()
RuntimeError: __class__ not set defining 'Test' as <class '__main__.Test'>. Was __classcell__ propagated to type.__new__?
In [3]: class Test(typing.NamedTuple):
...: a: int
...: b: float
...: #def __repr__(self):
...: # return super(object, self).__repr__()
...:
>>> # works
Целью этого вызова super(object, self).__repr__
является использование стандартного '<__main__.Test object at 0x7fa109953cf8>'
__repr__
вместо вывода всего содержимого элементов кортежа (что произошло бы по умолчанию). Есть некоторые вопросы на super
приводит к аналогичным ошибкам, но они:
- Обратитесь к версии без параметров
super()
- Сбой уже в Python 3.6 (у меня это работало до обновления 3.6 -> 3.8)
- Я все равно не понимаю, как это исправить, учитывая, что я контролирую не пользовательский метакласс, а предоставленный stdlib
typing.NamedTuple
.
Мой вопрос: как я могу исправить это, сохраняя при этом обратную совместимость с Python 3.6 (иначе я бы просто использовал @dataclasses.dataclass
вместо наследования от typing.NamedTuple
)?
Побочный вопрос заключается в том, как это может привести к сбою во время определения, учитывая, что вызывающий нарушение вызов super
находится внутри метода, который еще даже не выполнен. Например:
In [3]: class Test(typing.NamedTuple):
...: a: int
...: b: float
...: def __repr__(self):
...: return foo
работает (пока мы на самом деле не вызовем __repr__
), хотя foo
является неопределенной ссылкой. Является ли super
волшебным в этом отношении?
super
, а не представление вашего экземпляраTest
. - person chepner   schedule 01.05.2020__repr__ = object.__repr__
в вашем определении класса работает для меня на Python3.6 и Python3.8 - person Azat Ibrakov   schedule 01.05.2020typing.NamedTuple
;typing.NamedTupleMeta
, это какие-то махинации.super()
требует, чтобы__class__
был доступен во время компиляции, что, по-видимому, здесь не так. См. также: Приведите__classcell__
пример для метакласса Python 3.6 - person L3viathan   schedule 01.05.2020object
обязательно является последним классом в MRO любого класса, вам не нужны кооперативные способностиsuper
. - person chepner   schedule 01.05.2020NamedTuple
имеет метакласс, ограничивающий магию перегрузки методы. - person pylang   schedule 04.05.2020