I would like to use functools.singledispatchmethod to overload the binary arithmetic operator methods of a class called Polynomial. The problem I have is that I can't find a way to register method calls where other is a Polynomial.
Perhaps better explained with a simple example:
from __future__ import annotations
from functools import singledispatchmethod
class Polynomial:
@singledispatchmethod
def __add__(self, other):
return NotImplemented
@__add__.register
def _(self, other: Polynomial):
return NotImplemented
The code above raises a NameError:
NameError: name 'Polynomial' is not defined
This NameError is not caused by the annotation but is raised inside functools. Also, annotating using a string 'Polynomial' instead without the need of __future__.annotations doesn't work either. This behavior is not documented in the documentation for functools.singledispatchmethod.
I can make it work by making Polynomial inherit from another class, and then using that class in the type annotation:
from functools import singledispatchmethod
class _Polynomial:
pass
class Polynomial(_Polynomial):
@singledispatchmethod
def __add__(self, other):
return NotImplemented
@__add__.register
def _(self, other: _Polynomial):
return NotImplemented
..but I am not overly fond of this solution.
How can I make this work without needing the useless intermediate class?
The alternative is to add the methods after the class definition:
You can't actually reference the class during a class definition, because the class doesn't exist yet. Using the
from __future__ import annotationsmakes annotations get saved as strings, but as soon as the decorator tries to evaluate those strings for their values, the same problem occurs, so it doesn't get around it (because it isn't a mere annotation).This is evident in the stack trace (abbreviated):
So, when the
singledispatchmethoddecoratertyping.get_type_hints, which is essentiallyeval(with the added feature of taking care to obtain the correct global scope to evaluate the string in, the one where the annotation was made)