【问题标题】:Applying map for partial argument将映射应用于部分参数
【发布时间】:2012-11-22 04:44:42
【问题描述】:

给定以下带有两个参数的函数 f,将 map 仅应用于 x 的标准方法是什么?

def f (x,y):
    print x,y

更具体地说,我想在一行中执行以下操作。

list=[1,2,3]
fixed=10
for s in list:
    f(s,fixed)

一种方法是:

import functools
map(functools.partial(lambda x,y:f(y,x),fixed),list)

有什么更好的方法?

【问题讨论】:

    标签: python functional-programming


    【解决方案1】:

    首先,不需要使用 lambda AND partial - 它们是替代品:

    map(lambda x:f(x,fixed),srclist)
    

    其次,只要您知道参数的名称,您就可以将第二个参数与partial 绑定:

    map(functools.partial(f,y=fixed),srclist)
    

    或者,使用列表推导:

    [f(x, fixed) for x in srclist]
    

    【讨论】:

    • 你能评论一下这三种方法的性能如何叠加吗?
    • @chase 好吧,最后一个不涉及实际的部分应用程序,因此它避免了任何开销。至于其他两个,我不能说。无论如何,在您确定热点之前,不应进行这种微优化。
    • 一般来说我同意。虽然偶尔有人会在找到热点时搜索 2 年前的 SO 问题;) 应该很容易分析,尽管我个人更喜欢最后一种解决方案。
    • @chase 那就这样吧,肯定的。
    【解决方案2】:

    给定以下带有两个参数的函数 f,将 map 仅应用于 x 的标准方法是什么?

    关于柯里化和偏应用的一点讨论

    在 FP 术语中,您的函数 f"uncurried" - 虽然它在概念上需要两个参数,但它们被捆绑在一个产品结构中。在 Python 中,一切都是非咖喱的,一直都是。您必须一次给出所有论点,或者一个都不给出。

    要解决这个问题,有各种技巧,但从概念上讲,您只想“咖喱”函数。也就是说,将f(x,y) 转换为f(x),它会返回一个新函数g(y)

    在默认使用柯里化的语言中,您可以轻松地将这个翻译写成:

    -- curry: take a function from (x,y) to one from x to a function from y to z
    curry :: ((x,y) -> z) -> (x -> y -> z)
    curry f x y     = f (x, y)
    

    所以curry 将你的咖喱f 及其产品参数分开,并在它们都可用时应用这些参数。反之亦然:

    uncurry :: (x -> y -> z) -> ((x,y) -> z)
    uncurry f (x,y) =  f x y
    

    这与部分应用有何关系?

    • Currying 采用一个采用 1 (n-product) 参数结构的函数,并返回一个采用 n 参数的新函数。
    • 部分应用采用 n 个参数的函数并将它们应用于 k 个参数,从而产生 n-k 个剩余参数的函数。

    在非柯里化语言中,每个参数都可以依次应用(例如,部分地,关于函数的数量)。在柯里化语言中,您必须先使用一些技巧来取消函数的柯里化,如上面的示例所示。

    我认为在 curried-by-default 环境中更灵活,因为部分应用程序是免费的。在这样的环境中,将modify a data structure into a pipeline 的函数链接在一起是很常见的。例如。整数修改管道:

    (+1) . (*2) . (^3) $ 7
    

    只是一个部分应用的、非柯里化的函数链,由组合而成,每个函数都对前一个函数的输出进行操作。这很好,因为它在视觉上分离了关注点。

    【讨论】:

      【解决方案3】:
      map(lambda x: f(fixed,x), thelist)
      

      或者根本不使用map(),而是使用列表推导。

      [f(fixed, x) for x in thelist]
      

      PS:不要使用list作为变量名,它是一个重要的内置名称(列表类型)。

      【讨论】:

        【解决方案4】:

        有什么问题:

        def add(x, y):
            return x + y
        
        l = [1, 2, 3]
        
        from functools import partial
        plus10 = map(partial(add, y=10), l)
        print plus10
        
        ## [11, 12, 13]
        

        【讨论】:

        • 这是不可读的(我认为 python 是不言自明的?)。列表理解示例更具可读性。
        • @Ingo:当然,除了 OP 没有说任何关于理解的内容。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-20
        • 1970-01-01
        相关资源
        最近更新 更多