Подтвердить что ты не робот

Включение текущего класса в качестве аннотации возвращаемого типа

В 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.

4b9b3361

Ответ 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()