Python not演算子の使い方とis not Noneの違い

Pythonで「変数が空かどうか」を調べたくてif not x:と書いたのに、思った通りに動かず戸惑ったことはないでしょうか。0や空文字が混ざるデータを扱うと、「値が入っているのに空扱いされた」「Noneだけを弾きたかったのに、他の値まで弾かれた」といった不具合につながりがちです。
この記事では、Pythonのnot演算子がデータ型ごとにどう判定するのかをまとめました。あわせて、is not Noneとの違いと使い分けの基準も解説します。

この記事で分かること

  • not演算子の基本的な意味
  • None・ブール型・数値・文字列・リスト・辞書での判定結果
  • if not xとis not Noneの違い
  • どちらを使えばよいかの判断基準

先に結論

  • if not xは、Noneだけでなく0・空文字・空リスト・空辞書もまとめて「偽」扱い
  • is not Noneは、Noneかどうかだけを見る判定で、0や空文字は「Noneではない」ので条件を通過
  • 「中身が空っぽ」をまとめて弾きたいならif not x、「未設定(None)」だけを区別したいならis None・is not None

not演算子とは

Pythonのnot演算子は、他の言語の!(論理否定)演算子と同じ意味を持ちます。
Pythonには!という否定演算子がなく、代わりに英単語のnotを使います(!=は「等しくない」を表す別の演算子です)。notは後ろに置いた値を真偽値(TrueかFalse)として評価し、その結果を反転させます。
Pythonのif文は、条件式にTrueやFalse以外の値も書けます。このとき、値ごとに「真として扱うか、偽として扱うか」がルールで決まっています。このルールを知らないままif not xを使うと、冒頭のような想定外の動きにつながります。

偽として扱われる値

if文の条件で偽として扱われる代表的な値は、次のとおりです。

  • None
  • False
  • 数値の0(0、0.0)
  • 空文字("")
  • 空のリスト([])
  • 空の辞書({})

これら以外は、基本的に真として扱われます。たとえば-1や0.0001のように、0に近くても0そのものでなければ真です。つまりnotを付けたif not xは、xが上の一覧に当てはまるときに処理が実行されます。

実行例

データ型ごとに、if notがどう動くかを順に見ていきます。コードと出力結果をセットで載せているので、手元で動かして確かめる際の参考にしてください。

None

Noneが代入されている変数はすべて同じ結果となります。Noneは「値が存在しない」ことを表す特別な値で、if文では常に偽として扱われます。

param = None
if not param:
  print('None')
None

ブール型

Falseをnotで反転するとTrueになるので、ifの中身が実行されます。

bl = False
if not bl:
  print('not case')
not case

数値

整数では0だけが偽で、1や-1は真として扱われます。負の数でも真になる点は、見落としやすいので注意してください。

num1 = 0
num2 = 1
num3 = -1
if not num1:
  print('not case1')
if not num2:
  print('not case2')
if not num3:
  print('not case3')
not case1

小数でも考え方は同じです。0.0001のように極端に小さい値でも、0でなければ真になります。

num_f1 = 0
num_f2 = 1.0
num_f3 = 0.0001
if not num_f1:
  print('not case1')
if not num_f2:
  print('not case2')
if not num_f3:
  print('not case3')
not case1

文字列

空文字("")は偽、1文字でも入っていれば真です。この例では、Noneが入った変数もnotで同じように拾えることが分かります。最後のif str3:のようにnotを付けなければ、「値が入っているとき」の判定になります。

str1 = ""
str2 = None
str3 = "Hello"
if not str1:
  print('not case1')
if not str2:
  print('not case2')
if not str3:
  print('not case3')
if str3:
  print(str3)
not case1
not case2
Hello

リスト

要素が1つもない空のリストは偽として扱われます。「リストが空かどうか」を調べたいとき、len(ary) == 0と書かなくてもif not aryで済みます。

ary = []
if not ary:
  print('array is empty')
array is empty

辞書

辞書も同様に、空の{}は偽、キーが1つでもあれば真です。

dic1 = {}
dic2 = {'name': 'taro'}
if not dic1:
  print('empty dic')
if dic2:
  print(dic2)
empty dic
{'name': 'taro'}

is not None

ここまでのif not xは、None・0・空文字・空リストなどをひとまとめに「空」として扱っていました。一方、「Noneかどうか」だけを調べたい場面もあります。そこで使うのがis not Noneです。
is not Noneで判定すると0や空文字もTrueになります。
つまり、0や""は「Noneではない」と判断されるため、ifの中身が実行されます。if not xとは判定の粒度がまったく違います。
なお、Noneとの比較には==ではなくisを使うのがPythonの作法です。Noneはプログラム中に1つしか存在しない特別な値なので、「同じ値か」ではなく「同じ物か」を確かめるisが適しています。

str1 = ""
str2 = "Hello"
if str1 is not None:
  print(f"str1={str1}")
if str2 is not None:
  print(f"str2={str2}")
str1=
str2=Hello

空文字のstr1も表示されています。if not str1なら空文字は弾かれましたが、is not Noneでは通過します。

num1 = 0
num2 = 1
if num1 is not None:
  print(f"num1={num1}")
if num2 is not None:
  print(f"num2={num2}")
num1=0
num2=1

数値の0も通過します。数量や点数のように、0が正しい値として入る場面では、この性質が役立ちます。

ary1 = []
ary2 = [1]
if ary1 is not None:
  print(ary1)
if ary2 is not None:
  print(ary2)
[]
[1]
dic1 = {}
dic2 = {'name': 'taro'}
if dic1 is not None:
  print(dic1)
if dic2 is not None:
  print(dic2)
{}
{'name': 'taro'}

空のリストや空の辞書も、Noneではないので通過します。

if notとis not Noneの違いを一覧で確認

ここまでの結果を、値ごとにまとめます。表の値は「条件が成立してifの中身が実行されるか」を表しています。

値 if not x if x is not None
None 成立する 成立しない
0 成立する 成立する
空文字 成立する 成立する
空のリスト 成立する 成立する
空の辞書 成立する 成立する
"Hello" 成立しない 成立する
1 成立しない 成立する

Noneのときだけ両者の挙動が揃い、それ以外の「空っぽな値」では結果が食い違います。

どちらを使うべきか

迷ったときは、「0や空文字を、Noneと同じ『値がない』状態として扱ってよいか」を基準に考えると判断しやすくなります。

  • 0や空文字も「未入力」として扱いたい場合はif not x
  • 0や空文字は正しい値で、Noneだけを「未設定」として区別したい場合はis None・is not None

たとえば、数量を入力するフォームでif not quantity:と書くと、利用者が0を入力しただけでエラー扱いになってしまいます。この場合はif quantity is None:で未入力を判定するのが適切です。
反対に、名前欄の空文字を未入力として弾きたいときにif name is not Noneだけで判定すると、空文字がすり抜けます。この場合はif not name:のほうが意図に合います。

よくある疑問

リストが空かどうかはlen()とnotのどちらで調べるべきですか

どちらでも動きますが、if not ary:のほうがPythonらしい書き方とされています。コーディング規約のPEP 8でも、シーケンス(文字列・リスト・タプル)の空判定には「空のシーケンスは偽として扱われる」性質を使うよう勧められています。

Noneの判定に== Noneと書いてはいけませんか

動作はしますが、is None・is not Noneを使うのが推奨です。Noneは1つしか存在しない特別な値なので、同一かどうかを確かめるisのほうが意図が明確で、思わぬ不具合も避けられます。

まとめ

  • notは後ろの値を真偽値として評価して反転する演算子で、他の言語の!に相当
  • if not xは、None・False・0・空文字・空リスト・空辞書をまとめて拾う判定
  • is not NoneはNoneかどうかだけを見る判定で、0や空文字は真
  • 0や空文字を有効な値として扱うならis None系、まとめて「空」とみなすならif not x

判定に使う値にどんなデータが入りうるのかを先に整理しておけば、if not xとis not Noneのどちらを選ぶべきかは自然に決まります。「0や空文字が来たらどうなるか」を一度頭の中で通しておくと、思わぬバグを防げます。

このエントリーをはてなブックマークに追加
にほんブログ村 IT技術ブログへ

コメント

メールアドレスが公開されることはありません。 ※ が付いている欄は必須項目です