是否可以在 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 (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...