2010-02-19 69 views
8

我听说过python中的延迟评估(例如here),它仅仅指的是lambdas如何仅在使用它时才被解释器评估?或者这是一个合适的术语来描述,由于python的动态设计,它不会在运行时捕获许多错误?Python中的延迟评估

或者我完全错过了一些东西?

回答

8

迪特里希的回答是一个很好的,但我只想补充一点,推迟评价的最简单的形式是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,甚至是一个成语,它使代码更简单。

Reference discussion

+7

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

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”是延期评估。使用的thunk允许你分开你的顾虑:for循环不需要知道如何读文件

  • 的,所以list_files可以用list_ftp_fileslist_zip_archive更换。
  • list_files函数不需要知道哪些文件将被读取。使用thunk时,它不必读取每一个文件。

在正确的延期评估中,一旦您评估了“thunk”,它将用评估副本替换自己,因此评估两次将不会比评估一次更好。还有其他方法可以完成同样的事情,例如缓存值的类和对象。

延期评估是Sch​​eme中一个(相对)常见的习惯用法。在Haskell中,评估是默认推迟的,你不需要任何语法来完成它(有特殊的语法来关闭它)。

+4

拉姆达被推迟,但要小心保管,因为他们不捕捉FN,你目前有他们:http://codepad.org/fXfIj364。另一个警告:http://codepad.org/poXS7nc2。 – 2010-02-19 05:50:48

+0

这是一个很好的观点,也是我在Python编程时远离lambda的原因之一。 –

+1

这就是为什么我更喜欢内联函数+'functools.partial'来冻结参数:http:// codepad。org/fwxLbl7l – schlamar