绑定函数内的对象值(闭包)

时间:2012-08-14 13:27:51

标签: python closures sml

在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中的函数?

4 个答案:

答案 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只具有函数作用域,并且没有函数内部代码块的内部作用域。但您可以应用相同的解决方案 - 只需将第二个变量重命名为其他名称,您就不会遇到此问题。