I am trying to implement a multimethod approach based on this article http://www.artima.com/weblogs/viewpost.jsp?thread=101605. There are two differences from this approach:
- I only need to look at the first argument of the multimethod, so no need to form tuples of arg classes
- The multimethods will live in classes, they will not be regular functions.
However I mixed up my classes a bit, and the call to self
gets lost while dispatching a call to a class method.
Here is my code:
method_registry = {}
class SendMessageMultiMethod(object):
"""
A class for implementing multimethod functionality
"""
def __init__(self, name):
self.name = name
self.typemap = {}
def __call__(self, message, extra_payload=None):
"""
Overrriding method call and dispatching it to an actual method
based on the supplied message class
"""
first_arg_type = message.__class__
function = self.typemap.get(first_arg_type)
print(
'Dispatching to function {} with message {} and extra payload {}...'
.format(function, message, extra_payload)
)
return function(message, extra_payload)
def register(self, type_, function):
self.typemap[type_] = function
def use_for_type(*types):
"""
A decorator that registers a method to use with certain types
"""
def register(method):
"""Creating Multimethod with the method name
and registering it at at method_registry dict """
name = method.__name__
mm = method_registry.get(name)
if mm is None:
mm = method_registry[name] = SendMessageMultiMethod(name)
for type_ in types:
mm.register(type_, method)
return mm
return register
class Sender(object):
def send_messages(self, messages_list):
for message in messages_list:
# this is supposed to fire different send_message() methods
# for different arg types
self.send_message(message)
@use_for_type(int, float)
def send_message(self, message, *args, **kwargs):
print('received call for int/float message {} with {}, {}'
.format(message, args, kwargs))
print('self is {}'.format(self))
@use_for_type(bool)
def send_message(self, message, *args, **kwargs):
print('received call for bool message {} with {}, {}'
.format(message, args, kwargs))
print('self is {}'.format(self))
So when I call the send_messages
method on a Sender
class I receive the arguments in self
, not in message
variables. Here:
sender = Sender()
sender.send_messages([1, 2, True, 5.6])
output:
Dispatching to function <function Sender.send_message at 0x1013608c8> with message 1 and extra payload None...
received call for int/float message None with (), {}
self is 1
Dispatching to function <function Sender.send_message at 0x1013608c8> with message 2 and extra payload None...
received call for int/float message None with (), {}
self is 2
Dispatching to function <function Sender.send_message at 0x101360950> with message True and extra payload None...
received call for bool message None with (), {}
self is True
Dispatching to function <function Sender.send_message at 0x1013608c8> with message 5.6 and extra payload None...
received call for int/float message None with (), {}
self is 5.6
how do I not lose self
and dispatch the message contents to the message
variable?