lambda function acessing outside variable
我想玩匿名函数,所以我决定做一个简单的Prime Finder。这里是:
1 2 3 4 5 6 7 8 9 10 11 12 | tests = [] end = int(1e2) i = 3 while i <= end: a = map(lambda f:f(i),tests) if True not in a: tests.append(lambda x:x%i==0) print i print tests print"Test:"+str(i) print str(a) i+=2 |
不过,我发现,每次访问
创建lambda时可以"捕获"
1 | lambda x, i=i: x%i==0 |
这将使lambda上下文中的
如果没有这个,正如您所看到的,它将在封闭范围内查找
这是一个查找问题,类似于以下定义函数的问题:
1 2 3 4 5 6 7 8 9 10 11 12 | i ="original" def print_i1(): print(i) # prints"changed" when called below def print_i2(s=i): #default set at function creation, not call print(s) # prints"original" when called below i ="changed" print_i1() print_i2() |
问题是,
更常见的是,您在函数内部这样做,在这种情况下,您有一个定义范围变量
但这里更简单:
围绕这一点的传统方法(同时适用于闭包和全局变量)被亲切地称为"默认值黑客",尽管它不是真正的黑客。(参见常见问题解答中的解释)Ryan Haining的回答解释了如何做到这一点:
1 | lambda x, i=i: x%i==0 |
这将创建一个名为
解决这个问题的另一种方法是,创建一个函数创建函数,并将EDOCX1的值(0)作为参数传递给函数创建函数,这在用户2864740的回答中似乎更为常见:
1 | (lambda i: lambda x: x%i)(i) |
这避免了用一个额外的参数"污染"函数的签名(有人可能意外地将参数传递给),但代价是创建和调用一个函数没有任何好的理由。
第三种方法是使用
不幸的是,在这种情况下,函数隐藏在一个运算符内,而公开它的函数
1 2 3 4 | def opmod(a, b): return a % b partial(operator.mod, b=i) |
在这种情况下,我认为你最好选择其他的解决方案;只要把这一个放在你的脑子里,以备不时之需。
创建返回lambda的新函数。然后称之为,传入
1 2 3 4 5 6 7 | def make_test (i): # this i refers to the parameter (which evaluates to the /value/ passed) return lambda x: x%i==0 # .. # the /value/ resulting from evaluating the variable is passed tests.append(make_test(i)) |