2011-05-25 59 views
1

我发现自己写了很多功能,我希望能够运用关于例如集合的参数x, y, ...,[(x1, y1, ...), (x2, y2, ...), ...]python装饰器可以使一个函数能够智能地操作单个对象和集合对象吗?

是否有一个清晰和简单的装饰,图案或技术来编写这样的功能?

下面是一个任意例如:

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) 
+9

整个想法并不好,因为你最终不知道进出这个函数的内容,这使得它很难找到错误。只需键入'(mul(* x)for x in xs)' – 2011-05-25 17:15:27

+0

就是有道理的。向上。 – 2011-05-25 17:18:41

+0

为什么我们不使用管道输入和运算符重载?似乎更直观和pythonic – Pwnna 2011-05-25 18:02:04

回答

2

的Python 3.4引入single-dispatch generic functions@singledispatch装饰,提供调用不同的参数类型相同的功能时实施不同行为的简单方法。例如,为了让您的mult()函数接受iterables:

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,其将任意函数为通用功能,并注册另一函数将其适当地处理iterables:

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] 

CAVEAT:正如评论所指出的Blckknght,你如果调用@takes_iterable装饰它打算在“单”模式下运行的功能得到意想不到的效果,但它传递的是发生在一个参数可以迭代,就像一个字符串。

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

+0

一个复杂的是,字符串是可迭代的。因此,如果原始函数将单个字符串作为其参数,那么代码就无法判断func(“abc”)是单个调用还是三个调用'func(“a”); FUNC( “B”); FUNC( “C”)'。 – Blckknght 2014-06-08 23:22:06

+0

@Blckknght这是一个很好的观点(扩展Jochen Ritzel的[评论](http://stackoverflow.com/questions/6128227/can-a-python-decorator-make-a-function-able-to-operate-on- single-objects-and-col/24111648?noredirect = 1#comment7111301_6128227))。为了达到这个效果,我已经更新了答案。 – 2014-06-08 23:40:57

相关问题