python 重载的实现(single-dispatch generic function)

DAY 11. python 重载

函数重载是指允许定义参数数量或类型不同的同名函数,程序在运行时会根据所传递的参数类型选择应该调用的函数
,但在默认情况下,python是不支持函数重载的,定义同名函数会发生覆盖

def foo(a:int):
    print(f'int {a}')

def foo(b:list):
    print(f'list{b}')

foo(3)
foo([i for i in range(3)])

# list3
# list[0, 1, 2]

至于不支持的原因,我想大概是没必要,首先,只在两种情况下可能发生函数重载,一是参数类型不同,二是参数个数不同,对于第一种情况,鸭子类型的存在使得函数不在乎参数类型而只关心参数的行为,所以你可以传递任何类型的参数,对于第二种情况,缺省参数的使用使得可以传递任意多个参数,因此函数的重载在python中就显得很鸡肋了,但如果非要实现函数重载,可以使用3.4中增加的转发机制即单分派泛型函数(single-dispatch generic function)来实现重载

11.2 单分派泛型函数

  • 泛型函数 generic function :由多个函数组成的函数,可以根据不同的参数类型决定调用那个函数
  • 单分派,single-dispatch:一种泛型函数分派形式,其中实现是根据单个参数的类型选择的。

所以,单分派泛型函数就是根据函数的第一个参数类型决定使用哪个函数的泛型函数

将一个函数声明为泛型函数可以使用修饰器@singledispatch,需要从functools模块导入,singledispatch有两个常用方法,register和dispatch

from functools import singledispatch

@singledispatch
def Foo(arg,*args):
    print(arg)

这样就实现了一个泛型函数,他的分派发生在第一个参数类型上,如果想要基于此实现重载,需要使用他的register方法,

from functools import singledispatch

@singledispatch
def Foo(arg,*args):
    print(arg)

# 使用了类型注释
@Foo.register
def _1(arg:int,*args):
    print(f'int - {arg}')

# 没有使用类型注释,显式传递给修饰器
@Foo.register(list)
def _2(arg,*args):
    print(f'list - {arg}')

if __name__ == '__main__':
    Foo(3)  # int - 3
    Foo([i for i in range(10)])  # list - [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

对于使用了类型注释的变量,singledispatch会自动推断第一个参数的类型,如上面int的那个,对于没有使用类型注释的变量,可以显式传递类型给singledispatch,如下面list的那个

register属性还可以以函数的形式调用,这可以用在lambdas表达式上,如

>>> def nothing(arg, verbose=False):
...     print("Nothing.")
...
>>> fun.register(type(None), nothing)

如果没有实现针对特定类型的注册,那么就会使用被@singledispatch修饰的函数

Foo("string")  # string

要检查泛型函数将为给定类型选择哪个实现,请使用dispatch()属性

print(Foo.dispatch(int))  # <function _1 at 0x000001D7C2724B70>
print(Foo.dispatch(list))  # <function _2 at 0x000001D7C2792E18>
print(Foo.dispatch(str))  # <function Foo at 0x000001FB456FC268>

要访问所有已注册的实现,请使用只读的registry属性

11.3 总结

python默认不支持重载,但可以使用单分派泛型函数实现,声明泛型函数需要使用修饰器@singledispatch,它有三个属性,register用来注册针对特定类型的“重载函数”,这里必须指明针对的是哪一个特定的类型,可以给第一个参数类型注释,也可以给register传入一个显式类型,否则会抛出TypeError异常;dispatch属性用来查看特定的类型将要选择的函数;registry用来访问所有已注册的实现。

参考链接:

functools.singledispatch

single dispatch

generic function

python中的重载

为什么 Python 不支持函数重载?其他函数大部分都支持的?

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Junebao

如果你碰巧财力雄厚的话...

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值