在SML(我在Python之前学过的函数式编程语言)中,我可以执行以下操作:
val x = 3;
fun f() = x;
f();
>>> 3
val x = 7;
f();
>>> 3
然而,在Python中,第一个调用将给出3,第二个调用将给出7.
x = 3
def f(): return x
f()
>>> 3
x = 7
f()
>>> 7
如何将变量的值绑定到Python中的函数?
答案 0 :(得分:7)
您可以使用关键字参数:
x = 3
def f( x=x ):
return x
x = 7
f() # 3
创建函数时为分配关键字参数。当函数运行时,在函数的范围中查找其他变量。 (如果在函数范围内找不到它们,python会在包含函数等的范围内查找变量。)。
答案 1 :(得分:2)
你可以这样做:
x = 3
f = lambda y=x: y
f()
>>> 3
x = 7
f()
>>> 3
答案 2 :(得分:2)
作为mgilson和Neal,最直接的方法是在定义f
时使用默认参数。
更大的问题是这里的哲学不匹配。 Python做了闭包,但它们的运行方式与你对SML(我不是特别熟悉的)或Haskell或Clojure或其他东西(我都比较熟悉)的预期不同。这是因为Python处理闭包的方式,也是因为它以不同的方式定义匿名函数并允许副作用。
通常,在功能方法不能正常工作的地方,在Python中你使用一个类,在这种情况下捕获x的值。
class F(object):
def __init__(self, x):
self.x = x
def __call__(self):
return self.x
x = 3
f = F(x)
f()
# 3
x = 7
f()
# 3
对于这个例子来说,这样做太过分了,我显然不会在这里推荐它。但通常在Python中,答案是使用类。 (这是一个严重的过度陈述,我的大脑产生异常的速度比我输入的速度快。但是当你从功能背景中来时,我认为这个陈述是一个很好的启发式,因为你正在学习用Python来解决问题。)
另外,有趣的是,这明确了隐含地捕获函数参数定义中的变量的内容:它创建了一个函数对象,该对象在创建对象时挂起到x
的值。
答案 3 :(得分:0)
这个问题似乎是关于如何在创建闭包时捕获外部变量的值(不是引用)。从这个意义上说,通常的答案是使用默认参数:
def f(x=x):
return x
# or
f = lambda x=x: x
(但是,如果你想要一个带有可变数量参数的函数,这将不起作用)。或者更一般地(甚至在变量参数的情况下工作)但不太漂亮,使用立即执行的显式包装函数:
f = (lambda x: lambda: x)(x)
但是,我只是想指出你问题的前提是无效的 - 在SML中,你不能将分配给变量(I')我不是在谈论修改像ref
这样的可变数据结构;我在谈论分配给变量);语言中甚至没有语法来执行此操作。
您在SML代码中所做的是创建新范围并在新范围中定义具有相同名称x
的不同变量,这隐藏了之前的{{1} }。您始终可以简单地将第二个变量重命名为其他名称,但不会对该程序产生任何影响。现在,Python只具有函数作用域,并且没有函数内部代码块的内部作用域。但您可以应用相同的解决方案 - 只需将第二个变量重命名为其他名称,您就不会遇到此问题。