2011-05-25 63 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

相關問題