You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Problems using class type variable in class methods #3645
I would simplify the example to show only the essential part:
classFactory(Generic[T]):
defproduce(self) ->T:
...
@classmethoddefget(cls) ->T:
returncls().produce()
classHelloWorldFactory(Factory[str]):
defproduce(self) ->str:
return'Hello World'reveal_type(HelloWorldFactory.get()) # mypy should be able to infer 'str' here
On one hand, type variables are bound on instances, not on classes, but in case of a non-generic subclass I think the type variable can be bound on that class. The problem however is that we need to give a clear error message when this is not possible, something like (using above example):
Factory.get() # E: cannot bind type variable on class (use an instance or a non-generic subclass)Facrory[int].get() # E: cannot bind type variable on class (use an instance or a non-generic subclass)
Similar issues have come up previously, so this would perhaps be a reasonable feature to have eventually -- at least assuming the implementation isn't very complex.
changed the title [-]"Incompatible return value" error for classmethod generic subclasses[/-][+]Problems using class type variable in class methods[/+]on Jul 3, 2017
The produce() method is also irrelevant to the example. Shorter yet self-contained:
fromtypingimportGeneric, TypeVarT=TypeVar('T')
classFactory(Generic[T]):
@classmethoddefget(cls) ->T: ...
classHelloWorldFactory(Factory[str]): passreveal_type(HelloWorldFactory.get()) # mypy should be able to infer 'str' here
Reacted by LiraNuna, Noah Goetz, bwo, Roy Williams and kitsuyui
@rowillia My recommendation is to use a regular method instead of a class method. Example:
fromtypingimportGeneric, TypeVarT=TypeVar('T')
classFactory(Generic[T]):
defget(cls) ->T: ...
class_HelloWorldFactory(Factory[str]): passHelloWorldFactory=_HelloWorldFactory() # This singleton is mostly for conveniencereveal_type(HelloWorldFactory.get()) # this is 'str'
You can avoid the singleton by using HelloWorldFactory().get() instead.
Oh, I think in this case it's basically equivalent to a top-level function returning G[T]: there is nothing to constrain the value of the typevar, so mypy infers "". I believe there's a separate issue about that.
If this is the case, then why is ... not itself an error?
Because it is not, it may be bound in a subclass as said few word later in the comment you quote, there is even a simple example just few comments above #3645 (comment)
Activity
ilevkivskyi commentedon Jul 1, 2017
I would simplify the example to show only the essential part:
On one hand, type variables are bound on instances, not on classes, but in case of a non-generic subclass I think the type variable can be bound on that class. The problem however is that we need to give a clear error message when this is not possible, something like (using above example):
JukkaL commentedon Jul 3, 2017
Similar issues have come up previously, so this would perhaps be a reasonable feature to have eventually -- at least assuming the implementation isn't very complex.
[-]"Incompatible return value" error for classmethod generic subclasses[/-][+]Problems using class type variable in class methods[/+]gvanrossum commentedon Jul 5, 2017
The
produce()method is also irrelevant to the example. Shorter yet self-contained:rowillia commentedon Feb 24, 2018
@JukkaL Do you have any thoughts on what it would take to fix this? It's blocking us here at Lyft.
JukkaL commentedon Feb 26, 2018
@rowillia My recommendation is to use a regular method instead of a class method. Example:
You can avoid the singleton by using
HelloWorldFactory().get()instead.glyph commentedon Apr 18, 2018
I bumped into this bug today as well, and was surprised to see this comment:
If this is the case, then why is
not itself an error? being able to say
G[T]at least implies to me thatTis bound.JelleZijlstra commentedon Apr 18, 2018
That method returns an instance of
G[T].glyph commentedon Apr 18, 2018
According to
reveal_typeit returns an instance ofG[<nothing>].glyph commentedon Apr 18, 2018
More specifically:
G[int].m()returnsG[<nothing>].JelleZijlstra commentedon Apr 18, 2018
Oh, I think in this case it's basically equivalent to a top-level function returning
G[T]: there is nothing to constrain the value of the typevar, so mypy infers "". I believe there's a separate issue about that.ilevkivskyi commentedon Apr 18, 2018
@glyph
Because it is not, it may be bound in a subclass as said few word later in the comment you quote, there is even a simple example just few comments above #3645 (comment)
Fix member access on generic classes (#6418)
LiraNuna commentedon Feb 24, 2019
@ilevkivskyi Thank you for fixing this issue!