如何解决是否可以在 Python 中将 functools.singledispatch 与复合/嵌套/容器类型一起使用?
不知能否实现以下, 如果是这样,不需要太多额外的代码:
from __future__ import annotations
from functools import singledispatch
@singledispatch
def somefunc(value):
print(f"Type {type(value).__qualname__!r} "
f"is not registered for dispatch.")
@somefunc.register
def _(value: list[int]):
print(f"dispatched type list[int]!")
@somefunc.register
def _(value: list[str]):
print(f"dispatched type list[str]!")
somefunc('123')
somefunc([123])
somefunc(list('123'))
并得到输出:
Type 'str' is not registered for dispatch.
dispatched type list[int]!
dispatched type list[str]!
然而,使用 python 3.9.6 运行此代码段会导致在 functools.py 的第 742 行出现错误:
TypeError: issubclass() argument 2 cannot be
a parameterized generic
由于 singledispatch
确实适用于用户定义的类,使这项工作的一种方法是对传递的列表中的元素进行类型检查,将传递的列表包装到一个表示例如的类中list[str]
并让分派的函数以新实例作为参数再次调用自身:
from __future__ import annotations
from functools import singledispatch
class listofStrs(list):
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
class listofInts(list):
def __init__(self,**kwargs)
@singledispatch
def somefunc(value):
print(f"Type {type(value).__qualname__!r} "
f"is not registered for dispatch.")
@somefunc.register
def _(value: list):
if value and all(isinstance(subval,int)
for subval in value):
somefunc(listofInts(value))
elif value and all(isinstance(subval,str)
for subval in value):
somefunc(listofStrs(value))
else:
print(
f"dispatched a list whose elements ",f"are not all of a registered type."
)
@somefunc.register
def _(value: listofStrs):
print(f"dispatched type 'list[str]'!")
@somefunc.register
def _(value: listofInts):
print(f"dispatched type 'list[int]'!")
somefunc('123')
somefunc([1,2,3])
somefunc(list('123'))
somefunc([{1},{2},{3}])
正如预期的那样,结果:
Type 'str' is not registered for dispatch.
dispatched type 'list[int]'!
dispatched type 'list[str]'!
dispatched a list whose elements are
not all of a registered type.
然而,除了增加可扩展性之外,首先使用 singledispatch
的原因之一是为了规避冗长的类型检查,有些人认为这是一种反模式。当然,对于这个解决方案,您需要定义乱扔代码的包装类(可能有更好的方法来实现这一点,我目前没有看到,但第一点仍然存在)。
有理由在这里避免对“list”进行一次类型检查,但这仅通过一个 if/else 子句就降低了复杂性。
所以我实际上不会使用最后一种情况。
有谁知道如何像使用非复合类型一样优雅地获得这种行为?
我想这可以在 3.10 中使用模式匹配优雅地完成。所以,如果目前不可行,也许我应该等待它的推出和成熟?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。