python - python装饰器可以使函数能够智能地操作单个对象和集合对象吗?

标签 python generics collections decorator

我发现自己编写了很多函数,我希望能够对参数 x、y、... 的集合进行操作,例如[(x1, y1, ...), (x2, y2, ...), ...]

是否有一个清晰简单的装饰器、模式或技术来编写这样的函数?

这是一个任意示例:

def awesome(func):
    # ???

@awesome
def mult(a, b):
    return a * b

mult(3, 4)                      # should return 12
mult((3, 4))                    # should return 12 or possibly (12,)
mult(((3, 4), (2, 3), [3, 3]))  # should return (12, 6, 9)
mult([(3, 4), [4, 5]])          # should return (12, 20)

最佳答案

Python 3.4 引入 single-dispatch generic functions@singledispatch装饰器,提供了一种简单的方法来在使用不同参数类型调用同一函数时实现不同的行为。例如,要允许您的 mult() 函数接受可迭代对象:

from functools import singledispatch
from collections.abc import Iterable

@singledispatch
def mult(a, b):
    return a * b

@mult.register(Iterable)
def _(it):
    return [mult(a, b) for a, b in it]

函数的“基本”版本用 @singledispatch 修饰,将其转换为通用函数。接下来,定义函数 _() 来对可迭代中的每个元素调用 mult(),并使用 @mult.register( )

尽管上面的示例使用 collections.abc.Iterable为了最大程度地通用,还可以为多个具体类型注册一个函数:

@mult.register(list)
@mult.register(tuple)
def _(it):
    return [mult(a, b) for a, b in it]

使用上面的技术,可以编写一个装饰器@takes_iterable,它将任意函数转换为通用函数,并向其注册另一个函数以适本地处理可迭代对象:

def takes_iterable(func):
    generic = singledispatch(func)
    @generic.register(Iterable)
    def _(it):
        return [func(*args) for args in it]
    return generic

@takes_iterable
def mult(a, b):
    return a * b

使用示例:

>>> mult(17,23)
391
>>> mult([(11, 29), (13, 23), (17, 19)])
[319, 299, 323]

警告:正如 Blckknght 在评论中指出的那样,如果调用用 @takes_iterable 修饰的函数并希望其以“单一”方式运行,您将得到意外的结果模式,但向其传递一个恰好可迭代的参数,例如字符串。

这实际上是问题中所要求的行为固有的模糊性的结果,而不是此处概述的实现,但在考虑是否使用此技术时值得牢记。

关于python - python装饰器可以使函数能够智能地操作单个对象和集合对象吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6128227/

相关文章:

python - 在形状为 `(n,)` 的 numpy 数组上迭代调用 lambda 函数

python - 日志中的自定义 Logger 类和正确的行号/函数名称

c# - 在 C# : Taking very long 中迭代大型集合

java - 如果我们有原始的,为什么我们可以更改不可修改的列表?

c# - WCF - 不要序列化(发出)空集合

python - mlpy 的 scipy.sparse.csc_matrix 格式

python - 如何以及何时在 Python 中适本地使用弱引用

java - 运行时已知的通用上限通配符实例化

java - 可以使用泛型 Java 方法的泛型类型来强制执行参数类型吗?

java - ( Play 2.1.3)最小化模型中的代码。静态方法的泛型