Typing on child class' methods of a Generic base class

2022-03-09 Thread Nicolas Haller

Hello,

I am wondering about a situation involving typing, Generic and a child 
class.


The documentation about "user-defined generic types"[1] says that I can 
fix some types on a child class (class MyDict(Mapping[str, T]):) but 
doesn't say much about the signature of the methods I need to 
implement/override on that child class.


Should I keep the TypeVar and remember that I fixed the type(alternative 
1) or change the signature of the method to replace the TypeVar by the 
type I set (alternative 2)?


Mypy seems to prefer the second alternative but changing the signature 
feels wrong to me for some reason. That's why I'm asking :-)



Below is a small example to illustrate:

from abc import ABCMeta, abstractmethod
from typing import TypeVar, Generic


T = TypeVar("T")


class Base(Generic[T], metaclass=ABCMeta):
"""A base class."""

@abstractmethod
def _private_method(self, an_arg: T) -> T:
...

def public_method(self, an_arg: T) -> T:
from_private_method = self._private_method(an_arg)
return from_private_method


class Alternative1(Base[int]):
def _private_method(self, an_arg: T) -> T:  # I keep T
return 42


class Alternative2(Base[int]):
def _private_method(self, an_arg: int) -> int:  # I replace T
return 42


Thanks,

--
Nicolas Haller


[1]: 
https://docs.python.org/3/library/typing.html#user-defined-generic-types

--
https://mail.python.org/mailman/listinfo/python-list


Re: Typing on child class' methods of a Generic base class

2022-03-12 Thread Nicolas Haller

On 2022-03-10 12:31, Dieter Maurer wrote:

Nicolas Haller wrote at 2022-3-9 10:53 -0500:

...
The documentation about "user-defined generic types"[1] says that I can
fix some types on a child class (class MyDict(Mapping[str, T]):) but
doesn't say much about the signature of the methods I need to
implement/override on that child class.


I have the fealing that this is a case of (generic type) "specialization".
In this setup, `Mapping` would be a generic type with two type
variables `K` (the key type) and `V` (the value type).
The signatures of its methods would use those type variables.
In your example, you specialize the key type to `str` (and
leave the value type generic). The signatures of the methods
would automatically follow this specialization -- without the need
to do anything.


If I understand correctly, you're saying I should use the first 
alternative by keeping the signature as it is in the base class:

---
T = TypeVar("T")


class Base(Generic[T], metaclass=ABCMeta):
"""A base class."""

@abstractmethod
def _private_method(self, an_arg: T) -> T:
...

def public_method(self, an_arg: T) -> T:
from_private_method = self._private_method(an_arg)
return from_private_method

class Alternative1(Base[int]):
def _private_method(self, an_arg: T) -> T:  # I keep T
return 42
---

The problem with it is that mypy doesn´t seem quite happy with it:
./scratch.py:22: error: Incompatible return value type (got "int", 
expected "T")


Do you think this is error is incorrect? If so, I can open an issue with 
mypy.


Thanks,

--
Nicolas
--
https://mail.python.org/mailman/listinfo/python-list