Closed
Description
A colleague and I were wondering how to define a copy() method in a base class so that when called on an instance of a subclass it is known that it returns an instance of that subclass. We found the following solution:
T = TypeVar('T')
class Copyable:
def copy(self: T) -> T:
return self.__class__() # type: ignore
class X(Copyable):
def foo(self):
pass
x = X()
x.foo()
xx = x.copy()
xx.foo() # OK
Note that the # type: ignore
is required for two reasons: you can't call self.__class__()
, and it doesn't like the return type. Try e.g. return self
and you get
x.py:5: error: Incompatible return value type: expected T`-1, got x.Copyable
It works in --py2
mode too:
def copy(self):
# type: (T) -> T
return self.__class__() # type: ignore
UPDATE: This doesn't actually work. :-( See next comment.
Activity
JukkaL commentedon Feb 10, 2016
Hmm if this works it's not by design. I actually get errors when type checking the example:
To make this work properly we could provide a new kind of type: a "self" type, which is basically the concrete type of
self
(in a derived class it would refer to the derived class, even if the definition is inherited). It's been used in a bunch of languages, though I'm not sure if any mainstream language has it. To make it work well we'd also need to support callingself.__class__
.We could have something like this:
SelfType
would probably only be usable in a covariant position such as in a return type.self
andself.__class__(...)
would have the typeSelfType
.gvanrossum commentedon Feb 10, 2016
Oh, I could have sworn that it worked but it was late. :-( So yes, I guess this is two feature requests:
SelfType
and callingself.__class__
.[-]How to define a copy() function -- clever solution![/-][+]How to define a copy() function[/+]gvanrossum commentedon Feb 10, 2016
(It seems to work when the class is generic, but who knows what other effects that has.)
Parse `lambda (x): x` correctly. Fix #1212.
38 remaining items
python/mypy#1212 has been fixed, so this comment can be replaced
kyprifog commentedon Apr 28, 2020
For anyone else that stumbles on this and is looking for the SelfType application, this helped me:
#3661
Use correct return type annotation for BaseException.with_traceback (#…
Allow covariants of __enter__, __aenter__, and @classmethod (#1336)
Allow covariants of __enter__, __aenter__, and @classmethod (#1336)