Juste pour ajouter un exemple d'une bonne utilisation de ma réponse ici, couplé avec des décorateurs d'un mécanisme simple pour multimethods peut être fait.
# This is in the 'mm' module
registry = {}
class MultiMethod(object):
def __init__(self, name):
self.name = name
self.typemap = {}
def __call__(self, *args):
types = tuple(arg.__class__ for arg in args) # a generator expression!
function = self.typemap.get(types)
if function is None:
raise TypeError("no match")
return function(*args)
def register(self, types, function):
if types in self.typemap:
raise TypeError("duplicate registration")
self.typemap[types] = function
def multimethod(function):
name = function.__name__
mm = registry.get(name)
if mm is None:
mm = registry[name] = MultiMethod(name)
types = tuple(function.__annotations__.values())
mm.register(types, function)
return mm
et un exemple d'utilisation:
from mm import multimethod
@multimethod
def foo(a: int):
return "an int"
@multimethod
def foo(a: int, b: str):
return "an int and a string"
if __name__ == '__main__':
print("foo(1,'a') = {}".format(foo(1,'a')))
print("foo(7) = {}".format(foo(7)))
Cela peut être fait par l'ajout des types pour le décorateur comme Guido de l'original post montre, mais en annotant les paramètres eux-mêmes est préférable car elle permet d'éviter la possibilité d'un mauvais appariement des paramètres et types.
Remarque: En Python, vous pouvez accéder aux annotations function.__annotations__
plutôt que d' function.func_annotations
le func_*
style a été supprimé sur Python 3.