Consider the following code:
# foo.py
class A:
def _foo():
print('hello world')
bar = {'foo': _foo}
def run_bar(self):
self.bar['foo']()
def main():
A().run_bar()
if __name__ == '__main__':
raise SystemExit(main())
It runs just fine with Python 3.9.5:
python3.9 foo.py
> hello world
but mypy will give me the following error:
mypy foo.py
> foo.py:2: error: Method must have at least one argument
> Found 1 error in 1 file (checked 1 source file)
Is there a way to tell mypy that this function will only ever get called as a class variable ? If no, is this bad practice? I know I could simply add # type: ignore
, but that seems too hacky.
Two ways of doing this:
1. Use a staticmethod
Either like this:
from typing import Callable, Any
class A:
bar: dict[str, Callable[..., Any]] = {}
def __init__(self):
self.bar.update({'foo': self._foo})
@staticmethod
def _foo():
print('hello world')
def run_bar(self):
self.bar['foo']()
def main():
A().run_bar()
if __name__ == '__main__':
raise SystemExit(main())
Or like this:
class A:
@staticmethod
def _foo():
print('hello world')
def run_bar(self):
getattr(self, '_foo')()
def main():
A().run_bar()
if __name__ == '__main__':
raise SystemExit(main())
2. Put the function outside of the class
def _foo():
print('hello world')
class A:
bar = {'foo': _foo}
def run_bar(self):
self.bar['foo']()
def main():
A().run_bar()
if __name__ == '__main__':
raise SystemExit(main())