Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
lambda函数在python中如何引用其参数?_Python_Lambda_Functional Programming_Closures - Fatal编程技术网

lambda函数在python中如何引用其参数?

lambda函数在python中如何引用其参数?,python,lambda,functional-programming,closures,Python,Lambda,Functional Programming,Closures,我是Python新手。我的任务很简单——我需要一个函数列表,可以用它成批完成任务。所以我用了一些例子,比如 fs = [lambda x: x + i for i in xrange(10)] 令人惊讶的是 [f(0) for f in fs] 给我的结果是[9,9,9,9,9,9,9,9,9]。这不是我所期望的,因为我希望变量I在不同的函数中具有不同的值 所以我的问题是: lambda中的变量i是全局变量还是局部变量 python的概念是否与javascript中的“闭包”相同?我的意思是

我是Python新手。我的任务很简单——我需要一个函数列表,可以用它成批完成任务。所以我用了一些例子,比如

fs = [lambda x: x + i for i in xrange(10)]
令人惊讶的是

[f(0) for f in fs]
给我的结果是
[9,9,9,9,9,9,9,9,9]
。这不是我所期望的,因为我希望变量
I
在不同的函数中具有不同的值

所以我的问题是:

  • lambda中的变量
    i
    是全局变量还是局部变量

  • python的概念是否与javascript中的“闭包”相同?我的意思是,这里的每个lambda是否都持有对
    I
    变量的引用,或者它们只是在每个lambda中持有
    I
    值的副本

  • 在这种情况下,如果希望输出为
    [0,1,…9]
    ,该怎么办


  • 看起来有点凌乱,但你可以通过这样做得到你想要的:

    >>> fs = [(lambda y: lambda x: x + y)(i) for i in xrange(10)]
    >>> [f(0) for f in fs]
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    
    通常Python支持“闭包”概念,类似于Javascript中的闭包概念。然而,对于列表理解中lambda表达式的这种特殊情况,似乎
    i
    只绑定了一次,并连续接受每个值,使每个返回函数的作用就像
    i
    是9一样。上面的hack显式地将
    i
    的每个值传递到lambda,该lambda使用捕获的
    y
    值返回另一个lambda

  • 变量
    i
    是列表理解的局部变量,但它对lambda可用,因为lambda在其范围内
  • 是的,lambda是闭包。变量绑定可能并不总是按照您希望的方式工作,但它们是闭包。不过,你不应该过分依赖它们
  • 您只需要在
    xrange(10)
    上循环。你可以用lambdas来做这件事(见另一个答案),但你不想这样做。Lambdas应该非常谨慎地使用

  • lambda以这种方式运行的原因是,对于每个循环,
    i
    都是反弹。因为我不是lambda的本地值,所以它也会发生变化,最后一个值是9。所以你所做的就是
    0+9
    10次。

    i是本地的,python中确实有闭包

    我相信您的困惑在于您将fs分配给一个相同函数的列表

    >>> fs = [lambda x: x + i for i in xrange(10)]
    >>> fs
    [<function <lambda> at 0x02C6E930>, <function <lambda> at 0x02C6E970>, <function <lambda> at 0x02C6E9B0>, <function <lambda> at 0x02C6E9F0>, <function <lambda> at 0x02C6EA30>, <function <lambda> at 0x02C6EA70>, <function <lambda> at 0x02C6EAB0>, <function <lambda> at 0x02C6EAF0>, <function <lambda> at 0x02C6EB30>, <function <lambda> at 0x02C6EB70>]
    >>> fs[0](0)
    9
    >>> fs[0](100)
    109
    >>> fs[5](0)
    9
    >>> fs[5](100)
    109
    
    fs=[λx:x+i表示x范围内的i(10)] >>>财政司司长 [, , , , , ] >>>fs[0](0) 9 >>>fs[0](100) 109 >>>fs[5](0) 9 >>>fs[5](100) 109 我认为单个函数返回一个列表会更合适

    >>> fs3 = lambda x: [x + i for i in xrange(10)]
    >>> fs3
    <function <lambda> at 0x02C6EC70>
    >>> fs3(0)
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    
    fs3=lambda x:[x+i代表x范围内的i(10)] >>>fs3 >>>fs3(0) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    这里遇到的问题是“早期绑定”和“后期绑定”之间的区别

    当Python从外部范围(在本例中为
    i
    )查找变量时,它使用后期绑定。这意味着它在调用函数时看到该变量的值,而不是在定义函数时看到的值

    因此,在您的示例代码中,所有10个lambda函数都会看到循环过程分配给
    i
    变量的最终值:
    9

    Greg的回答显示了一种强制早期绑定行为的方法(即创建一个额外的闭包,并在循环中立即调用它)

    强制早期绑定语义的另一种常用方法是“默认参数hack”,它在函数定义时将变量绑定为默认参数:

    >>> fs = [(lambda x, _i=i: x + _i) for i in xrange(10)]
    >>> [f(0) for f in fs]
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    

    这两种方法都有效。Greg的优点是不干扰返回函数的签名,默认参数破解比定义命名函数而不是使用lambda表达式时添加额外的闭包级别更快,可读性更高。

    是的,上面的技巧很聪明。它通过使用一个额外的闭包来创建本地副本。实际上,闭包的工作方式与预期的一样(捕获变量,而不是在闭包创建时捕获变量的值),JS也这样做(尝试在循环中创建函数)。似乎我只绑定了一次,并连续接受每个值。。。如果是这样的话,
    i
    的值不应该是
    0
    ,因为它是由
    xrange
    生成的第一个值吗?是的,很高兴知道python中有另一种黑客攻击。格雷格的技巧在Javascript中有对应关系,但你的技巧对我来说是新的。谢谢你的解释