相关疑难解决方法(0)

(lambda)函数闭包捕获了什么?

最近我开始玩Python,我遇到了一些特殊的闭包方式.请考虑以下代码:

adders=[0,1,2,3]

for i in [0,1,2,3]:
   adders[i]=lambda a: i+a

print adders[1](3)
Run Code Online (Sandbox Code Playgroud)

它构建了一个简单的函数数组,它接受单个输入并返回由数字添加的输入.函数在for循环中构造,迭代器i从中循环03.对于这些数字中的每一个,lambda都会创建一个函数i,该函数捕获并将其添加到函数的输入中.最后一行将第二个lambda函数3作为参数调用.令我惊讶的是输出结果是6.

我期待一个4.我的理由是:在Python中,一切都是一个对象,因此每个变量都是指向它的指针.在创建lambda闭包时i,我希望它存储一个指向当前指向的整数对象的指针i.这意味着当i分配一个新的整数对象时,它不应该影响先前创建的闭包.遗憾的是,adders在调试器中检查数组表明它确实存在.所有的lambda功能指的最后一个值i,3,这将导致adders[1](3)返回6.

这让我想知道以下内容:

  • 闭包捕获的内容是什么?
  • 什么是最优雅的方式来说服lambda函数以更改其值i时不会受到影响的方式捕获当前i值?

python lambda closures

237
推荐指数
5
解决办法
4万
查看次数

lambda函数的范围及其参数?

我需要一个回调函数,对于一系列gui事件几乎完全相同.该函数的行为会略有不同,具体取决于调用它的事件.对我来说似乎是一个简单的案例,但我无法弄清楚lambda函数的这种奇怪的行为.

所以我在下面有以下简化代码:

def callback(msg):
    print msg

#creating a list of function handles with an iterator
funcList=[]
for m in ('do', 're', 'mi'):
    funcList.append(lambda: callback(m))
for f in funcList:
    f()

#create one at a time
funcList=[]
funcList.append(lambda: callback('do'))
funcList.append(lambda: callback('re'))
funcList.append(lambda: callback('mi'))
for f in funcList:
    f()
Run Code Online (Sandbox Code Playgroud)

此代码的输出是:

mi
mi
mi
do
re
mi
Run Code Online (Sandbox Code Playgroud)

我期望:

do
re
mi
do
re
mi
Run Code Online (Sandbox Code Playgroud)

为什么使用迭代器搞砸了?

我尝试过使用深度镜:

import copy
funcList=[]
for m in ('do', 're', 'mi'):
    funcList.append(lambda: callback(copy.deepcopy(m)))
for f in funcList:
    f()
Run Code Online (Sandbox Code Playgroud)

但这也存在同样的问题.

python lexical-closures

79
推荐指数
3
解决办法
3万
查看次数

在循环中创建函数

我正在尝试在循环内创建函数并将它们存储在字典中.问题是字典中的所有条目似乎最终都映射到最后创建的函数.代码如下:

functions = []

for i in range(3):
    def f():
        return i

    # alternatively: f = lambda: i

    functions.append(f)
Run Code Online (Sandbox Code Playgroud)

这输出:

print([f() for f in functions])
# expected output: [0, 1, 2]
# actual output:   [2, 2, 2]
Run Code Online (Sandbox Code Playgroud)

知道为什么吗?

python function

79
推荐指数
2
解决办法
3万
查看次数

lambda函数不关闭Python中的参数?

代码说明更多:


from pprint import pprint

li = []

for i in range(5):
        li.append(lambda : pprint(i))

for k in li:
        k()
Run Code Online (Sandbox Code Playgroud)

让:

4
4
4
4
4

为什么不

0
1
2
3
4

??

谢谢.

PS如果我写完整的装饰器,它按预期工作:



from pprint import pprint

li = []

#for i in range(5):
        #li.append(lambda : pprint(i))

def closure(i):
        def _func():
                pprint(i)
        return _func

for i in range(5):
        li.append(closure(i))

for k in li:
        k()
Run Code Online (Sandbox Code Playgroud)

python lambda

9
推荐指数
1
解决办法
1083
查看次数

在 python 中创建 lambda 时,i=i 是什么意思?

我在Python hitchhikers 指南中看到了这个例子:

def create_multipliers():
    return [lambda x, i=i : i * x for i in range(5)]
Run Code Online (Sandbox Code Playgroud)

上面的示例是对后期绑定引起的一些问题的解决方案,其中在调用内部函数时查找闭包中使用的变量。

i=i 是什么意思以及为什么会产生如此大的差异?

python lambda

5
推荐指数
1
解决办法
1937
查看次数

如何强制Python在循环中创建新的变量/新范围?

今天我探讨了Python 的奇怪行为.一个例子:

closures = []
for x in [1, 2, 3]:
    # store `x' in a "new" local variable
    var = x

    # store a closure which returns the value of `var'
    closures.append(lambda: var)

for c in closures:
    print(c())
Run Code Online (Sandbox Code Playgroud)

上面的代码打印出来

3
3
3
Run Code Online (Sandbox Code Playgroud)

但是我希望它能打印出来

1
2
3
Run Code Online (Sandbox Code Playgroud)

我为自己解释了这种行为,var它始终是相同的局部变量(并且python不像其他语言那样创建新的行为).如何修复上面的代码,以便每个闭包都返回另一个值?

python variables parameters closures for-loop

3
推荐指数
2
解决办法
1057
查看次数

如何在Python类中动态定义方法?

我想在我的类中定义许多方法TestClass。我想呼唤他们的名字TestClass().method_1......TestClass().method_n

我不想间接调用它们,例如通过中间方法来TestClass().use_method('method_1', params)保持与代码其他部分的一致性。

我想动态定义我的众多方法,但我不明白为什么这个最小的示例不起作用:

class TestClass:
    def __init__(self):
        method_names = [
            'method_1',
            'method_2']
        
        for method_name in method_names:
            def _f():
                print(method_name)
            # set the method as attribute
            # (that is OK for me that it will not be
            #   a bound method)
            setattr(
                self,
                method_name,
                _f)
            del _f

if __name__ == '__main__':
    T = TestClass()

    T.method_1()
    T.method_2()
    
    print(T.method_1)
    print(T.method_2)
Run Code Online (Sandbox Code Playgroud)

输出是:

function_2
function_2
<function TestClass.__init__.<locals>._f at 0x0000022ED8F46430>
<function TestClass.__init__.<locals>._f at 0x0000022EDADCE4C0>
Run Code Online (Sandbox Code Playgroud)

当我期待的时候

function_1
function_2
Run Code Online (Sandbox Code Playgroud)

我尝试在很多地方放置一些 …

python

2
推荐指数
1
解决办法
786
查看次数

如何将特定项目与功能关联起来?

我正在尝试创建一个函数(函数对象)列表,从另一个列表中打印出相应的项目:

strings = ["a", "b", "c"]
functions = []
for i in strings:
    functions.append(lambda: print(i))
Run Code Online (Sandbox Code Playgroud)

上面的代码的作用是创建 lambda 函数,该函数在调用时会打印 i 的值。我希望字符串列表和函数列表的项目具有一对一的关系,这意味着我想要以下结果。

输出1:

    >>> functions[0]()
    'a'
    >>> functions[1]()
    'b'
    >>> functions[2]()
    'c'
Run Code Online (Sandbox Code Playgroud)

但我得到这个:

输出2:

    >>> functions[0]()
    'c'
    >>> functions[1]()
    'c'
    >>> functions[2]()
    'c'
Run Code Online (Sandbox Code Playgroud)

我知道 for 循环中的变量 i 在循环结束后仍然存在,并且所有函数最终都会打印出相同的 i 值。

有没有办法让函数打印出字符串列表的相应值,就像上面的Output1一样?

python

1
推荐指数
1
解决办法
97
查看次数