functools.singledispatch

python标准模块functools中的singledispatch是一个装饰器,将普通函数转为泛型函数,这种泛型函数将根据第一个参数类型的不同表现出不同的行为,被装饰的函数是默认实现,如果有其他功能可以使用register进行注册。

1. 使用if 语句处理逻辑分支

这段话理解起来有一点费力,我们还是通过具体的案例来说明吧

class Stu(object):
    def __init__(self, name):
        self.name = name

    def wake_up(self):
        print('起床')

class Police(object):
    def __init__(self, name):
        self.name = name

    def wake_up(self):
        print('起床')

stu = Stu('小明')
police = Police('小明爸爸')

def wake_up(obj):
    if isinstance(obj, Stu):
        print('今天周末休息,让孩子们再睡一会')
    elif isinstance(obj, Police):
        print('警察很辛苦,又要起床了')
        obj.wake_up()
    else:
        print('不处理')

wake_up(stu)
wake_up(police)
wake_up('一个字符串')

在上面这段代码里,我主要做了一下几件事情

  1. 定义了Stu类,Police类
  2. 定义了函数wake_up
  3. 调用wake_up函数唤醒stu,police,和一个字符串

在函数wake_up里,传入的参数类型是不一样的,函数要根据obj类型的不同来决定自己的行为,假设obj可能有10种类型,那么我就得在wake_up函数里用if ... elif 写10个逻辑分支来处理,这是一件非常痛苦的事情,而singledispatch就是为了解决这个问题而引入的

2. 使用singledispatch处理逻辑分支

from functools import singledispatch

class Stu(object):
    def __init__(self, name):
        self.name = name

    def wake_up(self):
        print('起床')

class Police(object):
    def __init__(self, name):
        self.name = name

    def wake_up(self):
        print('起床')


@singledispatch
def wake_up(obj):
    print('不处理')


@wake_up.register(Stu)
def wake_stu(obj):
    print('今天周末休息,让孩子们再睡一会')


@wake_up.register(Police)
def wake_police(obj):
    print('警察很辛苦,又要起床了')
    obj.wake_up()


stu = Stu('小明')
police = Police('小明爸爸')

wake_up(stu)
wake_police(police)
wake_up('一个字符串')

wake_up被singledispatch装饰以后,变成了泛型函数,使用@wake_up.register注册一个类型来装饰一个函数,这个函数就专门来处理对应类型的数据。我这里没有注册字符串,当第一个参数是没有被注册的类型时,默认使用wake_up来处理。

扫描关注, 与我技术互动

QQ交流群: 211426309

加入知识星球, 每天收获更多精彩内容

分享日常研究的python技术和遇到的问题及解决方案