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
Actually it seems that the signature of A.func should be rejected, since T is not defined at class/static method level, since the type variable is specific to an instance, and we have no self. Type variables should not be in scope for static or class methods. I'm going to move this to 0.4 since this seems like a pretty rare edge case.
It also seems consistent to turn the class typevars into function typevars for a static method call, like we do for constructors. We could give A.func the type def [T] () -> T, and B.func the type def () -> B. Hard to say whether that is useful without some realistic examples.
That would seem useful for constructors. I can't think of any off the bat
but I betcha there are some classes that take AnyStr and have a handy
alternate constructor that's a class or static method.
class A(Generic[T]):
a = [] # type: List[T]
class B(A[int]): pass
What is the type of B.a? For that matter what is the type of A.a?
This issue is actually more severe, because on the one hand we cannot give A.a any sort of generic type (only functions can be generic in mypy currently, and besides it would not be type safe to give A.a a type like forall T. List[T], as it is a mutable variable); and on the other hand the style of declaring class variables in order to specify the types of instance variables is used frequently, at least in mypy itself, and if we want to do the same in generic classes, we need to be able to make declarations like that of A.
Yeah, but mypy's handling of class attributes is just really poor, and the
meaning of that example isn't clear, because we do type erasure -- at
runtime there's only one A and it has only one a.
OTOH for classmethod/staticmethod it makes sense to be generic? Well I
guess interpreting them as generic functions works too, so actually Jukka
is right about that. Sorry.
Hard to say whether that is useful without some realistic examples.
The issue was encounter when I wanted to force a subclass to implement a method to return an instance of the subclass (and this way, force a constructor).
If you want to have some code example (the main idea is to parse XML from nexpose API), it is the XmlParse class which force his childs to have the from_xml method. You can see how it used in the Message class.
@tharvik I'm not sure if your example is possible to be fully annotated via PEP 484, as type variables are specific to instances. Currently having an Any return type in the XmlParse class seems like the only option. If/when mypy will support 'self types' (#1212), they might be helpful in your use case.
@rwbarton If a class-level variable has a type based on a type variable, mypy should enforce that this variable should only be accessed via an instance, not via the class object. If we add that restriction, things should be fine.
Having generic class methods and static methods is fine, but they should perhaps use a separate type variable, not a class-level type variable. However, we could implicitly understand a class-level type variable as a method-level one if used in a static or class method, but that might be a little confusing.
@JukkaL, is there anything wrong with continuing to turn class type variables that appear in class methods into function type variables, like we do now (and very similar to how the signature of __init__ is treated)?
What I'm going to implement is just mapping class type variables from the superclass before turning them into function type variables (as already happens for __init__). I think this will allow the above use case.
@rwbarton I think it's fine to turn class type variables into function type variables, but if we make this a real feature we should test that there is unlikely to be confusion (by mypy) between two different kinds of type variables in a single scope, as discussed above.
Activity
gvanrossum commentedon Apr 6, 2016
@rwbarton Another typevar mystery you might look into?
JukkaL commentedon Apr 14, 2016
Actually it seems that the signature of
A.funcshould be rejected, sinceTis not defined at class/static method level, since the type variable is specific to an instance, and we have noself. Type variables should not be in scope for static or class methods. I'm going to move this to 0.4 since this seems like a pretty rare edge case.rwbarton commentedon Apr 14, 2016
It also seems consistent to turn the class typevars into function typevars for a static method call, like we do for constructors. We could give
A.functhe typedef [T] () -> T, andB.functhe typedef () -> B. Hard to say whether that is useful without some realistic examples.gvanrossum commentedon Apr 14, 2016
rwbarton commentedon Apr 14, 2016
This is also an issue for class attributes:
What is the type of
B.a? For that matter what is the type ofA.a?This issue is actually more severe, because on the one hand we cannot give
A.aany sort of generic type (only functions can be generic in mypy currently, and besides it would not be type safe to giveA.aa type likeforall T. List[T], as it is a mutable variable); and on the other hand the style of declaring class variables in order to specify the types of instance variables is used frequently, at least in mypy itself, and if we want to do the same in generic classes, we need to be able to make declarations like that ofA.gvanrossum commentedon Apr 14, 2016
Yeah, but mypy's handling of class attributes is just really poor, and the
meaning of that example isn't clear, because we do type erasure -- at
runtime there's only one A and it has only one a.
OTOH for classmethod/staticmethod it makes sense to be generic? Well I
guess interpreting them as generic functions works too, so actually Jukka
is right about that. Sorry.
tharvik commentedon Apr 15, 2016
The issue was encounter when I wanted to force a subclass to implement a method to return an instance of the subclass (and this way, force a constructor).
If you want to have some code example (the main idea is to parse XML from nexpose API), it is the XmlParse class which force his childs to have the from_xml method. You can see how it used in the Message class.
JukkaL commentedon Apr 15, 2016
@tharvik I'm not sure if your example is possible to be fully annotated via PEP 484, as type variables are specific to instances. Currently having an
Anyreturn type in theXmlParseclass seems like the only option. If/when mypy will support 'self types' (#1212), they might be helpful in your use case.@rwbarton If a class-level variable has a type based on a type variable, mypy should enforce that this variable should only be accessed via an instance, not via the class object. If we add that restriction, things should be fine.
Having generic class methods and static methods is fine, but they should perhaps use a separate type variable, not a class-level type variable. However, we could implicitly understand a class-level type variable as a method-level one if used in a static or class method, but that might be a little confusing.
methane commentedon Jun 2, 2016
Here is another realistic example.
https://gist.github.com/methane/d18c66d38b1916e7c36883c0a83f0a01
This demonstrates "Repository Pattern". [1]
Since repository is singleton for many cases, I want to implement it by classmethod.
[1] https://msdn.microsoft.com/en-us/library/ff649690.aspx
rwbarton commentedon Jun 29, 2016
@JukkaL, is there anything wrong with continuing to turn class type variables that appear in class methods into function type variables, like we do now (and very similar to how the signature of
__init__is treated)?What I'm going to implement is just mapping class type variables from the superclass before turning them into function type variables (as already happens for
__init__). I think this will allow the above use case.Map class type parameters to superclass when checking class method use
JukkaL commentedon Jun 29, 2016
@rwbarton I think it's fine to turn class type variables into function type variables, but if we make this a real feature we should test that there is unlikely to be confusion (by mypy) between two different kinds of type variables in a single scope, as discussed above.
elazarg commentedon Oct 19, 2017
This should be possible to solve with a slightly better unification for self-type (currently it does only the minimal effort).
Fix member access on generic classes (#6418)