首页 > 代码库 > EAFP和LBYL 两种防御性编程风格

EAFP和LBYL 两种防御性编程风格

EAFP:Easier to ask for forgiveness than permission 获得事后原理总是比事先得到许可要容易的多。

这个EAFP在python中表现的比较多。EAFP,This common Python coding style assumes the existence of valid keys or attributes and catches exceptions if the assumption proves false. This clean and fast style is characterized by the presence of many try andexcept statements. The technique contrasts with the LBYL style common to many other languages such as C.

LBYL:

Look before you leap. 跳跃This coding style explicitly tests for pre-conditions before making calls or lookups. This style contrasts with the EAFP approach and is characterized by the presence of many if statements.

In a multi-threaded environment, the LBYL approach can risk introducing a race condition between “the looking” and “the leaping”. For example, the code, if key in mapping: return mapping[key] can fail if another thread removes key from mapping after the test, but before the lookup. This issue can be solved with locks or by using the EAFP approach.

在多线程编程中,LBYL能导致竞争状态。例如:if key in mapping:return mapping[key]会失败如果另一个线程在测试后移除了key。这个问题能够通过通过锁结局或使用EAFP.

检查数据可以让程序更健壮,用术语来说就是防御性编程。
检查数据的时候,有这样的两种不同的风格。
LBYL:Look Before You Leap  
EAFP:It‘s Easier to Ask Forgiveness than Permission 
LBYL即事先检查。
EAFP是不检查,出了问题由异常处理来处理。

下面通过一个单词统计的例子来阐释一下。

d = {}  
words = [a,d,a,c,b,z,d]
#LBYL
for w in words:  
    if w not in d:  
        d[w] = 0  
    d[w] += 1  

#EAFP
for w in words:  
    try:  
        d[w] += 1  
    except KeyError:  
        d[w] = 1  

 

这两种风格各有好坏。
对于LBYL,容易打乱思维,本来业务逻辑用一行代码就可以搞定的。却多出来了很多行用于检查的代码。防御性的代码跟业务逻辑混在一块降低了可读性。
而EAFP,业务逻辑代码跟防御代码隔离的比较清晰,更容易让开发者专注于业务逻辑。
不过,异常处理会影响一点性能。因为在发生异常的时候,需要进行保留现场、回溯traceback等操作。但其实性能相差不大,尤其是异常发生的频率比较低的时候。
还有一点要注意的是,如果涉及到原子操作,强烈推荐用EAFP风格。比如我某段程序逻辑是根据redis的key是否存在进行操作。如果先if exists(key),然后do something。这样就变成2步操作,在多线程并发的时候,可能key的状态已经被其他线程改变了。而用EAFP风格则可以确保原子性

上面参考了部分博文。