class AnnotationSupport(type): '''Preload a class with a deferred reference to itself. After the class is created, scan function annotations and replace the deferred references with the actual class. ''' @classmethod def __prepare__(mcl, name, bases): return {name: type(name, bases, {})} def __new__(mcl, name, bases, mapping): deferred = mapping.pop(name) cls = super().__new__(mcl, name, bases, mapping) for attrname, attrvalue in vars(cls).items(): annotations = getattr(attrvalue, '__annotations__', {}) for var, kind in annotations.items(): if kind is deferred: annotations[var] = cls return cls if __name__ == '__main__': class Set(metaclass=AnnotationSupport): 'Example of class that needs self-referencing function annotations' def union(self: Set, other: Set) -> Set: return Set(list(self) + list(other)) print('Set id:', id(Set)) print('Set vars:', list(vars(Set))) print('Set.union.__annotations:', Set.union.__annotations__) print('Id of return type:', id(Set.union.__annotations__['return']))