python中的延迟评估

C-o*_*r-E 8 python evaluation lambda interpreter

我听说过python中的延迟评估(例如这里),它只是指的是只有在使用它们时,解释器如何评估lambdas?或者这是描述如何由于python的动态设计在运行时之前不会捕获许多错误的正确术语?

或者我完全错过了什么?

Die*_*Epp 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()
Run Code Online (Sandbox Code Playgroud)

在这里,list_files返回一堆文件名和一个"thunk"(没有参数的lambda),它返回文件的内容."thunk"是延期评估.使用thunk可以分离您的顾虑:

  • for循环不需要知道如何读取文件,因此list_files可以用list_ftp_files或替换list_zip_archive.
  • list_files函数不需要知道将读取哪些文件.使用thunk,它不必读取每个文件.

在适当的延迟评估中,一旦你评估了"thunk",它就会用一个评估版本替换它自己,所以评估它两次就不会比评估它一次了.还有其他方法可以实现相同的功能,例如使用缓存值的类和对象.

递延评估是Sch​​eme中(相对)常见的习语.在Haskell中,默认情况下会延迟评估,您不需要任何语法(有关闭它的特殊语法).

  • lambda是延迟的,但要小心存储,因为它们不会像你现在拥有的那样捕获fn:http://codepad.org/fXfIj364.另一个警告:http://codepad.org/poXS7nc2. (4认同)

Eli*_*sky 8

迪特里希的答案很好,但我只想补充说,最简单的延期评估形式是if声明:

if True:
  x = 5
else:
  x = y    # huh? what is y?
Run Code Online (Sandbox Code Playgroud)

这段代码解析并正确运行,虽然该else条款毫无意义 - y未定义.该else子句只被解析 - 所以它在语法上应该是有效的Python.这实际上可以用于一些简单的代码:

if stuff:
   print stuff.contents
else:
   print "no stuff"
Run Code Online (Sandbox Code Playgroud)

在强类型语言中,这不起作用,因为类型stuff.contents需要stuff具有contents属性的特定类型.在Python中,由于对语句的延迟评估if,这不一定是真的.stuff可能None显然没有属性,解释器将只else执行该子句而不执行第一个.因此,这是有效的Python,甚至是成语,使代码更简单.

参考讨论

  • 我认为你在第二个例子中混淆了类型系统和懒惰的评估."强烈"类型的语言可以使用惰性评估来做巧妙的技巧.例如,Haskell有一个非常强大的静态类型系统,有很多懒惰的评估!与Python不同,`if-then-else`必须进行类型检查,但除此之外,评估是延迟的.例如,你可以写`if True然后5 else undefined`,这编译并运行得很好(结果是5,正如预期的那样).你的`if-else`在Python中工作,即使它没有用静态语言进行类型检查也与评估策略无关. (7认同)