python singledispatch

关于singledispatch的知识不赘述,直接百度即可。

而singledispatch仅支持静态方法的dispatch,如果在class内部的方法则不行,因为第一个参数一直是self。

所以下面是一个实现class内部singledispatch的方法。

### 基础的singledispatch装饰器只能实现静态方法
from functools import singledispatch


class TestClass(object):
    @singledispatch
    def test_method(arg, verbose=False):
        if verbose:
            print("Let me just say,", end=" ")

        print(arg)

    @test_method.register(int)
    def _(arg):
        print("Strength in numbers, eh?", end=" ")
        print(arg)

    @test_method.register(list)
    def _(arg):
        print("Enumerate this:")

        for i, elem in enumerate(arg):
            print(i, elem)

if __name__ == '__main__':
    TestClass.test_method(55555)
    TestClass.test_method([33, 22, 11])

-------------------
### singledispatch装饰器只能实现静态方法,因为装饰器返回的第一个参数在类中总是self
# def wrapper(*args, **kw):
#        return dispatch(args[0].__class__)(*args, **kw)
    
# 第一种方法
from functools import singledispatch, update_wrapper

def methdispatch(func):
    dispatcher = singledispatch(func)
    def wrapper(*args, **kw):
        return dispatcher.dispatch(args[1].__class__)(*args, **kw)
    wrapper.register = dispatcher.register
    update_wrapper(wrapper, func)
    return wrapper
  
class Patchwork(object):

    def __init__(self, **kwargs):
        for k, v in kwargs.items():
            setattr(self, k, v)

    @methdispatch
    def get(self, arg):
        return getattr(self, arg, None)

    @get.register(list)
    def _(self, arg):
        return [self.get(x) for x in arg]

      
# 第二种方法
from functools import singledispatch

class TestClass(object):

    def __init__(self):
      
        self.test_method = singledispatch(self.test_method)
        self.test_method.register(int, self._test_method_int)
        self.test_method.register(list, self._test_method_list)

    def test_method(self, arg, verbose=False):
        if verbose:
            print("Let me just say,", end=" ")

        print(arg)

    def _test_method_int(self, arg):
        print("Strength in numbers, eh?", end=" ")
        print(arg)

    def _test_method_list(self, arg):
        print("Enumerate this:")

        for i, elem in enumerate(arg):
            print(i, elem)


if __name__ == '__main__':
    test = TestClass()
    test.test_method(55555)
    test.test_method([33, 22, 11])

重点关注这里即可:

def methdispatch(func):
    dispatcher = singledispatch(func)
    def wrapper(*args, **kw):
        return dispatcher.dispatch(args[1].__class__)(*args, **kw)
    wrapper.register = dispatcher.register
    update_wrapper(wrapper, func)
    return wrapper

这个装饰器的实际作用是把dispatch的原则调整为按照args[1]的type来dispatch。

以上代码来自于:参考资料
(粘过来的原因是github访问不太容易。。。)

posted @ 2021-07-28 17:04  xinze  阅读(185)  评论(0编辑  收藏  举报