Why is the name of the containing class not recognized as a return value function annotation? [duplicate] Why is the name of the containing class not recognized as a return value function annotation? [duplicate] python python

Why is the name of the containing class not recognized as a return value function annotation? [duplicate]


Trie is a valid expression, and evaluates to the current value associated with the name name Trie. But that name is not defined yet -- a class object is only bound to its name after the class body has run to completition. You'll note the same behavior in this much simpler example:

class C:    myself = C    # or even just    C

Normally, the workaround would be setting the class attribute after the class has been defined, outside the class body. This is not a really good option here, though it works. Alternatively, you could use any placeholder value in the initial definition, then replace it in the __annotations__ (which is legal because it's a regular dictionary):

class C:    def f() -> ...: passprint(C.f.__annotations__)C.f.__annotations__['return'] = Cprint(C.f.__annotations__)

It does feel rather hacky though. Depending on your use case, it might be possible to instead use a sentinel object (e.g. CONTAINING_CLASS = object()) and leave interpreting that to whatever actually processes the annotations.


PEP 484 provides an official solution to this in the form of forward references.

When a type hint contains names that have not been defined yet, that definition may be expressed as a string literal, to be resolved later.

In the case of the question code:

class Trie:    @staticmethod    def from_mapping(mapping) -> Trie:        # docstrings and initialization ommitted        trie = Trie()        return trie

Becomes:

class Trie:    @staticmethod    def from_mapping(mapping) -> 'Trie':        # docstrings and initialization ommitted        trie = Trie()        return trie