简体   繁体   中英

Python generics and subclasses

I'm trying to add type annotations to an existing package, and clearly I'm missing something important. I have an abstract superclass, and subclasses. The superclass should be generic, whereas the subclasses should be for a specific type. Here's a simple example if that I see, and what I'd like to see:

from typing import Generic, TypeVar

T = TypeVar("T")

class A(Generic[T]):
    def method(self, arg: T):
        ...

class B(A[int]):
    def method(self, arg):
        reveal_locals()

Expected (or at least hoped for):

GenericTest.py:11: note: Revealed local types are:
GenericTest.py:11: note:     arg: int
GenericTest.py:11: note:     self: Any

Got:

GenericTest.py:11: note: Revealed local types are:
GenericTest.py:11: note:     arg: Any
GenericTest.py:11: note:     self: Any

reveal_locals() prints the types of the variables inferred by mypy in the scope where the call its placed. And when redefining a method in a subclass, you are also overriding the annotations ( Any is used by default when no parameter annotation is given explicitly)

This could be more clear:

class A(Generic[T]):
    def method(self, arg: T):
        ...

class B(A[int]):
    def method(self, arg):
        pass

B().method('')

The above code is fine for mypy but the next gives an error:

class C(A[int]):
    pass

C().method('')
error: Argument 1 to "method" of "A" has incompatible type "str"; expected "int"

You need to add type annotations to the methods in your subclass. So doing:

from typing import Generic, TypeVar

T = TypeVar("T")

class A(Generic[T]):
    def method(self, arg: T) -> None:
        ...

class B(A[int]):
    def method(self, arg: int) -> None:
        reveal_locals()

...results in the expected output of:

test.py:11: note: Revealed local types are:
test.py:11: note:     arg: builtins.int
test.py:11: note:     self: test.B

If a function is not annotated with type hints, mypy will treat that function as being dynamically typed and assume all of its arguments are of type Any .

If you would like mypy to warn you when you forget type hints like this, run mypy with the --disallow-untyped-defs command line flag -- and also maybe --disallow-incomplete-defs for good measure. Or alternatively, run mypy with the --strict flag, which automatically enables the above two flags (and more).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM