python / python/mypy

Generic class with constrained type vars

Offen
#5,416 7 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

bug false-positive priority-1-normal topic-type-variables
Vorherrschende Sprache
Python
Sterne
20.6k
Forks
3.3k
PR-Merge-Kennzahlen
PR-Kennzahlen ausstehend

Beschreibung

On Python 3.7.0 and mypy 0.620, I'm getting some error messages I don't understand. The Mypy documentation and PEP 484 didn't clear it up for me. Maybe it's a bug in Mypy. Maybe I don't understand type erasure. In case it's the former, here's a minimal example. In case it's the latter, please help.

In the following examples, the fact that m does not return is not critical. In the real code that gave me these errors, m is an abstract method, which also doesn't change anything important.

Put the following examples in mypy-test.py to get the corresponding output from running mypyt mypy-test.py. The first and the last examples are the ones that are baffling me.

classmethod with constrained type variable

from typing import TypeVar, Generic
T = TypeVar('T', int, str)
class K(Generic[T]):
	@classmethod
	def m(cls) -> T:
		raise NotImplementedError

Mypy output:

mypy-test.py:5: error: The erased type of self 'def [T in (builtins.int, builtins.str)] () -> mypy-test.K[builtins.int*]' is not a supertype of its class 'Type[mypy-test.K[T`1]]'
mypy-test.py:5: error: The erased type of self 'def [T in (builtins.int, builtins.str)] () -> mypy-test.K[builtins.str*]' is not a supertype of its class 'Type[mypy-test.K[T`1]]'

classmethod with generic self

from typing import TypeVar, Generic
S = TypeVar('S')
T = TypeVar('T', int, str)
class K(Generic[T]):
	@classmethod
	def m(cls: S) -> T:
		raise NotImplementedError

produces no error.

classmethod with unconstrained type variable

from typing import TypeVar, Generic
T = TypeVar('T')
class K(Generic[T]):
	@classmethod
	def m(cls) -> T:
		raise NotImplementedError

produces no error.

instance method with constrained type

from typing import TypeVar, Generic
T = TypeVar('T', int, str)
class K(Generic[T]):
	def __init__(self, t: T) -> None:
		self.t = t

produces

mypy-test.py:5: error: Need type annotation for 't'

instance method with unconstrained type

from typing import TypeVar, Generic
T = TypeVar('T')
class K(Generic[T]):
	def __init__(self, t: T) -> None:
		self.t = t

produces no error.

instance method with constrained type and inheritance

from typing import TypeVar, Generic
T = TypeVar('T', int, str)
class K(Generic[T]):
	def __init__(self, t: T) -> None:
		self.t: T = t

class L(K[T]):
	def __init__(self, t: T) -> None:
		self.u = 1
		super().__init__(t=t)

produces

mypy-test.py:10: error: Argument "t" to "__init__" of "K" has incompatible type "int"; expected "T"
mypy-test.py:10: error: Argument "t" to "__init__" of "K" has incompatible type "str"; expected "T"

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Reproduziere die Beispiele in mypy-test.py mit Python 3.7.0 und mypy 0.620, beginnend mit den eingeschränkten und uneingeschränkten generischen Klassenmethoden. Vergleiche die Diagnosen für Klassenmethoden, Instanzattribute und geerbte Konstruktoren und ermittle anschließend das beabsichtigte Verhalten, bevor du entscheidest, ob Implementierungsänderungen oder Regressionstests erforderlich sind.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
python
Bereich
devtools
Issue-Typ
Bug
Schwierigkeit
5/5
Geschätzter Aufwand
Über eine Woche
Aktivitätsstatus
Veraltet
Klarheit
Muss geklärt werden
Anfängerfreundlichkeit
25/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.