Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type-Hinting Child class returning self

Is there any way to type an abstract parent class method such that the child class method is known to return itself, instead of the abstract parent.

class Parent(ABC):
    @abstractmethod
    def method(self) -> [what to hint here]:
        pass

class Child1(Parent)
    def method(self):
        pass

    def other_method(self):
        pass

class GrandChild1(Child1)
    def other_method_2(self):
        pass

This is more to improve autocompletes for IDEs like PyCharm or VScode's python plugin.

like image 866
dbokers Avatar asked Nov 22 '19 01:11

dbokers


People also ask

What does return self do in Python?

return self would return the object that the method was called from.

What is Classmethod?

The classmethod() is an inbuilt function in Python, which returns a class method for a given function.; Syntax: classmethod(function) Parameter :This function accepts the function name as a parameter. Return Type:This function returns the converted class method.

What is the type of self in Python?

Self is a convention and not a Python keyword . self is parameter in Instance Method and user can use another parameter name in place of it. But it is advisable to use self because it increases the readability of code, and it is also a good programming practice.

How do you override type in Python?

In Python method overriding occurs by simply defining in the child class a method with the same name of a method in the parent class.


1 Answers

So, the general approach is described in the docs here

import typing
from abc import ABC, abstractmethod

T = typing.TypeVar('T', bound='Parent') # use string

class Parent(ABC):
    @abstractmethod
    def method(self: T) -> T:
        ...

class Child1(Parent):
    def method(self: T) -> T:
        return self

    def other_method(self):
        pass

class GrandChild1(Child1):
    def other_method_2(self):
        pass

reveal_type(Child1().method())
reveal_type(GrandChild1().method())

And mypy gives us:

test_typing.py:22: note: Revealed type is 'test_typing.Child1*'
test_typing.py:23: note: Revealed type is 'test_typing.GrandChild1*'

Note, I had to keep using type-variables to get this to work, so when I originally tried to use the actual child class in the child class annotation, it (erroneously?) inherited the type in the grandchild:

class Child1(Parent):
    def method(self) -> Child1:
        return self

I'd get with mypy:

test_typing.py:22: note: Revealed type is 'test_typing.Child1'
test_typing.py:23: note: Revealed type is 'test_typing.Child1'

Again, I am not sure if this is expected/correct behavior. The mypy documentation currently has a warning:

This feature is experimental. Checking code with type annotations for self arguments is still not fully implemented. Mypy may disallow valid code or allow unsafe code.

like image 103
juanpa.arrivillaga Avatar answered Sep 23 '22 13:09

juanpa.arrivillaga