4

我想了解如何map在 python 中使用,谷歌搜索将我带到了http://www.bogotobogo.com/python/python_fncs_map_filter_reduce.php,我发现这很有帮助。

该页面上的其中一个代码使用了一个 for 循环并map以一种有趣的方式放入该 for 循环中,并且该map函数中使用的列表实际上采用了 2 个函数的列表。这是代码:

def square(x): 
    return (x**2)

def cube(x):
    return (x**3)

funcs = [square, cube]

for r in range(5):
    value = map(lambda x: x(r), funcs)
    print value

输出:

[0, 0]
[1, 1]
[4, 8]
[9, 27]
[16, 64]

所以,在那个教程的这一点上,我想“如果你可以使用动态函数(lambda)编写代码,那么它可以使用标准函数编写,使用def”。所以我把代码改成这样:

def square(x): 
    return (x**2)

def cube(x):
    return (x**3)

def test(x):
    return x(r)

funcs = [square, cube]

for r in range(5):
    value = map(test, funcs)
    print value

我得到了与第一段代码相同的输出,但令我困扰的是变量r是从全局命名空间中获取的,并且代码不是严格的函数式编程。还有我被绊倒的地方。这是我的代码:

def square(x): 
    return (x**2)

def cube(x):
    return (x**3)

def power(x):
    return x(r)

def main():
    funcs = [square, cube]
    for r in range(5):
        value = map(power, funcs)
        print value

if __name__ == "__main__":
    main()

我玩过这段代码,但问题在于传递给函数def power(x)。我尝试了多种尝试传递到此函数的方法,但 lambda 能够自动将x变量分配给 list 的每次迭代funcs

有没有办法通过使用标准def函数来做到这一点,还是不可能,只能使用 lambda?由于我正在学习 python,这是我的第一语言,所以我试图了解这里发生了什么。

4

3 回答 3

4

您可以将函数嵌套在power()函数中main()

def main():
    def power(x):
        return x(r)

    funcs = [square, cube]
    for r in range(5):
        value = map(power, funcs)
        print value

所以r现在再次从周围的范围中获取,但不是全局的。相反,它是一个闭包变量。

但是,使用 alambda只是r从此处的周围范围注入并将其传递给power()函数的另一种方法:

def power(r, x):
    return x(r)

def main():
    funcs = [square, cube]
    for r in range(5):
        value = map(lambda x: power(r, x), funcs)
        print value

这里r仍然是一个非本地的,取自父范围!

r您可以使用作为第二个参数的默认值来创建 lambda :

def power(r, x):
    return x(r)

def main():
    funcs = [square, cube]
    for r in range(5):
        value = map(lambda x, r=r: power(r, x), funcs)
        print value

现在r作为默认值传入,因此它被视为本地值。但就您的目的而言,map()这实际上并没有什么不同。

于 2015-03-28T14:57:32.317 回答
3

咖喱是另一种选择。因为两个参数的函数与一个参数的函数返回另一个接受剩余参数的函数相同,所以你可以这样写:

def square(x):
    return (x**2)

def cube(x):
    return (x**3)

def power(r):
    return lambda(x): x(r) # This is where we construct our curried function

def main():
    funcs = [square, cube]
    for y in range(5):
        value = map(power(y), funcs) # Here, we apply the first function
                                     # to get at the second function (which
                                     # was constructed with the lambda above).
        print value

if __name__ == "__main__":
    main()

为了使关系更明确一点,类型(a, b) -> c的函数(一个接受类型a参数和类型参数b并返回类型值的c函数)等价于类型函数a -> (b -> c)

关于等价的额外内容

如果您想更深入地了解这种等价背后的数学原理,您可以使用一些代数来了解这种关系。将这些类型视为代数数据类型,我们可以将任何函数转换a -> b为 b a并将任何对(a, b)转换为 a * b。由于这种联系,有时函数类型被称为“指数”,而对类型被称为“乘积类型”。从这里,我们可以看到

c (a * b) = (c b ) a

所以,

(a, b) -> c  ~=  a -> (b -> c)
于 2015-03-28T19:35:25.933 回答
1

为什么不简单地将函数作为参数的一部分传递给power(),并用于itertools.product创建所需的(value, func)组合?

from itertools import product

# ...

def power((value, func)):
    return func(value)

for r in range(5):
    values = map(power, product([r], funcs))
    print values

或者,如果您不希望/要求按函数对结果进行分组,而是想要一个平面列表,您可以简单地执行以下操作:

values = map(power, product(range(5), funcs))
print values

注意:签名power((value, func))定义power()为接受单个 2 元组参数,该参数会自动解压缩到valueandfunc中。

相当于

def power(arg):
    value, func = arg
于 2015-03-28T15:36:26.987 回答