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