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() -> ...: pass
print(C.f.__annotations__)
C.f.__annotations__['return'] = C
print(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.