LBYL与EAFP漫谈

栏目: IT资讯 · 发布时间: 6年前

内容简介:LBYL 的意思是“Look before you leap.” 指在程序执行之前做好检查。比如下面这段代码:EAFP 的意思是“Easier to ask for forgiveness than permission.” 在编程方面指的是相信程序会正确执行,如果出错了再处理错误,比如上面这段代码用 EAFP 风格写就是下面这样:很多情况下,两种方式的写法是可以互相替换的,但是

LBYL 的意思是“Look before you leap.” 指在程序执行之前做好检查。比如下面这段代码:

if "key" in my_dict:
    x = my_dict["key"]
else:
    # handle missing key

EAFP 的意思是“Easier to ask for forgiveness than permission.” 在编程方面指的是相信程序会正确执行,如果出错了再处理错误,比如上面这段代码用 EAFP 风格写就是下面这样:

try:
    x = my_dict["key"]
except KeyError:
    # handle missing key

很多情况下,两种方式的写法是可以互相替换的,但是 Python 鼓励 EAFP 。原因是这种方法的可读性更高,速度也更快(只有在出错的时候才需要处理,而 LBYL 需要每次运行都检查)。

现在的大多数语言都有异常处理机制了,比如 Java, Python, Ruby 等,没有异常处理机制的都是一些古老的语言,比如 C 语言。但是没有异常处理机制并不代表程序总能运行正确,所以 C 语言需要其他形式来处理程序(函数)不能正确运行的情况,一般的方法是返回 0 表示运行正常,其他值表示运行异常。

但是这种处理形式有两个缺点(这部分可以参考《代码之髓》这本书的第 6 章):第一是可能遗漏错误。比如一个函数在大部分情况下都能正确运行,只有在很少的情况下会出错,或者只有改变了环境之后才会出错。那么很可能 程序员 会默认这个函数总是正确的,而忘记处理这个异常。如果是 Java 的话,程序员就必须在调用函数的地方处理掉所有可能的异常(虽然很多 Java 程序员喜欢不优雅地用 RuntimeError 处理所有的异常)。更让人头疼的事情是,一旦这“极少数”的情况发生了,那么错误经常不在错误出现的地方,而在很外层的一个调用处。你要花很多时间调试才能找到最终出错的地方。如果有异常处理机制的话,异常栈通常会直接给出 Exception 发生的地方。

第二个缺点是会使代码的可读性下降。因为要检查函数的返回值,要写很多 if-else ,程序真正的逻辑就变得难以阅读。我记得有位高人说过这么一句话,具体是谁说的记不得了,大意是:“高级语言和低级语言的区别是,需要不需要写很多与程序的逻辑无关的东西。” 很多 if-else ,很难看出这个只是判断,还是程序逻辑/业务的判断。如果用 try-catch ,那么 try 代码块里面可以只写程序的逻辑,在 except 里面处理所有的异常。

即使在有异常处理机制的语言中,比如 Python,很多人喜欢做的一个事情是在子函数用 if 判断,然后 logger.error + return。其实不如 raise ,然后在调用者那里 try-catch,更能表达逻辑。

if not monitor_config.link:
    logger.error(f'{self} does not associate with link')
    return

此外,Python 语言内置的协议也大量使用了异常的机制。比如《fluent python》(314页)关于重载加运算符 __add__ 就提到,为了遵守鸭子精神,不要测试 other 操作数的类型,而是应该捕获异常,然后抛出 NotImplemented

这样的好处是,比如我们定义了一个新的数据类型,支持和 int 相加  a.__add__(4) 。但是内置的 int 可不支持和我们自定义的类型相加, 4.__add__(a) 就会抛出异常。这时解释器尝试用  __radd__ 来处理(即 a.__add__(4) )。如果 int__add__ 是实现是相加对象的类型,如果不符合预期就抛出一个 TypeError ,就没有这样的便利了。

但是 EAFP 在某些情况下可能是不可行的,它的一个问题就是等错误发生的时候,程序已经运行了一半,如果函数会造成一些副作用,那么这个时候副作用已经发生了。这种情况下,如果没有数据事务这种外部的东西来提供原子性的话,就比较麻烦了,需要手动清理副作用的状态。而 LBFY 这种风格可以尽量保证提供给程序的参数正确,可以顺利运行完成。

其实我想讨论这二者的区别的真正地方是,在生活中也会有这两种风格的处理方式。

团队管理上 try-catch 更自由,更人性化,大家可以关注自己“做事的逻辑”而没有很多条条框框,在程序上 if 可能就多了一次判断,但是在实际生活中的话,这种 if 可能是各种各样的沟通和 ask permission,效率可就不只低这么多了。但是换句话来说,严谨的系统容不得做到半路才出现 “Exception”,还是需要“Look before you leap”的。

参考资料:

  1. https://www.codeproject.com/Tips/490765/If-else-instead-of-try-catch
  2. https://www.quora.com/When-should-I-use-try-catch-instead-of-if-else
  3. https://en.wikiquote.org/wiki/Grace_Hopper
  4. https://stackoverflow.com/questions/12265451/ask-forgiveness-not-permission-explain
  5. https://stackoverflow.com/questions/11360858/what-is-the-eafp-principle-in-python

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

冒号课堂

冒号课堂

郑晖 / 电子工业出版社 / 2009-10 / 65.00元

《冒号课堂》以课堂对话的形式,借六位师生之口讲述编程要义。上篇对编程范式作了入门性的介绍,并对一些流行的编程语言进行了简评;下篇侧重阐发软件设计思想,其中在范式上以OOP为主,在语言上以C++、Java和C#为主。全书寓庄于谐,深入浅出,既可开阔眼界,又能引发思考,值得编程爱好者品读。一起来看看 《冒号课堂》 这本书的介绍吧!

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具