【问题标题】:How can I dispatch Python 2 functions based on the data type passed to the function?如何根据传递给函数的数据类型调度 Python 2 函数?
【发布时间】:2018-07-24 16:08:35
【问题描述】:

我想根据传递给“调度”函数的参数的数据类型(例如使用isinstance())调度依赖于(例如使用dict approach)的Python函数。是否有实现替代方案?最简单的方法是什么?

【问题讨论】:

  • 您是否尝试过使用字典方法?发生了什么?
  • 强烈敦促您考虑升级到 Python 3,此时标准库会为您提供 @singledispatch decorator function 来处理基于类型的调度。
  • 我知道。但我必须在这里明确使用 python-2.7。

标签: python python-2.7 generic-function single-dispatch


【解决方案1】:

从 Python 3.4 开始,Python 标准库包括对 @singledispatch() generic functions 的支持。

这使您可以注册多个函数来处理不同的类型,它会根据类型处理分派,包括子类测试和缓存。该方法在PEP 443 - Single-dispatch generic functions中有描述。

有一个backport available on PyPI 支持 Python 2.6 及更高版本,由 PEP 作者编写。

请注意,Python 2.7 即将达到最终生命周期结束日期,届时它将不再接收错误修复和安全更新;您确实需要尽早计划升级到 Python 3。当您这样做时,您会注意到 Python 3.7 版本支持使用类型提示来记录每个函数接受的类型。

例如,从嵌套的字典和列表数据结构(典型的 JSON 数据结构)中删除 NoneFalse 值的一系列函数可以定义为:

from functools import singledispatch

@singledispatch
def remove_null_false(ob):
    return ob

@remove_null_false.register
def _process_list(ob: list):
    return [remove_null_false(v) for v in ob]

@remove_null_false.register
def _process_list(ob: dict):
    return {k: remove_null_false(v) for k, v in ob.items()
            if v is not None and v is not True and v is not False}

在 Python 版本 @remove_null_false.register(...) 装饰器工厂符号。

【讨论】:

    【解决方案2】:

    请看下面的例子。

    def get_int_square(a):
        """
        Returns square of integer parameter
        """
        return a ** 2
    
    def get_float_cube(a):
        """
        Returns cube of float parameter
        """
        return a ** 3
    
    def sum_of_items(l):
        """
        Returns sum of all the items in list
        """
        return sum(l)
    
    def get_squared_items(t):
        return tuple(item ** 2 for item in t)
    
    def dispatching(a):
        """
        Calls the corresponding functions based on match found in the dictionary
        """
        functions = {
            'int': get_int_square,
            'float': get_float_cube,
            'list': sum_of_items,
            'tuple': get_squared_items
        }
    
        data_type = str(type(a)).split("'")[1]
        result = functions[data_type](a)
        return result
    
    if __name__ == "__main__":
        print(dispatching(12))  # 144
        print(dispatching(1.2)) # 1.7279999999999998
        print(dispatching((4, 7, 9, 3, 1, 5, 8))) # (16, 49, 81, 9, 1, 25, 64)
        print(dispatching([56, 4, 50, 26, 24]))   # 160
    

    【讨论】:

    • 使用自己的类型而不是 int、float 等应该不是问题。凉爽的。谢谢。
    • 你也可以使用其他类型,你只需要添加更多的代码行。如果您有任何问题,请发表评论。感谢您的回复。
    猜你喜欢
    • 2017-09-16
    • 1970-01-01
    • 1970-01-01
    • 2018-04-10
    • 2012-11-25
    • 2021-05-21
    • 1970-01-01
    • 2015-12-18
    • 1970-01-01
    相关资源
    最近更新 更多