避免elif和ELSE IF的阶梯和阶梯问题
本文重点讨论了C和Python编程语言中的elif和else if梯子和楼梯问题以及解决方法。
ELIF和ELSE IF的阶梯和楼梯问题
有些程序员对长序列的IF、ELSE IF、ELSE IF、ELSE IF等,通常以最后的ELSE子句结束,他们会感到羞愧。在有ELSE IF或elif语法的语言中,这种模式被称为 “ELSE IF阶梯”。在没有ELSE IF或elif的语言中,每个概念性的ELSE IF都被写成一个IF,放在其前身的ELSE部分中。在缩进的情况下,它看起来就像在下一个倒置的楼梯。
- 这形成了一个不可取的、难以阅读的、更糟糕的、容易出错的编程结构。
- 有了缩进,楼梯的代码就会从屏幕的右边掉下来。
- 对于一些程序员来说,问题在于美学,而另一些人则担心可维护性。
- 有时,语法确实妨碍了表达需要表达的逻辑。
从根本上说,这种模式既表达了优先次序,也表达了短路。
- 优先级是指在一组条件中,只对第一个 “真 “的语句进行处理。
- 短路是在发现第一个条件为真后,甚至没有进一步的测试条件表达式被评估。这很重要,因为条件表达式可能会调用一些函数,比如IF(42 < somefunction( x ))。.其中一些函数可能是有状态的,并且有副作用。
任何替代方案都必须保持这些语义。此外,有时有些语句只有在某些先前的条件失败时才需要执行,但对所有后来的条件都需要执行。
示例:
// Many people find this code
// undesirable to work with.
if (a < b)
{
// a<b statements
}
else if (b < c)
{
// b<c statements
}
else if (c < d)
{
// Statements before every
// remaining possibility
a = 45;
// c<d statements
}
else if (d < e)
{
// Statements before every
// remaining possibility
a = 45;
// d<e statements
}
else if (e < f)
{
// Statements before every
// remaining possibility
a = 45;
// e<f statements
}
else
{
// Statements before every
// remaining possibility
a = 45;
// else statements
}
# Many people find this code
# undesirable to work with.
if (a < b):
# a<b statements
elif (b < c):
# b<c statements
elif (c < d):
# statements before every
# remaining possibility
a = 45
# c<d statements
elif (d < e):
# statements before every
# remaining possibility
a = 45
# d<e statements
elif (e < f):
# statements before every
# remaining possibility
a = 45
# e<f statements
else:
# statements before every
# remaining possibility
a = 45
# else statements
# end of IF-ELIF-ELSE
pass
# Contributed by David A. Kra
请注意,这种重复适用于后面每种可能性的语句 ( a = 45 ) 违反了 “不要重复自己”(DRY)原则。任何变化都必须在每个条件之后重复。
消除ELSE IF和ELSE的两步方法
以下方法取代了上面的ELSE IF和ELSE代码,消除了对它们的需要,同时保留了优先级和短路语义。
1.将一组独立的IF语句放在一个单次迭代的循环中。不要使用任何ELSE IF或ELSE语法。
2.添加一个循环退出语句作为_each_IF内的最后一条语句。BREAK是优于CONTINUE的。python代码中提供了for和while版本的循环。BREAK必须与while版本的循环一起使用。
示例:
// This is the ELSEless equivalent.
do
{
// This is a one pass WHILE loop.
if (a < b)
{
// a<b statements
break;
}
if (b < c)
{
// b<c statements
break;
}
// Statements for every remaining
// possibility
a = 45;
// More conditions
if (c < d)
{
// c<d statements
break;
}
if (d < e)
{
// d<e statements
break;
}
if (e < f)
{
// e<f statements
break;
}
// else statements
q = 75;
// break unnecessary.
// Already at end of loop.
} while (0);
// Once was enough. Do not repeat it.
# This is the ELSEless equivalent.
# for version # !!!! Use any one and
# only one value in the iteration set. !!!!
# forversion="""for i in ("once - elseless"):"""
# while version # !!!! requires a BREAK
# at the bottom !!!!
# whileversion="""while(True):"""
while (True):
if (a < b):
# a<b statements
break
if (b < c):
# b<c statements
break
# statements for every remaining
# possibility indenting aligns
# with the if's above
a = 45
if (c < d):
# c<d statements
break
if (d < e):
# d<e statements
break
if (e < f):
# e<f statements
break
# else statements
# indenting aligns with the if's above
q = 75
# for version: break unnecessary.
# Already at end of one-pass loop.
# while version: break absolutely
# required for the while version
break # required for the while version
pass # past end of else-less IF-ELIF-ELSE
# Contributed by David A. Kra
解释: 来跳到循环的下一个迭代。然而,在这种单次循环的使用中,不会也不可能有任何下一次迭代。
这个解决方案利用了这些迭代语句来代替ELSE IF和ELSE .BREAK , 或 CONTINUE 语句使循环内的所有其他语句被绕过。当循环被指定为只有一个迭代时,甚至CONTINUE语句也会导致退出循环。
在代码示例中,无论是CONTINUE还是BREAK都可以在C语言版本或python的for循环版本中使用。python的while循环版本需要使用break语句,包括在最后的else-equivalent语句之后的语句。
另外,在IF语句之间,可以有额外的语句,在测试任何后面的条件之前执行。
加工成本或管理费用:python版本确实经历了设置循环的最小开销。C语言的开销更小,如果使用一个聪明的优化编译器,可能根本就没有开销。
总结
乍一看,这个成语看起来是一个不必要的技巧。经过更仔细的考虑,它使应用程序更容易理解和维护。我会在编译语言中使用它,特别是使用优化编译器。我也会在解释型语言中使用它,除非是在对性能要求极高的热点地区。即使在那里,我也会在最初使用它,只有在对应用程序进行全面调试之后,才会恢复到if、elif、elif、elif…else。