我想玩匿名函数,所以我决定做一个简单的寻找者.这里是:
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
Run Code Online (Sandbox Code Playgroud)
然而,我发现了什么,就是i在lambda x:x%i==0每次访问,而我希望它是一个字面上的数字.我怎么能让它变成lambda x:x%3==0呢?
Rya*_*ing 44
你可以i在创建lambda时"捕获"它
lambda x, i=i: x%i==0
Run Code Online (Sandbox Code Playgroud)
这将i在lambda的上下文中设置等于i创建它时的任何内容.你也可以说,lambda x, n=i: x%n==0如果你想要,它不是完全捕获,但它可以满足你的需要.
如果没有这个,正如你所见,它将i在封闭范围内寻找一个
这是一个查找问题,类似于以下定义的函数:
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()
Run Code Online (Sandbox Code Playgroud)
问题是这些函数中的每一个tests都是指变量i.
更常见的是,你在一个函数内部执行此操作,在这种情况下,你有一个local-to-the-defined-scope变量i,它存储在一个闭包中,正如在这些讨厌的闭包中很好地解释的那样.
但在这里,它甚至更简单:i是一个全局变量,因此没有闭包.编译这些函数以i在运行时查找为全局变量.自i更改后,函数将在运行时看到更改的值.就那么简单.
围绕它的传统方式(适用于闭包和全局变量)被人们称为"默认值黑客",尽管它并不是真正的黑客攻击.(请参阅常见问题解答中的说明.)Ryan Haining的答案解释了如何执行此操作:
lambda x, i=i: x%i==0
Run Code Online (Sandbox Code Playgroud)
这将创建一个名为的参数i,其默认值等于i创建函数时的值.然后,在函数内部,当您访问参数时i,您将获得该值.
如果你习惯使用像JavaScript这样的语言,这可能看起来更熟悉的另一种方法是创建一个函数创建函数,并将i作为参数的值传递给该函数创建函数,如user2864740的答案:
(lambda i: lambda x: x%i)(i)
Run Code Online (Sandbox Code Playgroud)
这避免了使用额外参数(有人可能意外地将参数传递给)来"污染"函数的签名,但是代价是无缘无故地创建和调用函数.
第三种方法是使用partial.如果你想要做的就是部分应用一个函数,那么使用partial而不是将包装器函数定义为lambda可以更清晰.
不幸的是,在这种情况下,函数隐藏在运算符中,并且operator.mod公开它的函数不接受关键字参数,因此您无法有效地部分其第二个操作数.所以,在这种情况下,这是一个糟糕的解决方案.如果你真的想要,你可以写一个行为更好的包装器,并且partial:
def opmod(a, b):
return a % b
partial(operator.mod, b=i)
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我认为你对其他解决方案更好; 只要保持这一个在你的头的情况下它是适当的.
| 归档时间: |
|
| 查看次数: |
19517 次 |
| 最近记录: |