Pythonのelse詳細

3434 ワード

Pythonでelseの基本的な使い方は条件制御文の中のif...elif...else...であることはよく知られていますが、elseには他の二つの用途があります。一つはサイクルの終わりに、もう一つはエラー処理のtryに使います。これは元々Pythonの標準文法ですが、ほとんどの他のプログラミング言語とは習慣が違っていますので、意図的にまたは無意識的にこれらの使い方を無視してしまいました。また、これらの用法については0に該当していますか?×00 The Zen of Pythonの原則と、広く使われるべきでないことについても多くの論争があります。例えば、私が見た二冊の本の中で、二人の作者はそれぞれ違った態度を持っています。
サイクル中のelse
サイクルの後に付いてくるelse文はサイクル内でbreakが発生していない場合、つまり正常循環が完了した時にのみ実行されます。まず、挿入順序法の例を見ます。

from random import randrange
def insertion_sort(seq):
  if len(seq) 1:
    return seq
  _sorted = seq[:1]
  for i in seq[1:]:
    inserted = False
    for j in range(len(_sorted)):
      if i _sorted[j]:
        _sorted = [*_sorted[:j], i, *_sorted[j:]]
        inserted = True
        break
    if not inserted:
      _sorted.append(i)
  return _sorted
 
print(insertion_sort([randrange(1, 100) for i in range(10)]))

[8, 12, 12, 34, 38, 68, 72, 78, 84, 90]

この例では、並べ替えられた_に対してsorted要素は1つずつiと比較し、iが並べ替えられたすべての要素よりも大きい場合、並べ替えられたリストの最後に並ぶしかない。この時、私達はもう一つの追加の状態変数insertedを必要とします。巡回を完了するかそれとも途中でbreakされるかをマークします。この場合、この状態変数をelseで置換できます。

def insertion_sort(seq):
  if len(seq) 1:
    return seq
  _sorted = seq[:1]
  for i in seq[1:]:
    for j in range(len(_sorted)):
      if i _sorted[j]:
        _sorted = [*_sorted[:j], i, *_sorted[j:]]
        break
    else:
      _sorted.append(i)
  return _sorted
print(insertion_sort([randrange(1, 100) for i in range(10)]))

[1, 10, 27, 32, 32, 43, 50, 55, 80, 94]

これはとてもかっこいいやり方だと思います。ただし、breakは後のelse文をトリガします。ループがない場合もあります。

while False:
  print("Will never print!")
else:
  print("Loop failed!")


Loop failed!

エラーキャプチャ中のelse
try...except...else...finallyフロー制御文法は、try文に発生するエラーをキャプチャするためにexceptを使用し、対応する処理を行う。一方、elseはエラーが発生していない場合を処理するために使用される。finallyはtry文の後始末を担当します。簡単な例によって示されてもよい。

def divide(x, y):
  try:
    result = x / y
  except ZeroDivisionError:
    print("division by 0!")
  else:
    print("result = {}".format(result))
  finally:
    print("divide finished!")
divide(5,2)
print("*"*20)
divide(5,0)


result = 2.5
divide finished!
********************
division by 0!
divide finished!
もちろん、状態変数の方法でelseの代わりにすることもできます。

def divide(x, y):
  result = None
  try:
    result = x / y
  except ZeroDivisionError:
    print("division by 0!")
  if result is not None:
    print("result = {}".format(result))
  print("divide finished!")
 
divide(5,2)
print("*"*20)
divide(5,0)


result = 2.5
divide finished!
********************
division by 0!
divide finished!
締め括りをつける
これらのelseの使い方は、直感やimplicitではなく、explicitではないと主張する人がいます。しかし、このような判決は「具体的な応用シーンとPythonに対する理解が必要であり、必ずしも新人に友好的な文法が必要ではないと思います。もちろん、すべてのところでこの文法を使うことを勧めません。for/while...elseの最大の欠点は、elseがfor/fileに揃う必要があります。多層嵌合や循環体が長すぎると、elseを使うにはとても適しないということです。いくつかの簡単な循環制御文の中で、私達はelseを通していくつかの厄介な状態変数を抜け出します。これが一番Pythonicの応用シーンです。