13

Python 3.2 documentationCollin Winter's functional module含有功能compose撰寫功能和功能模塊

撰寫()函數實現功能的組合物。在其他的 字樣中,它返回一個圍繞外部和內部可調用元素的包裝,例如 來自內部的返回值直接送到外部。

不幸的是,該模塊自2006年7月以來沒有更新;我想知道是否有可用的替代品。

現在,我只需要compose函數。以下原始functional.compose定義對Python 3還是有用的嗎?

def compose(func_1, func_2, unpack=False): 
    """ 
    compose(func_1, func_2, unpack=False) -> function 

    The function returned by compose is a composition of func_1 and func_2. 
    That is, compose(func_1, func_2)(5) == func_1(func_2(5)) 
    """ 
    if not callable(func_1): 
     raise TypeError("First argument to compose must be callable") 
    if not callable(func_2): 
     raise TypeError("Second argument to compose must be callable") 

    if unpack: 
     def composition(*args, **kwargs): 
      return func_1(*func_2(*args, **kwargs)) 
    else: 
     def composition(*args, **kwargs): 
      return func_1(func_2(*args, **kwargs)) 
    return composition 

這個SO question有點相關;它詢問Python是否應該支持compose的特殊語法。

+0

Python 3裏有加時賽的'callable'內置關鍵字 - 它通常是與'取代hasattr(obj,「__call__」)'否則,上面的代碼應該可以工作。 – jsbueno

+3

'callable()'被添加回3.2中的語言。 –

+0

我認爲在Python 3.2中應該沒問題。正如其他人指出的那樣,對於Python 3.0和3.1,您需要實現'callable',但如果您對3.2感到滿意,只需複製,粘貼和信用。 –

回答

6

您的compose的實現對python 3.2有效,如上面的註釋中所討論的。 您提供的庫的大部分功能都有一個等效的documentation

諸如mapfilter之類的函數已經在python中實現,並且也可以簡單地表示爲列表解析。 Python有一個返回對象身份的函數(作爲整數),但函數庫的id可以表示爲lambda x: x

您可能感興趣的另一個模塊是itertoolsfunctools具有partialreduce(這是類似foldl但參數順序是不一樣的)。

下面是其中的幾個簡單的實現,我沒有在標準庫中找到:

from functools import reduce 

def flip(f): 
    if not callable(f): 
     raise TypeError("Cannot filp a non-callable object") 
    def result(*args, **kw): 
     args = list(args) 
     args.reverse() 
     return f(*args, **kw) 
    return result 

def ilast(i): 
    return reduce(lambda _, x: x, i) 

def iscanl(f, v, seq): 
    yield v 
    for a in seq: 
     v = f(v, a) 
     yield v 

def scanl(*args, **kw): 
    return list(iscanl(*args, **kw)) 

def foldl(*args, **kw): 
    return ilast(iscanl(*args, **kw)) 
# Or using reduce 
#def foldl(f, v, seq): 
# return reduce(f, seq, v) 

def iscanr_reverse(f, v, seq): 
    return iscanl(flip(f), v, seq) 

def scanr(*args, **kw): 
    result = list(iscanr_reverse(*args, **kw)) 
    result.reverse() 
    return result 

def foldr(*args, **kw): 
    return ilast(iscanr_reverse(*args, **kw))