技术迷

Good Luck To You!

白学这么多年 Python ?连泛型函数都不会写?

泛型,如果你尝过java,应该对他不陌生吧。但你可能不知道在 Python 中(3.4+ ),也可以实现 简单的泛型函数。


在Python中只能实现基于单个(第一个)参数的数据类型来选择具体的实现方式,官方名称 是 single-dispatch。你或许听不懂,说人话,就是可以实现第一个参数的数据类型不同,其调用的函数也就不同。


singledispatch 是 PEP443 中引入的,如果你对此有兴趣,PEP443 应该是最好的学习文档:https://www.python.org/dev/peps/pep-0443/


它使用方法极其简单,只要被singledispatch 装饰的函数,就是一个single-dispatch 的泛函数(generic functions)。


单分派:根据一个参数的类型,以不同方式执行相同的操作的行为。

多分派:可根据多个参数的类型选择专门的函数的行为。

泛函数:多个函数绑在一起组合成一个泛函数。

这边举个简单的例子。


CopyCopy

from functools import singledispatch


@singledispatch

def age(obj):

    print('请传入合法类型的参数!')


@age.register(int)

def _(age):

    print('我已经{}岁了。'.format(age))


@age.register(str)

def _(age):

    print('I am {} years old.'.format(age))



age(23)  # int

age('twenty three')  # str

age(['23'])  # list

执行结果


CopyCopy

我已经23岁了。

I am twenty three years old.

请传入合法类型的参数!

说起泛型,其实在 Python 本身的一些内建函数中并不少见,比如 len() , iter(),copy.copy() ,pprint() 等


你可能会问,它有什么用呢?实际上真没什么用,你不用它或者不认识它也完全不影响你编码。


我这里举个例子,你可以感受一下。


大家都知道,Python 中有许许多的数据类型,比如 str,list, dict, tuple 等,不同数据类型的拼接方式各不相同,所以我这里我写了一个通用的函数,可以根据对应的数据类型对选择对应的拼接方式拼接,而且不同数据类型我还应该提示无法拼接。以下是简单的实现。


CopyCopy

def check_type(func):

    def wrapper(*args):

        arg1, arg2 = args[:2]

        if type(arg1) != type(arg2):

            return '【错误】:参数类型不同,无法拼接!!'

        return func(*args)

    return wrapper



@singledispatch

def add(obj, new_obj):

    raise TypeError


@add.register(str)

@check_type

def _(obj, new_obj):

    obj += new_obj

    return obj



@add.register(list)

@check_type

def _(obj, new_obj):

    obj.extend(new_obj)

    return obj


@add.register(dict)

@check_type

def _(obj, new_obj):

    obj.update(new_obj)

    return obj


@add.register(tuple)

@check_type

def _(obj, new_obj):

    return (*obj, *new_obj)


print(add('hello',', world'))

print(add([1,2,3], [4,5,6]))

print(add({'name': 'wangbm'}, {'age':25}))

print(add(('apple', 'huawei'), ('vivo', 'oppo')))


# list 和 字符串 无法拼接

print(add([1,2,3], '4,5,6'))

输出结果如下


CopyCopy

hello, world

[1, 2, 3, 4, 5, 6]

{'name': 'wangbm', 'age': 25}

('apple', 'huawei', 'vivo', 'oppo')

【错误】:参数类型不同,无法拼接!!

如果不使用singledispatch 的话,你可能会写出这样的代码。


CopyCopy

def check_type(func):

    def wrapper(*args):

        arg1, arg2 = args[:2]

        if type(arg1) != type(arg2):

            return '【错误】:参数类型不同,无法拼接!!'

        return func(*args)

    return wrapper


@check_type

def add(obj, new_obj):

    if isinstance(obj, str) :

        obj += new_obj

        return obj


    if isinstance(obj, list) :

        obj.extend(new_obj)

        return obj


    if isinstance(obj, dict) :

        obj.update(new_obj)

        return obj


    if isinstance(obj, tuple) :

        return (*obj, *new_obj)


print(add('hello',', world'))

print(add([1,2,3], [4,5,6]))

print(add({'name': 'wangbm'}, {'age':25}))

print(add(('apple', 'huawei'), ('vivo', 'oppo')))


# list 和 字符串 无法拼接

print(add([1,2,3], '4,5,6'))

输出如下


CopyCopy

hello, world

[1, 2, 3, 4, 5, 6]

{'name': 'wangbm', 'age': 25}

('apple', 'huawei', 'vivo', 'oppo')

【错误】:参数类型不同,无法拼接!!



发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

«    2024年9月    »
1
2345678
9101112131415
16171819202122
23242526272829
30
控制面板
您好,欢迎到访网站!
  查看权限
网站分类
搜索
最新留言
    文章归档
    网站收藏