如何使用python实现`一元函数chainer`?

时间:2015-02-25 07:58:27

标签: python

我正在做代码战,我无法赢得这个挑战。 链接在这里: http://www.codewars.com/kata/54ca3e777120b56cb6000710/train/python

这是我的实现,但是有一个错误'TypeError:'generator'对象不可调用 “:

def chained(functions):
    for f in functions:
        yield f

def f1(x): return x*2
def f2(x): return x+2
def f3(x): return x**2

def f4(x): return x.split()
def f5(xs): return [x[::-1].title() for x in xs]
def f6(xs): return "_".join(xs)

print chained([f1, f2, f3])(0)

注意:重播chained([f1, f2, f3])(0)4 !!!!!

以下是这些案例:

test.assert_equals( chained([f1,f2,f3])(0), 4 )
test.assert_equals( chained([f1,f2,f3])(2), 36 )
test.assert_equals( chained([f3,f2,f1])(2), 12 )

4 个答案:

答案 0 :(得分:8)

您需要返回一个函数,而不是返回一个生成器,该函数接受一个参数并将其应用于每个链接函数。

您的调用语法为:

chained([f1, f2, f3])(0)

这意味着您希望chained返回可以使用单个参数调用的内容。功能会很好。

一个可行的功能是:

def apply(param):
    result = param
    for f in functions:
        result = f(result)
    return result

这将使用前一个函数调用的结果调用每个函数。首先,使用初始参数。

但是,由于您没有将函数列表传递给只接受一个参数的此函数,因此您需要以其他方式捕获它们。您可以在函数中定义函数,并捕获任何局部变量:

def chained(functions):
    def apply(param):
        result = param
        for f in functions:
            result = f(result)
        return result
    return apply

在本地定义函数apply会捕获functions参数。然后我们返回函数,以便可以调用它,基本上是apply(0)

>>> chained([f1, f2, f3])(0)
4

答案 1 :(得分:4)

您可以使用reduce ...

这将获取一系列函数,并依次将值应用于每个函数。因此,将采用第一个函数,并返回一个值。然后,将采用第二个函数,并将其应用于新值,...

fs = [f1, f2, f3] 
print reduce( lambda val, f: f(val) , fs, 0 )

你想要的是一个函数chained,它返回另一个带有一个变量的函数。获取一个变量(例如m)的示例函数是lambda m: m*2

现在是一个返回另一个带一个值的函数的函数?

def retFunc(): return (lambda m: m*2)

所以我们只是将上述两个想法结合起来,然后......

def chained(fs):
    return (lambda m: reduce( lambda val, f: f(val) , fs, m))

print chained(fs)(0)

此处,chained(fs)获取函数列表fs并返回函数lambda m: reduce( lambda val, f: f(val) , fs, m)。这是一个按顺序执行mreduce所有函数的函数。

所以,chained(fs)(0)

变为(lambda m: reduce( lambda val, f: f(val) , fs, m))(0)

变为(reduce( lambda val, f: f(val) , fs, 0))

这正是第一个表达式...

答案 2 :(得分:0)

应该迭代生成器。而不是:

print chained([f1, f2, f3])(0)

尝试:

for i in chained([f1, f2, f3]):
    print i(0)

答案 3 :(得分:0)

您必须使用递归和currying来解决问题:

def chained(functions):
    def g(x): #curry the functions
        result = x 
        for f in functions:
            result = f(result) 
        return result
    return g
给定test.assert_equals(chained([f1,f2,f3])(0),4),结果经过以下步骤 第一次迭代x = 0时,结果=0。因此对函数进行迭代 结果= f1(0)然后结果= f2(f1(0))然后结果= f3(f2(f1(0)))。然后我们返回结果 我们在“链接”函数中称呼函数“ g”,因为我们只是在本地对其进行了定义。