【发布时间】:2010-02-19 05:18:34
【问题描述】:
我听说过python中的延迟评估(例如here),它只是指解释器如何仅在使用lambda时对其进行评估?或者这是描述由于 python 的动态设计而在运行时之前不会捕获很多错误的正确术语?
还是我完全错过了什么?
【问题讨论】:
标签: python lambda interpreter evaluation
我听说过python中的延迟评估(例如here),它只是指解释器如何仅在使用lambda时对其进行评估?或者这是描述由于 python 的动态设计而在运行时之前不会捕获很多错误的正确术语?
还是我完全错过了什么?
【问题讨论】:
标签: python lambda interpreter evaluation
延迟评估是在需要时才评估表达式。在大多数语言中,您使用 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 或list_zip_archive。list_files 函数不需要知道将读取哪些文件。使用 thunk,它不必读取每个文件。在适当的延迟评估中,一旦您评估了“thunk”,它将用评估的副本替换自己,因此评估它两次不会比评估一次更多的工作。还有其他方法可以完成相同的事情,例如使用缓存值的类和对象。
延迟评估是Scheme中(相对)常见的习语。在 Haskell 中,默认情况下评估是延迟的,您不需要任何语法来执行它(有特殊的语法可以关闭它)。
【讨论】:
functools.partial 来冻结参数:codepad.org/fwxLbl7l
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,甚至是一个习语,它使代码更简单。
【讨论】:
if-then-else 必须进行类型检查,但除此之外,评估被推迟。例如,你可以写if True then 5 else undefined,这样编译和运行都很好(结果是5,正如预期的那样)。你的if-else 在 Python 中工作,即使它没有在静态语言中进行类型检查,这与评估策略无关。