装饰器之丐版singledispatch

本文介绍了Python中的装饰器singledispatch,它是用于实现单分派泛型函数的一种方式。文章通过一个丐版的singledispatch实现,展示了如何根据函数的第一个参数类型来选择调用不同函数。文中还提供了示例代码,演示了如何注册新函数处理特定类型的参数,并给出了实际应用的例子。
摘要由CSDN通过智能技术生成

装饰器之丐版singledispatch

前言

在公众号上看到《一日一技:使用装饰器简化大量 if…elif…代码》,感觉很有意思跑去看了下源代码1,看到文档写着 Like singledispatch() but dispatches by value of the first arg ,记得 singledispatch() 好像在标准库 functools2里,于是故事开始。

singledispatch()

英文不好,参考了大佬的文章3知道了singledispatch是单分派泛型函数。

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

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

丐版实现

看看就好,反正真正用的时候 from functools import singledispatch 就行。

from functools import update_wrapper
from collections import defaultdict
def singledispatch(func):

	registry = defaultdict(lambda :func)

	def dispatch(cls):
		return registry[cls]

	def register(cls, func=None):
		if func is None:
			return lambda x: register(cls, x)
		registry[cls] = func
		return func

	def wrapper(*args, **kwargs):
		if not args:
			raise TypeError('我要根据单个参数选择分派,然后你不给我参数?')
		return dispatch(args[0].__class__)(*args, **kwargs)

	wrapper.dispatch = dispatch
	wrapper.register = register
	update_wrapper(wrapper, func)
	return wrapper

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

@Foo.register(int)
def _1(arg, *args):
	print(f'int - {arg}')
# Foo.register(int, _1)

# @Foo.register(list)
def _2(arg, *args):
	print(f'list - {arg}')
Foo.register(list, _2)

Foo(3)
Foo([*range(10)])
Foo((1,2))

# int - 3
# list - [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# (1, 2)

因为不像标准库里那样,为了一个 best matching implementation from registry for type cls,去继承里用C3去找,我这里直接偷懒用了一个 defaultdict ,把原函数当成默认的处理函数,匹配不上就用这个而不是去寻找。

然后注册的时候用到 register 函数,可以显式调用或者作为带参数的装饰器,所以实现里面要加一个判断。

总结

装饰器这个东西总能整出新活,一阵子不用就跟忘掉一样,需要长时间的积累和回顾。


  1. 源代码: https://github.com/edgedb/edgedb/blob/master/edb/common/value_dispatch.py ↩︎

  2. functools库: https://github.com/python/cpython/blob/main/Lib/functools.py#L799 ↩︎

  3. python 重载的实现: https://blog.csdn.net/zjbyough/article/details/97152241 ↩︎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值