在 python 中,引号运算符的等价物是什么?我发现需要延迟评估。例如,假设在下面的 lisp 伪代码中我有:
a = '(func, 'g)
g = something
(eval a)
我正在做的是将评估推迟g
到以后。这是必要的,因为我想g
稍后定义。这个伪代码在python中的等效思想是什么?
在 python 中,引号运算符的等价物是什么?我发现需要延迟评估。例如,假设在下面的 lisp 伪代码中我有:
a = '(func, 'g)
g = something
(eval a)
我正在做的是将评估推迟g
到以后。这是必要的,因为我想g
稍后定义。这个伪代码在python中的等效思想是什么?
a = lambda: func(g)
g = something
a()
这不是最直接的翻译——最直接的翻译会使用一个字符串和eval
——但它可能是最合适的。无论如何,引用可能不是您在 Lisp 中想要的。您可能想要delay
做某事或创建一个lambda
. 请注意,func
andg
是lambda
函数中的闭包变量,而不是符号,因此如果您a
从具有不同绑定的环境调用func
or g
,它仍将使用来自a
定义环境的变量。
在Lispeval
和 Python 中,用于延迟评估都是不好的。
在 Python 和 Lisp 中,您可以使用闭包延迟评估:
def print_it(x):
def f():
print g(x)
return f
f = print_it(42)
def g(x):
return x * x
f()
请注意,闭包中捕获的不是变量的值,而是变量本身,这有时令人惊讶:
fa = []
for x in range(10):
def g():
print x
fa.append(g)
for f in fa:
f() # all of them will print 9
x = 42
fa[0]() # the output will be 42
要解决这个问题(Common Lisp 中也可能存在),您可能会看到如下内容:
for x in range(10):
def g(x = x):
print x
fa.append(g)
或(在 CL 中)之类的东西
(let ((a a))
(lambda () (print a)))
Python 也有lambda
匿名函数的特殊形式,但它们仅限于一个表达式,不能包含任何语句。相反,本地def
函数是没有任何限制的常规函数。
for x in range(10):
# print is a statement in Python 2.x and cannot be in a lambda
fa.append(lambda x=x: sys.stdout.write(str(x) + "\n"))
最后,Python 2.x 有语法限制,封闭变量是只读的,因为如果函数中有赋值(或扩充赋值),则只有两种可能性:
global x
)特别是排除了被分配的变量可能是封闭函数范围的局部变量。
Python 3.x 通过提供新的可能声明消除了这个限制nonlocal x
,现在这个著名的adder
例子可以实现为
def adder(x):
def f(y):
nonlocal x
x += y
return x
return f