How should I annotate a @classmethod
that returns an instance of cls
? Here's a bad example:
class Foo(object):
def __init__(self, bar: str):
self.bar = bar
@classmethod
def with_stuff_appended(cls, bar: str) -> ???:
return cls(bar + "stuff")
This returns a Foo
but more accurately returns whichever subclass of Foo
this is called on, so annotating with -> "Foo"
wouldn't be good enough.
The trick is to explicitly add an annotation to the
cls
parameter, in combination withTypeVar
, for generics, andType
, to represent a class rather then the instance itself, like so:Normally, you can leave
cls
(andself
) unannotated, but if you need to refer to the specific subclass, you can add an explicit annotation. Note that this feature is still experimental and may be buggy in some cases. You may also need to use the latest version of mypy cloned from Github, rather then what's available on pypi -- I don't remember if that version supports this feature for classmethods.Just for completeness, in Python 3.7 you can use the
postponed evaluation of annotations
as defined in PEP563 by importingfrom __future__ import annotations
at the beginning of the file.Then for your code it'd look like