[Pythonクイズ]「if len(yourlist) > 0:」を、もっとシンプルに書ける?:Pythonステップアップクイズ
len関数でリストの要素数を調べて、その数が0より大きいかどうかを比較したりしていませんか? チッチッ! リスト(コレクション)の性質を理解して、もっとPythonicなコードを書くようにしましょう!
【問題】
以下はリストを与えると、それが空でなければ「not empty」と、空なら「empty」と表示する関数fooの定義とその呼び出し例である。関数fooのif文は問題なく動作するが、無駄な記述がある。どのように修正できるだろうか。
def foo(yourlist):
if len(yourlist) > 0:
print('not empty')
else:
print('empty')
mylist = []
foo(mylist) # empty
どうもHPかわさきです。
最近、Pythonクイズをたくさんの方に見ていただけているようなんですよ。でも、理由が分からないんですよね。そして、見てくれる人が増えているにもかかわらず、Xのフォロワーさんの数は全く増えていないんですよ! 何とかなりません? や、まー、増えなくてもいいんですけどね。目立ちたくないから……(しょぼん)。
【答え】
正解のコード例を以下に示します。
def foo(yourlist):
if yourlist:
print('not empty')
else:
print('empty')
mylist = []
foo(mylist) # empty
問題文のコードではlen関数でyourlistに与えられるリストの要素数を取得して、それが0より大きいかどうかをif文で判定していました。実際には、リストが空でなければ真(True)と、空であれば偽(False)として扱われるので、上のコードのように記述できます。
【解説】
問題文にあるfoo関数は、yourlistに受け取ったリスト(あるいは何らかのコレクション)の要素数をlen関数で調べています。そして、それが0より大きければ(リストに要素が1個でも含まれていれば)「not empty」と表示して、そうでなければ(リストに空であれば)「empty」と表示します。
つまり、if文では「要素数を調べて、それが0より大きいかどうか」ではなく「リストが空でないかどうか」を判定しているといってよいでしょう。もちろん、問題文のコードでも問題なく動作します。
つまり、問題文にあるコードのifでは以下のような処理をしていました。
if コレクションの要素数 > 0:
print('not empty')
else: # コレクションの要素数が0(マイナスはあり得ない)
print('empty')
しかし、これは次のように置き換えられるということです。
if コレクションが空でない:
print('not empty')
else: # コレクションが空
print('empty')
では、どうすれば、要素が空でないかどうかを調べられるのでしょう(わざとらしいですねぇ)。
Pythonではリストやタプル、辞書、集合などのコレクションはそこに要素が1つもない場合、真偽値の判定という場面では偽(False)として扱われます。逆に1つ以上の要素があれば、真(True)として扱われます。おっと忘れていました。文字列も文字を0個以上の文字を含むコレクションなことは思い出しておきましょう。つまり、真偽値の判断において、空文字列は偽(False)として、そうでない文字列は真(True)として扱われます。詳細についてはPythonドキュメント「真理値判定」などを参考にしてください。
この他に偽として扱われるのは、None、False、数値のゼロ(整数値の0、浮動小数点数値の0.0など)、range(0)などです。
注意したいのは、[0]は0(偽として評価される値)を含んでいますが、空のリストではないので真と評価される点です。0は偽ですし、[]も偽ですが、[0]は真です。慣れないうちは「何で?」となるかもしれませんね。
以下のコードでは、1個の要素を持つリストをif文の条件に記述しています。
mylist = [0]
if mylist: # 空のリストじゃないので真
print('not empty')
else:
print('empty')
mylistは空ではないので、この場合は真と評価され、上のコードでは「not empty」と表示されます。
ここではリストを例に取りましたが、他のコレクションでも同様です(気になる方はご自分で試してみてくださいね)。
というわけで、問題文にあるif文は次のように書き換えられます。
def foo(yourlist):
if yourlist:
print('not empty')
else:
print('empty')
mylist = []
foo(mylist) # empty
逆に「リストが空の場合」に何かをしたければ、次のようにnot演算子で真偽値を反転させればよいことも覚えておきましょう。
mylist = []
if not mylist: # リストが空なら真になる
print('empty')
なお、「要素数が5個よりも多ければ」のような条件のときには、このような単純な置き換えができないことには注意してください。このような置き換えが可能なのは、「コレクションの要素数が0より大きいかどうか = コレクションが空ではないかどうか = コレクションが真かどうか」をチェックしている場合です。
前回の『「list()」vs「[]」。空のリストを作る2つの方法に振る舞いの差はあるのかい?』はバイトコードが出てきたり、実行時間を計測してみたりとちょっと難しく感じたかもしれません。それと比べると、今回は「カンタンだよ!」って人が多いでしょうね。が、この振り幅の広さが大事だと思います(いいネタを思い付かなかったからというわけではないですよ?)。
そういうわけで、「Python入門」では「if文による条件分岐」なんかがオススメです。
Copyright© Digital Advantage Corp. All Rights Reserved.