I am playing around with python's 3.5 type hints. I was wondering how can I type hint the return type of a class method.
This is what I had in mind:
>>> class A():
@classmethod
def a(cls) -> A:
pass
Traceback (most recent call last):
File "<pyshell#24>", line 1, in <module>
class A():
File "<pyshell#24>", line 3, in A
def a(cls) -> A:
NameError: name 'A' is not defined
Clearly it does not work. I guess one way would be to do some sort of "forward declaration" like so:
>>> class A():
pass
>>> class A():
@classmethod
def a(cls) -> A:
pass
But that does not feel "pythonic". How do people normally solve this?
Forward references When a type hint contains names that have not been defined yet, that definition may be expressed as a string literal, to be resolved later.
https://www.python.org/dev/peps/pep-0484/#forward-references
The PEP text goes on to provide the following example:
class Tree:
def __init__(self, left: 'Tree', right: 'Tree'):
self.left = left
self.right = right
Apart from the provision for strings, there is a problem with your proposed workaround - if you do:
class A():
pass
class A():
@classmethod
def a(cls) -> A:
pass
The return value annotated in the (final and real) class A
is the object that was carrying A
name at the time the class body was processed - and that object is the stub class A
. So any tool that would check in a static or runtime analysis the return value of A.a()
would find it not to be equal the class A
.
So, if a work around as this is ever needed (I had needed it once, I forgot the context -it had not to do with annotations - ah - I recall now: it is in a project that automatically generates Python ctypes wrappers for a specific C library), the way to go is to create one single class, and to augment it afterwards with assignment statements. For your example, that would be:
class A:
pass
def a(self) -> A:
pass
A.a = a
del a
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With