Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python function annotation in class return type is the class raise undefined

Python 3.6.1, there are several ways of type hinting, in the doc string or annotation. How can I achieve this using annotation?

Say I have a class, which have a class method load to load data from somewhere, json or database for instance, and construct and return a instance of this class.

class Foo:

    @classmethod
    def load(cls, bar) -> Foo:
        pass

I think this is quite straightforward, but python interpreter raised an error that Foo is not defined.

I know the reason, because when python loads Foo's load's function signature, the Foo class's definition is not finished, so the Foo is not defined yet.

Is this a drawback of function annotation? Can I find some way to achieve this goal, instead of using doc string to type hint, since I really like the clearness of function annotation.

like image 374
AZLisme Avatar asked May 10 '17 03:05

AZLisme


People also ask

What is __ annotations __ in Python?

__annotations__ is a dict that provides some annotations about global(?) variables, classes, class attributes, function parameters and return types. __annotations__ is one of the names that is present in the top level scope ( __name__ == '__main__' ) as returned by dir() .

What is type annotation in Python?

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.

Can a python function return different types?

You can use any Python object as a return value. Since everything in Python is an object, you can return strings, lists, tuples, dictionaries, functions, classes, instances, user-defined objects, and even modules or packages.

How do you annotate code in Python?

First, annotations can be fully implemented as decorators. You can just define an @annotate decorator and have it take an argument name and a Python expression as arguments and then store them in the target function's annotations attribute. This can be done for Python 2 as well.


1 Answers

You can use string literals for forward references:

import typing


class Foo:

    @classmethod
    def load(cls, bar) -> 'Foo':
        pass


class Bar:

    @classmethod
    def load(cls, bar) -> Foo:
        pass


print(typing.get_type_hints(Foo.load))  # {'return': <class '__main__.Foo'>}
print(typing.get_type_hints(Bar.load))  # {'return': <class '__main__.Foo'>}
like image 94
Igonato Avatar answered Oct 03 '22 18:10

Igonato