考虑以下示例:
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')
答案 0 :(得分:1)
定义函数或lambda时,一次评估参数的默认参数值。不会在每个呼叫站点进行评估。 (这就是为什么通常不能使用[]
作为默认参数,而必须指定None
并编写代码以在每次调用该函数时分配一个新鲜列表的原因。)
lambda,函数或类是否合适,实际上取决于周围的代码。通常,如果只有一个操作并且状态不能直接从外部(仅在操作内部)进行更改,则适合使用lambda或函数。
答案 1 :(得分:1)
通过捕获lambda定义中的变量,似乎保留了原始变量。
因为您将其设置为lambda的test
参数的默认值,并且Python在创建函数时仅对默认值评估一次。 FWIW,这与lambda
关键字的使用无关-lambda
只是语法糖,使用“功能全面”的功能,您将得到完全相同的结果,即:>
test = 123
def f(x, test=test):
print(x, test)
test = 456
f('hello')
当您还可以使用一个简单的对象来存储相同的数据时,可以使用lambda吗?
桔子和苹果,真的。函数并不是要用来“存储”任何东西,而是要执行一些计算。它可以通过参数defaults或通过闭包捕获某些值的事实,尽管在某些用例中非常有用,但这并不意味着可以替换适当的对象或集合。因此答案是:取决于您要对这些值和函数执行的操作。
NB:从技术上讲,您在这里所做的(几乎)是所谓的“部分应用程序”(您只需将 在这种情况下,在函数式编程传统中,我们使用闭包来捕获Test.f
重命名为Test.__call__
并使用t("hello")
在第二个示例中))。函数的部分应用是一种机制,通过该机制,N个参数的函数在用N-x(x 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等价(闭包是将状态和行为封装在一起的一种方式),因此实现部分应用程序也很有意义作为适当的类,可以使用“临时”专用对象(您的Test
类,也可以使用Method
对象),或者使用更通用的“部分”类-which already exists in the stdlib as functools.partial