putting current class as return type annotation

sasha.sochka picture sasha.sochka · Apr 6, 2013 · Viewed 20.5k times · Source

In python 3 I can make arguments and return type annotations. Example:

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

The problem is I can't make an annotation with return type of the current class (Graph), which is not defined yet. Example:

class Graph:
   def reverse(self) -> Graph:
       pass

This code goes with error

def reverse(self) -> Graph:
NameError: name 'Graph' is not defined

These annotations are really useful both for documenting and allowing IDE to recognize argument and return types => enable autocomplete

UPD: So what I came up is this is either impossible or requires some hacks I don't like, so I decided to use just def reverse (self) -> 'Graph': which is understandable for documentation although breaks the rule. The downside is that it doesn't work for IDE autocomplete.

Answer

Kasravnd picture Kasravnd · Apr 17, 2018

In python-3.7 this issue has been resolved by not evaluating the annotations at function definition time. Instead, they are preserved in __annotations__ in string form. This is called Postponed Evaluation of Annotations, introduced in PEP 563.

Also note:

Deprecation policy

Starting with Python 3.7, a __future__ import is required to use the described functionality. No warnings are raised.

In Python 3.8 a PendingDeprecationWarning is raised by the compiler in the presence of type annotations in modules without the __future__ import.

Starting with Python 3.9 the warning becomes a DeprecationWarning.

In Python 4.0 this will become the default behavior. Use of annotations incompatible with this PEP is no longer supported.

Here is an example:

In [7]: from __future__ import annotations

In [8]: class C:
   ...:     def func(cls, arg:str) -> C:
   ...:         pass
   ...:     

In [9]: c = C()