SwimBikeRun
SwimBikeRun

Reputation: 4460

Typehints for python class

Is it possible to typehint a class's self?

The reason being is basing a class off of an ambiguously dynamic class that has definitions given in hint stubs called BaseClassB and SubClassD.

I would have expected this to be valid python, but it's not. Is there a way to typehint the baseclass argument(s) to creating a class?

I'd also accept any tricks that get PyCharm to autocomplete off self correctly as an answer as this doesn't seem to be supported Python in 3.7.4.

e.g.

class MyClass(BaseClassAmbiguous: Union[BaseClassB, SubClassD])
    def func(self):
        self.self_doesnt_autocomplete_correctly
        self. # Desired functionality is this to autocomplete according to BaseClassB and SubClassD

Upvotes: 2

Views: 116

Answers (1)

Michael0x2a
Michael0x2a

Reputation: 63978

I suspect the reason why your type checker is choking on your code is because it's not actually valid syntax. The annotation in your base class list is a syntax error.

Probably the best available workaround is to just give BaseClassAmbiguous a fake type, like so:

from typing import Union, TYPE_CHECKING

if TYPE_CHECKING:
    class BaseClassAmbiguous(BaseClassB, SubClassD): pass
else:
    # Create your ambiguous base class however it's actually
    # constructed at runtime

class MyClass(BaseClassAmbiguous):
    def func(self) -> None:
        self.blah

Basically, lie to your type-checker and pretend that BaseClassAmbiguous directly inherits from your two classes. I'm not sure if Pycharm specifically supports this kind of thing, but it's something it in principle ought to support. (E.g. it's possible to do these kinds of shenanigans in Python).

That said, if you're going to use this approach, you're probably better off just having BaseClassAmbiguous actually inherit directly from both subclasses if at all possible.


To answer your original question, yes, it's legal to annotate the self method. That technique is usually reserved for when you want to have your self variable be generic -- see this example in PEP 484, and this mini-tutorial in the mypy docs.

But you could in principle annotate self using any type hint, really, including Unions, as long as it's not fundamentally incompatible with what your class really is -- your annotation for self would need to essentially be the same type as or a supertype of MyClass.

That said, this technique will likely not help you here: what you'd need is an intersection type, not a union type, and annotating self won't help resolve the syntax error in your base class list.

I think the more broad problem here is that the PEP 484 ecosystem doesn't necessarily deal well with ambiguous or dynamic base classes. Perhaps this is not possible to do in your case, but If I were in your shoes, I'd concentrate my efforts on making the base class more concrete.

Upvotes: 2

Related Questions