我听说过 python 中的延迟评估(例如这里),它只是指解释器如何仅在使用 lambda 时对其进行评估?或者这是描述由于 python 的动态设计,它在运行时之前不会捕获很多错误的正确术语吗?
还是我完全错过了什么?
我听说过 python 中的延迟评估(例如这里),它只是指解释器如何仅在使用 lambda 时对其进行评估?或者这是描述由于 python 的动态设计,它在运行时之前不会捕获很多错误的正确术语吗?
还是我完全错过了什么?
延迟评估是在需要时才评估表达式。在大多数语言中,您使用类似的东西lambda
来完成这项工作。这是一个人为的示例,显示了部分概念:
def list_files():
for fn in os.listdir('.'):
yield fn, lambda: open(fn, 'r').read()
for fn, body in list_files():
if fn.endswith('.txt'):
print body()
在这里,list_files
返回一堆文件名和一个“thunk”(不带参数的 lambda),它返回文件的内容。“thunk”是延迟评估。使用 thunk 可以分离您的关注点:
list_files
可以替换为list_ftp_files
or list_zip_archive
。list_files
函数不需要知道将读取哪些文件。使用 thunk,它不必读取每个文件。在适当的延迟评估中,一旦您评估了“thunk”,它将用评估的副本替换自己,因此评估它两次不会比评估一次更多的工作。还有其他方法可以完成相同的事情,例如使用缓存值的类和对象。
延迟评估是 Scheme 中(相对)常见的习语。在 Haskell 中,默认情况下评估是延迟的,您不需要任何语法来执行它(有特殊的语法可以关闭它)。
迪特里希的回答很好,但我只想补充一点,延迟评估的最简单形式是if
声明:
if True:
x = 5
else:
x = y # huh? what is y?
此代码解析并正确运行,尽管该else
子句没有意义 -y
未定义。该else
子句仅被解析 - 因此它在语法上应该是有效的 Python。这实际上可以用于一些简单的代码:
if stuff:
print stuff.contents
else:
print "no stuff"
在强类型语言中,这是行不通的,因为类型stuff.contents
需要stuff
是具有contents
属性的特定类型。在 Python 中,由于 中语句的延迟评估if
,这不一定是真的。stuff
可以是None
显然没有属性的,解释器只会接受该else
子句而不执行第一个。因此,这是有效的 Python,甚至是一个习惯用法,它使代码更简单。