Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Self-reference or forward-reference of type annotations in Python [duplicate]

I'm trying to figure out how self-reference of types work with python3's type annotations - the docs don't specify anything regarding this.

As an example:

from typing import TypeVar, Optional, Generic  T = TypeVar('T') class Node(Generic[T]):     left = None     right = None     value = None      def __init__(         self, value: Optional[T],         left: Optional[Node[T]]=None,         right: Optional[Node[T]]=None,     ) -> None:         self.value = value         self.left = left         self.right = right 

This code generates the error:

Traceback (most recent call last):   File "node.py", line 4, in <module>     class Node(Generic[T]):   File "node.py", line 12, in Node     right: Optional[Node[T]]=None, NameError: name 'Node' is not defined 

This is using Python 3.5.1

like image 762
LiraNuna Avatar asked Mar 24 '16 04:03

LiraNuna


People also ask

What type is self Python?

Python3. Self is a convention and not a Python keyword . self is parameter in Instance Method and user can use another parameter name in place of it. But it is advisable to use self because it increases the readability of code, and it is also a good programming practice.

What is Python type annotation?

Type annotations — also known as type signatures — are used to indicate the datatypes of variables and input/outputs of functions and methods. In many languages, datatypes are explicitly stated. In these languages, if you don't declare your datatype — the code will not run.

What is TypeVar in Python?

It is a type variable. Type variables exist primarily for the benefit of static type checkers. They serve as the parameters for generic types as well as for generic function definitions.

Should you use type hints in Python?

Type hints work best in modern Pythons. Annotations were introduced in Python 3.0, and it's possible to use type comments in Python 2.7. Still, improvements like variable annotations and postponed evaluation of type hints mean that you'll have a better experience doing type checks using Python 3.6 or even Python 3.7.


1 Answers

PEP 0484 - Type Hints - The problem of forward declarations addresses the issue:

The problem with type hints is that annotations (per PEP 3107 , and similar to default values) are evaluated at the time a function is defined, and thus any names used in an annotation must be already defined when the function is being defined. A common scenario is a class definition whose methods need to reference the class itself in their annotations. (More general, it can also occur with mutually recursive classes.) This is natural for container types, for example:

...

As written this will not work, because of the peculiarity in Python that class names become defined once the entire body of the class has been executed. Our solution, which isn't particularly elegant, but gets the job done, is to allow using string literals in annotations. Most of the time you won't have to use this though -- most uses of type hints are expected to reference builtin types or types defined in other modules.

from typing import TypeVar, Optional, Generic  T = TypeVar('T') class Node(Generic[T]):     left = None     right = None     value = None      def __init__(         self,         value: Optional[T],         left: Optional['Node[T]']=None,         right: Optional['Node[T]']=None,     ) -> None:         self.value = value         self.left = left         self.right = right 

>>> import typing >>> typing.get_type_hints(Node.__init__) {'return': None,  'value': typing.Union[~T, NoneType],  'left': typing.Union[__main__.Node[~T], NoneType],  'right': typing.Union[__main__.Node[~T], NoneType]} 
like image 93
falsetru Avatar answered Oct 02 '22 22:10

falsetru