我听说过python中的延迟评估(例如here),它只是指的是只有在使用它们时,解释器如何评估lambdas?或者,这是否是描述由于python的动态设计如何在运行时之前不会捕获许多错误的正确术语?
或者我完全错过了什么?
答案 0 :(得分:14)
延迟评估是指在需要之前不评估表达式。在大多数语言中,您使用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”是延期评估。使用thunks可以分离您的疑虑:
list_files
可以替换为list_ftp_files
或list_zip_archive
。list_files
函数不需要知道将读取哪些文件。通过thunk,它不必读取每个文件。在正确的延期评估中,一旦你评估了“thunk”,它就会用一个评估版本替换它自己,所以评估它两次就不会比评估它一次了。还有其他方法可以实现相同的功能,例如使用缓存值的类和对象。
延期评估是Scheme中(相对)常见的习语。在Haskell中,默认情况下会推迟评估,并且您不需要任何语法(有关闭它的特殊语法)。
答案 1 :(得分:8)
Dietrich的答案很好,但我只想补充说,最简单的延期评估形式是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,甚至是一个成语,使代码更简单。