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文の条件で偽として扱われる代表的な値は、次のとおりです。
NoneFalse- 数値の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 x0や空文字は正しい値で、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や空文字が来たらどうなるか」を一度頭の中で通しておくと、思わぬバグを防げます。
