我正在尝试基于本文http://www.artima.com/weblogs/viewpost.jsp?thread=101605实现多方法方法。这种方法有两点不同:
但是我把我的类混淆了一下,调用self
时调用类方法的调用就丢失了。
这是我的代码:
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))
因此,当我在send_messages
课程上调用Sender
方法时,我会在self
中收到参数,而不是message
个变量。这里:
sender = Sender()
sender.send_messages([1, 2, True, 5.6])
输出:
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
如何不丢失self
并将邮件内容发送到message
变量?
答案 0 :(得分:2)
正如def send_message(self, message, *args, **kwargs)
之类的Python方法签名所示,方法的第一个参数必须是self
对象。通常,通过执行obj.send_message
,您可以访问对象的方法,而不是类'。请尝试以下方法:
>>> class Foo():
... def bar(self):
... pass
>>> Foo.bar
<function __main__.Foo.bar>
>>> Foo().bar
<bound method Foo.bar of <__main__.Foo object at 0x7f5fd927cc18>>
绑定方法意味着已经指定了self
。
您的@use_for_type
装饰器在类级别工作,所以在send_message
函数上,而不是绑定方法。
现在只是找出明确传递self
代码丢失的地方,而__call__
- self
中的一件事就是SendMessageMultiMethod
对象,而不是Sender
对象 - 以及装饰者:
class SendMessageMultiMethod(object):
...
# note the `self_` parameter
def __call__(self, self_, message, extra_payload=None):
...
return function(self_, message, extra_payload)
def use_for_type(*types):
...
def register(method):
...
return lambda self, *args, **kwargs: mm(self, *args, **kwargs)
输出:
Dispatching to function <function Sender.send_message at 0x7f1e427e5488> with message 1 and extra payload None...
received call for int/float message 1 with (None,), {}
self is <__main__.Sender object at 0x7f1e4277b0f0>
Dispatching to function <function Sender.send_message at 0x7f1e427e5488> with message 2 and extra payload None...
received call for int/float message 2 with (None,), {}
self is <__main__.Sender object at 0x7f1e4277b0f0>
Dispatching to function <function Sender.send_message at 0x7f1e427e5598> with message True and extra payload None...
received call for bool message True with (None,), {}
self is <__main__.Sender object at 0x7f1e4277b0f0>
Dispatching to function <function Sender.send_message at 0x7f1e427e5488> with message 5.6 and extra payload None...
received call for int/float message 5.6 with (None,), {}
self is <__main__.Sender object at 0x7f1e4277b0f0>