/
multimethodic.py
66 lines (43 loc) · 1.71 KB
/
multimethodic.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# -*- coding: utf-8 -*-
''' Multimethodic
An implementation of multimethods for Python, heavily influenced by
the Clojure programming language.
Copyright (C) 2010-2012 by Daniel Werner.
See the README file for information on usage and redistribution.
'''
class DefaultMethod(object):
def __repr__(self):
return '<DefaultMethod>'
Default = DefaultMethod()
class MultiMethod(object):
def __init__(self, name, dispatchfn):
if not callable(dispatchfn):
raise TypeError('dispatchfn must be callable')
self.dispatchfn = dispatchfn
self.methods = {}
self.name = name
def __call__(self, *args, **kwds):
dv = self.dispatchfn(*args, **kwds)
if dv in self.methods:
return self.methods[dv](*args, **kwds)
if Default in self.methods:
return self.methods[Default](*args, **kwds)
raise Exception("No matching method on multimethod '%s' and "
"no default method defined" % self.name)
def addmethod(self, func, dispatchval):
self.methods[dispatchval] = func
def removemethod(self, dispatchval):
del self.methods[dispatchval]
def method(self, dispatchval):
''' Decorates a function as a new method of this multimethod, to be
invoked when the dispatch function returns `dispatchval`.
The return value is the MultiMethod itself.
'''
def method_decorator(func):
self.addmethod(func, dispatchval)
# Return the multimethod itself
return self
return method_decorator
def __repr__(self):
return "<%s '%s'>" % (type(self).__name__, self.name)
__all__ = ['MultiMethod', 'Default']