python中的延迟求值
我听说过python中的延迟求值(例如),它只是指只有在使用lambda时,解释器才会对其求值吗?或者,这是描述由于python的动态设计,它在运行时之前不会捕获许多错误的恰当术语吗python中的延迟求值,python,lambda,interpreter,evaluation,Python,Lambda,Interpreter,Evaluation,我听说过python中的延迟求值(例如),它只是指只有在使用lambda时,解释器才会对其求值吗?或者,这是描述由于python的动态设计,它在运行时之前不会捕获许多错误的恰当术语吗 还是我完全遗漏了什么?延迟求值是指直到需要时才对表达式求值。在大多数语言中,您使用类似于lambda的东西来实现这一点。下面是一个人为的例子,展示了部分概念: def list_files(): for fn in os.listdir('.'): yield fn, lambda: ope
还是我完全遗漏了什么?延迟求值是指直到需要时才对表达式求值。在大多数语言中,您使用类似于
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\u files
返回一组文件名和一个“thunk”(lambda,不带参数),返回文件内容。“thunk”是一个延迟评估。使用thunks可以分离您的关注点:
- for循环不需要知道如何读取文件,因此
可以替换为list\u文件
或list\u ftp\u文件
list\u zip\u存档
功能不需要知道将读取哪些文件。使用thunks,它不必读取每个文件list_files
延迟求值是Scheme中(相对)常见的习惯用法。在Haskell中,默认情况下延迟求值,并且不需要任何语法(有专门的语法用于关闭它)。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,甚至是一种使代码更简单的习惯用法
lambda延迟,但要注意存储,因为它们不会像您当前拥有的那样捕获fn:。还有一个警告:。这是一个很好的观点,也是我在用Python编写代码时远离lambda的原因之一。这就是为什么我更喜欢内联函数+
functools。要冻结参数,请使用partial
:我认为您在第二个示例中混淆了类型系统和惰性计算。“强”类型语言可以使用惰性求值来完成巧妙的操作。例如,Haskell有一个非常强大的静态类型系统,其中包含大量惰性评估!与Python不同,if-then-else
必须进行类型检查,但除此之外,计算是延迟的。例如,如果为True,则可以编写,如果为True,则可以编写5个else undefined
,这样编译和运行很好(结果是5,正如预期的那样)。您的if-else
在Python中工作,即使它在静态语言中没有键入check,这与评估策略无关。