Включение текущего класса в качестве аннотации возвращаемого типа
В python 3 я могу создавать аргументы и возвращать аннотации типа. Пример:
class Graph:
def __init__(self, V: int, E: int, edges: list):
pass
@classmethod
def fromfile(cls, readobj: type(sys.stdin)):
pass
def V(self) -> int:
pass
def E(self) -> int:
pass
Проблема в том, что я не могу сделать аннотацию с типом возвращаемого значения текущего класса (Graph), который еще не определен.
Пример:
class Graph:
def reverse(self) -> Graph:
pass
Этот код идет с ошибкой
def reverse(self) -> Graph:
NameError: name 'Graph' is not defined
Эти аннотации действительно полезны как для документирования, так и для IDE для распознавания аргументов и возвращаемых типов = > enable autocomplete
UPD:
Так что я пришел, это либо невозможно, либо требует некоторых хаков, которые мне не нравятся, поэтому я решил использовать только def reverse (self) -> 'Graph':
что понятно для документации, но нарушает правило. Недостатком является то, что он не работает для автозаполнения IDE.
Ответы
Ответ 1
Итак, через некоторое время я могу сказать, что решение, которое я принял, состояло в использовании -> 'Graph'
вместо -> Graph
. Это не делает мою среду IDE (PyCharm) способной распознавать тип таким образом, но она достаточно хорошо работает для целей документирования.
Другим возможным решением, которое я мог бы использовать, было изменение аннотации во время выполнения, но это не решает проблему с документацией - вы не захотите искать объявления типов где-то в середине источников...
Проблема имеет корни в распознавании объекта класса до того, как класс был определен. Это просто невозможно сделать в python.
Ответ 2
В python-3.7 эта проблема была решена путем отсутствия оценки аннотаций во время определения функции. Вместо этого они сохраняются в __annotations__
в виде строки. Это называется отложенной оценкой аннотаций, представленной в PEP 563.
Также обратите внимание:
Амортизационная политика
Начиная с Python 3.7, для использования описанной функциональности требуется импорт __future__
. Нет предупреждений.
В Python 3.8 PendingDeprecationWarning
вызывает PendingDeprecationWarning
при наличии аннотаций типов в модулях без импорта __future__
.
Начиная с Python 3.9, предупреждение становится предупреждением об DeprecationWarning
.
В Python 4.0 это станет поведением по умолчанию. Использование аннотаций, несовместимых с этим PEP, больше не поддерживается.
Вот пример:
In [7]: from __future__ import annotations
In [8]: class C:
...: def func(cls, arg:str) -> C:
...: pass
...:
In [9]: c = C()