Python lambda捕获外部变量

问题描述 投票:0回答:2

请考虑以下示例:

test = 123
f = lambda x,test=test: print(x, test)
del test
f('hello')

版画

hello 123

通过捕获lambda定义中的变量,似乎保留了原始变量。

当你还可以使用一个简单的对象存储相同的数据时,lambda可以使用吗?

class Test:
    def __init__(self, some_data):
        self.some_data = some_data

    def f(self, x):
        print(x, self.some_data)

t = Test('123')
t.f('hello')
python python-3.x lambda
2个回答
1
投票

通过捕获lambda定义中的变量,似乎保留了原始变量。

因为你使它成为lambda的test参数的默认值,而Python只在创建函数时评估参数默认值。 FWIW,这与使用lambda关键字无关 - lambda只是语法糖,你可以通过“完整”功能得到完全相同的结果,即:

test = 123
def f(x, test=test):
    print(x, test)
test = 456
f('hello')

当你还可以使用一个简单的对象存储相同的数据时,lambda可以使用吗?

橘子和苹果,真的。函数并不意味着用于“存储”任何东西,而是用于执行某些计算。事实上,它可以通过参数defaults或闭包来捕获一些值,虽然对某些用例非常有用,但并不意味着替换正确的对象或集合。所以答案是:取决于你想用这些值和你的功能做什么。

注意:从技术上讲,你在这里所做的是(几乎)所谓的“部分应用”(你只需要将Test.f重命名为Test.__call__并在第二个例子中使用t("hello")))。函数的部分应用是一种机制,通过该机制,当使用N-x(带有x <N)参数调用时,N个参数的函数返回Nx参数的函数,当使用缺少的参数调用时,将返回结果原始功能,即:

def foo(a, b=None):
   if b is None:
       return lambda b, a=a: foo(b, a)
   return a + b

# here, `f` is a partial application of function `foo` to `1`
f = foo(1)
print(f)
f(2)

在这种情况下,我们使用闭包捕获a,在函数式编程传统中 - “部分应用”也主要是函数式编程概念FWIW。虽然它确实支持一些FP特性和习惯用法,但Python首先是一种OO语言,并且由于闭包是FP等价的对象(闭包是一种将状态和行为封装在一起的方法),所以实现部分应用程序也是有意义的。作为适当的类,或者使用“ad hoc”专用对象(你的Test类,还有Method对象),或者使用更通用的“部分”类 - which already exists in the stdlib as functools.partial


1
投票

定义函数或lambda时,参数的默认参数值将被计算一次。它不会在每个呼叫站点进行评估。 (这就是为什么你通常不能使用[]作为默认参数而必须指定None,并且每次调用函数时都要编写用于分配新列表的代码。)

如果lambda,函数或类是合适的,它实际上取决于周围的代码。通常,如果只有一个操作且状态不能直接从外部变异(仅在操作中),则lambda或函数是合适的。

© www.soinside.com 2019 - 2024. All rights reserved.