关于python:Pythonic在类中使用Python3的functools.singledispatch的方法?

Pythonic way of using Python3's functools.singledispatch in a class?

我正在过渡到python3,并且一直在探索stdlib的一些功能。functools.singledispatch引起了我的注意,我一直在玩它。然而,当我在课堂上尝试使用它时,我遇到了一些问题。

它似乎不适用于在类中注册的函数,您可以通过直接调用fun.dispatch(type(arg))(argname=arg)使其工作,我想知道是否有更好的方法可以做到这一点。

我尝试使用@classmethod和@staticmethod作为注册的上面和下面的装饰器,但这不起作用。

下面是一个人为设计的示例,它在创建类时注册处理程序来转换输入参数,以确保它始终是一个列表。

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
from functools import singledispatch

class UrlDispatcher(object):

    @singledispatch
    def url_input(self, input):
        print('input wasn\'t dispatched', input)

    @url_input.register(str)
    def _(self, input):
        print('input is a str', input)
        self.input = [input]

    @url_input.register(list)
    def _(self, input):
        print('input is a list', input)
        self.input = input

    def __init__(self, arg):

        # Works, albeit clunkily
        self.url_input.dispatch(type(arg))(self,input=arg)

        # Always uses the base dispatcher
        self.url_input(input=arg)

a ="http://www.cnn.com"
b = ["http://www.google.com","http://www.slashdot.org"]

s1 = UrlDispatcher(a)
s2 = UrlDispatcher(b)


以下内容应该有效。我不知道这是否是最好的解决方案。

1
2
3
4
5
6
7
8
9
10
class Foo:
    def method(self, arg):
        _method(arg, self)

@functools.singledispatch
def _method(arg, self):
    ...

...
...


我找到了答案-你没有。

http://code.activestate.com/lists/python-dev/122554/

引用我在上面的网址上找到的一篇文章,我认为这是解释过的——简短的回答是"通用函数",用于无状态算法。我不知道这个定义。

Correct. OO and generic functions are different development paradigms,
and there are limitations on mixing them. Generic functions are for
stateless algorithms, which expect to receive all required input
through their arguments. By contrast, class and instance methods
expect to receive some state implicitly - in many respects, they
already are generic functions.

Thus, this is really a request for dual dispatch in disguise: you want
to first dispatch on the class or instance (through method dispatch)
and then dispatch on the second argument (through generic function
dispatch).

Dual dispatch is much harder than single dispatch and
"functools.singledispatch" does not and should not support it (it's in
the name). As PJE noted, you can use singledispatch with
staticmethods, as that eliminates the dual dispatch behaviour by
removing the class and instance based dispatch step. You can also
register already bound class and instance methods as implementations
for a generic function, as that also resolves the dual dispatch in a
way that means the single dispatch implementation doesn't even need to
be aware it is happening.