请考虑以下示例:
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')
通过捕获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
定义函数或lambda时,参数的默认参数值将被计算一次。它不会在每个呼叫站点进行评估。 (这就是为什么你通常不能使用[]
作为默认参数而必须指定None
,并且每次调用函数时都要编写用于分配新列表的代码。)
如果lambda,函数或类是合适的,它实际上取决于周围的代码。通常,如果只有一个操作且状态不能直接从外部变异(仅在操作中),则lambda或函数是合适的。