PythonでNoneかどうかを判定するときは、x is None(Noneでないことは x is not None)と書きます。 None は「値がない」ことを表すただ1つのオブジェクトで、空文字 ""、空リスト []、0、False とは別のものです。if not x: と書くと、これらがすべて同じ扱いになるため、「Noneだけを見分けたい」ときは is None を使います。

この記事では、None・空文字・空リスト・0・False・NaN を「is None/== None/not x/len(x)==0」で判定した結果を1枚の早見表にまとめ、全パターンの実行結果を載せました。さらに、__eq__ を上書きしたクラスや NumPy 配列で == None が思わぬ結果になる例を再現し、X | None の型ヒント、pandas の NaN/None 判定、関数の引数デフォルトに None を使う定番コードまで、コピーして使える形で解説します。実行環境は Python 3.11.15、NumPy 2.4.4、pandas 3.0.2、mypy 2.3.1 です。

None・空文字・空リスト・0の判定早見表

次のコードで、14種類の値を5通りの方法で判定しました。

# n1.py
values = [
    ("None", None), ('""', ""), ('" "', " "), ("[]", []), ("{}", {}), ("()", ()),
    ("set()", set()), ("0", 0), ("0.0", 0.0), ("False", False),
    ('float("nan")', float("nan")), ('"0"', "0"), ("[None]", [None]), ('"None"', "None"),
]

def safe_len(x):
    try:
        return len(x) == 0
    except TypeError:
        return "TypeError"

print(f"{'値':<14}{'is None':<9}{'== None':<9}{'not x':<7}{'bool(x)':<9}{'len(x)==0'}")
for label, v in values:
    print(f"{label:<14}{str(v is None):<9}{str(v == None):<9}{str(not v):<7}{str(bool(v)):<9}{safe_len(v)}")

実行結果を表に整えたものが、この記事の早見表です。

値 x is None x == None not x bool(x) len(x) == 0
None True True True False TypeError
""(空文字) False False True False True
" "(空白1つ) False False False True False
[](空リスト) False False True False True
{}(空辞書) False False True False True
()(空タプル) False False True False True
set()(空集合) False False True False True
0 False False True False TypeError
0.0 False False True False TypeError
False False False True False TypeError
float("nan") False False False True TypeError
"0"(文字列) False False False True False
[None] False False False True False
"None"(文字列) False False False True False

この表から読み取れる要点は4つです。

要点 内容
is None が True になるのは None だけ 「値がない」ことだけを見分けたいときはこれ
not x は「空っぽ・ゼロ」も True None・空文字・空のコンテナ・0・False をまとめて扱う
len(x) == 0 は長さを持つ型だけ None や数値に使うと TypeError
NaN はどの判定でも「値あり」側 math.isnan() や pd.isna() で別に調べる

やりたいこと別の書き方もまとめておきます。

やりたいこと 書き方
None かどうか if x is None:
None でないか if x is not None:
空文字・空リストなどをまとめて「空」と扱う if not x:
None と空文字だけを「未入力」と扱う(0 は値あり) if x is None or x == "":
リストが空か(None は来ない前提) if not items:
None または空リスト if not items:(0 や False が来ない変数なら)
NaN かどうか math.isnan(x)/pd.isna(x)
None または NaN pd.isna(x)(pandas 利用時)

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Python None判定はis Noneで|空文字・空リスト・0との違い早見表」

Noneとは|「値がない」を表すただ1つのオブジェクト

None は NoneType 型のただ1つのインスタンスで、「値がない・未設定・該当なし」を表します。 プログラムのどこで None と書いても、同じ1つのオブジェクトを指します。

# n5.py(抜粋)
print(type(None), None is None)
print(type(None)() is None)

def f():
    pass

print(f(), f() is None)
print([1, 2].sort(), {"a": 1}.get("b"))
<class 'NoneType'> True
True
None True
None None

type(None)() で新しく作ろうとしても、返ってくるのは同じ None です。「1つしかない」からこそ、同一性を調べる is で判定できるわけです。

Noneが返ってくる代表的な場面

場面 例 結果
return のない関数 def f(): pass の f() None
リストをその場で並べ替えるメソッド [1, 2].sort() None
辞書にキーがない {"a": 1}.get("b") None
正規表現が一致しない re.match(r"\d+", "abc") None
print() の戻り値 x = print("a") None
JSON の null json.loads("null") None

Noneのまま使うと出るエラー

None と気づかずに操作したときのエラー文を、実際に出して確かめました。

操作 エラー文
None.upper() AttributeError: 'NoneType' object has no attribute 'upper'
None + 1 TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'
len(None) TypeError: object of type 'NoneType' has no len()
None[0] TypeError: 'NoneType' object is not subscriptable
for x in None: TypeError: 'NoneType' object is not iterable
sorted([3, None, 1]) TypeError: '<' not supported between instances of 'NoneType' and 'int'

エラー文に 'NoneType' と出てきたら、「どこかの変数が None になっている」という合図です。その変数に値を入れている関数の戻り値をさかのぼって確認し、is None の分岐を入れると解決します。

is Noneと== Noneの違い

2つの演算子は調べているものが違う

演算子 調べること 上書きできるか
x is None x と None が同じオブジェクトか(同一性) できない
x == None x と None が等しいとみなせるか(等価性)。x.__eq__(None) の結果 クラス側で自由に上書きできる

普通の値では両方とも同じ結果になります。違いが表に出るのは、== の意味を独自に決めている型を扱うときです。Python のコーディング規約 PEP 8 にも「Comparisons to singletons like None should always be done with is or is not, never the equality operators.(None のようなシングルトンとの比較は常に is か is not で行う)」と書かれています。

再現1:__eq__を上書きしたクラス

# n2.py
class Always:
    def __eq__(self, other):
        return True

a = Always()
print("a == None :", a == None)
print("a is None :", a is None)

class Money:
    def __init__(self, amount):
        self.amount = amount
    def __eq__(self, other):
        return self.amount == other.amount

m = Money(100)
print("m is None :", m is None)
try:
    print(m == None)
except AttributeError as e:
    print("AttributeError:", e)
a == None : True
a is None : False
m is None : False
AttributeError: 'NoneType' object has no attribute 'amount'

Always は None ではないのに == None が True になりました。Money は、__eq__ の中で相手の amount を読もうとして AttributeError になっています。is None はクラスの実装に左右されず、どちらも正しく False を返します。

再現2:NumPy配列

# n3.py(抜粋)
import numpy as np

arr = np.array([1, 2, 3])
print("arr == None :", arr == None)
print("arr is None :", arr is None)
try:
    if arr == None:
        print("None です")
except ValueError as e:
    print("ValueError:", e)

obj = np.array([1, None, 3], dtype=object)
print("obj == None :", obj == None)
arr == None : [False False False]
arr is None : False
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
obj == None : [False  True False]

NumPy 配列の == は要素ごとの比較で、結果は真偽値1つではなく配列です。それを if に渡すと「どの要素で判断するのか決められない」という ValueError になります。配列そのものが None かどうかは arr is None で調べます。

配列には not arr も使えません。空かどうかは size で調べます。

# n3.py(抜粋)
empty = np.array([])
if not empty: ...   # ValueError
if not arr: ...     # ValueError
ValueError The truth value of an empty array is ambiguous. Use `array.size > 0` to check that an array is not empty.
ValueError The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

「None または空の配列」を1行で扱う定番の形です。

# n11.py(抜粋)
import numpy as np

def total(arr=None):
    if arr is None or arr.size == 0:
        return 0
    return int(arr.sum())

print(total(), total(np.array([])), total(np.array([1, 2, 3])))
0 0 6

直す前と後

直す前 起きること 直した後
if x == None: __eq__ を持つ型で結果が変わる if x is None:
if x != None: 同上 if x is not None:
if not x is None: 動くが読みにくい if x is not None:
if arr == None:(NumPy) ValueError if arr is None:
if not arr:(NumPy) ValueError if arr is None or arr.size == 0:

静的チェックツールもこの書き方を見つけてくれます。次のファイルを pycodestyle 2.15.0 にかけた結果です。

# n9.py
x = None
if x == None:
    print("a")
if x != None:
    print("b")
if not x is None:
    print("c")
n9.py:2:6: E711 comparison to None should be 'if cond is None:'
n9.py:4:6: E711 comparison to None should be 'if cond is not None:'
n9.py:6:4: E714 test for object identity should be 'is not'

isを使うのはNone・True・Falseなどに限る

is が向いているのは、1つしか存在しないオブジェクトとの比較です。数値や文字列のリテラルに is を使うと、Python が警告を出します。

# n10.py
x = 0
print(x is 0, x == 0)
n10.py:2: SyntaxWarning: "is" with a literal. Did you mean "=="?
True True
比べる相手 使う演算子
None is / is not
数値、文字列、リストなどの「値」 == / !=
自作の番兵オブジェクト(後述の _MISSING) is / is not

if not xとis Noneの使い分け

if not xは「偽とみなされる値」すべてに反応する

if x: や if not x: は、bool(x) の結果で分岐します。偽(falsy)とみなされるのは、None・False・数値のゼロ・空のコンテナです。

分類 偽とみなされる値
定数 None、False
数値のゼロ 0、0.0、0j、Decimal(0)、Fraction(0, 1)
空のシーケンス・コレクション ""、[]、()、{}、set()、range(0)、b""
自作クラス __bool__ が False、または __len__ が 0 を返すもの

これ以外は真(truthy)です。早見表で確かめたとおり、" "(空白1つ)、"0"、[None]、"None"、float("nan") はすべて真になります。

0を「未指定」と取り違える例

# n6.py(抜粋)
def show(count=None):
    if not count:
        return "未指定"
    return f"{count}件"

print(show(0), show(None), show(3))

def show2(count=None):
    if count is None:
        return "未指定"
    return f"{count}件"

print(show2(0), show2(None), show2(3))
未指定 未指定 3件
0件 未指定 3件

if not count: では、正当な値である 0 まで「未指定」になりました。 is None に直すと 0件 と表示されます。PEP 8 も「if x is not None のつもりで if x と書かないよう注意する」と述べています。

orでデフォルト値を入れるときも同じ

# n8.py(抜粋)
cfg = {"timeout": 0, "retries": None}

print(cfg.get("timeout") or 30)      # 0 が 30 に置き換わる
t = cfg.get("timeout")
print(30 if t is None else t)        # 0 がそのまま残る
30
0

x or 既定値 は、x が 0 や空文字のときも既定値に置き換わります。 0 や空文字を有効な値として扱う変数では、既定値 if x is None else x と書きます。

どちらを使うかの判断表

変数に入りうる値 見分けたいこと 書き方
None か、オブジェクト 値があるか if x is None:
None か、数値(0 を含む) 未指定か if x is None:
None か、文字列(空文字を区別したい) 未設定か、空の入力か if x is None: と if x == "": を分ける
None か、文字列(空文字も未入力扱い) 入力があるか if not x:
リスト(None は来ない) 要素があるか if not items:
None か、リスト 処理する要素があるか if not items:(None と空を同じに扱ってよいとき)
真偽値か None(3状態) 未回答か if flag is None: を先に書く

空のシーケンスの判定について、PEP 8 は if not seq: / if seq: の形を勧めています(if len(seq): より短く読みやすいため)。

値の種類を言葉で返す関数

None・空文字・空のコンテナを区別して扱いたいときの完成形です。

# n11.py(抜粋)
def describe(x):
    if x is None:
        return "None(値がない)"
    if isinstance(x, str) and x.strip() == "":
        return "空文字・空白だけ"
    if isinstance(x, (list, tuple, dict, set)) and len(x) == 0:
        return "空のコンテナ"
    return f"値あり: {x!r}"

for v in [None, "", "  ", [], {}, 0, False, "0", [None]]:
    print(f"{v!r:8} -> {describe(v)}")
None     -> None(値がない)
''       -> 空文字・空白だけ
'  '     -> 空文字・空白だけ
[]       -> 空のコンテナ
{}       -> 空のコンテナ
0        -> 値あり: 0
False    -> 値あり: False
'0'      -> 値あり: '0'
[None]   -> 値あり: [None]

is None を最初に判定するのがポイントです。None に対して x.strip() や len(x) を呼ぶとエラーになるため、先に None を取り除いておきます。

NaNはNoneとは別物|判定はisnanで

NaN(Not a Number)は「数値として表せない結果」を表す浮動小数点数の特別な値で、型は float です。 None とは別のもので、判定方法も異なります。

# n5.py(抜粋)
import math

nan = float("nan")
print(nan == nan, nan is nan, nan != nan, math.isnan(nan), bool(nan), nan is None)
print(float("nan") in [float("nan")])
False True True True True False
False
性質 結果
nan == nan False(自分自身とも等しくない)
nan != nan True
bool(nan) True(not nan は False)
nan is None False
math.isnan(nan) True

== では見つけられず、if not x: でも素通りするので、NaN の判定には専用の関数を使います。

相手 判定方法
Python の float math.isnan(x)
NumPy のスカラー・配列 np.isnan(x)
pandas の値・Series・DataFrame pd.isna(x)(None も NaN も True)

None と NaN のどちらも「欠けている」と扱いたい場合の関数です。math.isnan() に文字列などを渡すと TypeError になるため、float かどうかを先に確かめています。

# n11.py(抜粋)
import math

def is_missing(v):
    return v is None or (isinstance(v, float) and math.isnan(v))

print([is_missing(v) for v in [None, float("nan"), 0, "", 1.5]])
[True, True, False, False, False]

pandasでのNone・NaN判定

pandas では、欠損値の判定は isna()/notna() に任せるのが基本です。is None や == None が期待どおりに働かない場面を、pandas 3.0.2 で確かめました。

数値の列ではNoneがNaNに変わる

# n4.py(抜粋)
import pandas as pd, numpy as np

s = pd.Series([1.0, None, np.nan, 4.0])
print(s)
print(s.isna().tolist())
print((s == None).tolist())
print([v is None for v in s])
0    1.0
1    NaN
2    NaN
3    4.0
dtype: float64
[False, True, True, False]
[False, False, False, False]
[False, False, False, False]

数値の Series に None を入れると、格納の時点で NaN に変換されます。 そのため == None も、要素を取り出しての is None も、すべて False でした。isna() だけが2件の欠損を見つけています。

整数だけのつもりで pd.Series([1, None, 3]) を作ると、型は float64、中身は [1.0, nan, 3.0] になります。整数のまま欠損を持たせたいときは dtype="Int64" を指定します(中身は [1, <NA>, 3]、isna() は [False, True, False])。

文字列の列・object型の列

# n4.py(抜粋)
o = pd.Series(["a", None, np.nan, ""])
print(o.dtype, o.isna().tolist(), [v is None for v in o])

ob = pd.Series(["a", None, np.nan, ""], dtype=object)
print(ob.tolist(), [v is None for v in ob], ob.isna().tolist())
str [False, True, True, False] [False, False, False, False]
['a', None, nan, ''] [False, True, False, False] [False, True, True, False]

pandas 3.0.2 では文字列の列の型が str になり、None は NaN として保持されました(is None はすべて False)。dtype=object を明示したときだけ None がそのまま残ります。列の型によって None の残り方が変わるので、isna() に統一しておくと型を気にせずに済みます。 なお、空文字 "" は欠損として扱われません。

pd.isnaが欠損とみなす値

値 pd.isna(値)
None True
np.nan / float("nan") True
pd.NA True
pd.NaT(日時の欠損) True
""(空文字) False
0 False

pd.NA は if pd.NA: のように真偽値として使うと TypeError: boolean value of NA is ambiguous になり、pd.NA == None や pd.NA is None はどちらも False でした。ここでも pd.isna() を使います。

DataFrameでよく使う操作

# n4.py(抜粋)
df = pd.DataFrame({"name": ["A", "B", None], "price": [100, None, 300]})

print(df.isna().sum())                 # 列ごとの欠損数
print(df["price"].fillna(0).tolist())  # 欠損を 0 で埋める
print(df.dropna())                     # 欠損のある行を除く
print(df[df["price"].isna()])          # price が欠損の行だけ
name     1
price    1
dtype: int64
[100.0, 0.0, 300.0]
  name  price
0    A  100.0
  name  price
1    B    NaN
やりたいこと 書き方
欠損かどうか(要素ごと) df.isna() / s.isna()
欠損でないか df.notna() / s.notna()
列ごとの欠損数 df.isna().sum()
欠損のある行を除く df.dropna()
欠損を値で埋める s.fillna(0)
欠損の行だけ取り出す df[df["price"].isna()]
1つの値が欠損か pd.isna(value)

行から取り出した値を判定するとき

row = df.iloc[1]
print(repr(row["price"]), row["price"] is None, pd.isna(row["price"]))
np.float64(nan) False True

取り出した値は None ではなく NaN なので、is None では見つかりません。pandas から取り出した値は pd.isna() で判定します。

JSON に書き出す前など、NaN を Python の None に戻したいときは次の形が使えます。

recs = df.astype(object).where(df.notna(), None).to_dict("records")
print(recs)
[{'name': 'A', 'price': 100.0}, {'name': 'B', 'price': None}, {'name': None, 'price': 300.0}]

型ヒントでNoneを表す|X | NoneとOptional

「None かもしれない値」は、型ヒントで X | None と書きます(Python 3.10 以降)。それより前から使える Optional[X] と同じ意味です。

# n8.py(抜粋)
from typing import Optional

print(Optional[str] == (str | None))
print(str | None)
print(Optional[str])
True
str | None
typing.Optional[str]
書き方 使える版 意味
str | None Python 3.10 以降 str または None
Optional[str] それ以前から(from typing import Optional) 同じ
Union[str, None] それ以前から 同じ

Optional は「引数を省略できる」という意味ではなく、「None が入りうる」という意味です。省略できるかどうかは、デフォルト値(= None)の有無で決まります。

型チェッカーがNoneの見落としを教えてくれる

# n7.py
def find_user(user_id: int) -> str | None:
    users = {1: "sato", 2: "suzuki"}
    return users.get(user_id)

name = find_user(3)
print(name.upper())

実行すると、該当者がいないため None に対して upper() を呼ぶことになります。

AttributeError: 'NoneType' object has no attribute 'upper'

同じファイルを mypy 2.3.1 にかけると、実行する前にこの箇所を指摘してくれます。

n7.py:11: error: Item "None" of "str | None" has no attribute "upper"  [union-attr]
Found 1 error in 1 file (checked 1 source file)

is Noneで分岐すると型が絞り込まれる

# n8.py(抜粋)
def find_user(user_id: int) -> str | None:
    return {1: "sato", 2: "suzuki"}.get(user_id)

name = find_user(3)
if name is None:
    print("見つかりませんでした")
else:
    print(name.upper())          # ここでは name は str と推論される

if (name := find_user(1)) is not None:
    print(name.upper())
見つかりませんでした
SATO

is None で分けたあとの else 側では、型チェッカーが「ここでは str」と判断するため、指摘は出なくなります。is None は実行時の安全と、型チェックの通過を同時に満たす書き方です。:=(代入式)を使うと、取得と判定を1行にまとめられます。

引数のデフォルトにNoneを使う定番コード

リストや辞書をデフォルト値にするとどうなるか

# n6.py(抜粋)
def add_bad(item, bucket=[]):
    bucket.append(item)
    return bucket

print(add_bad("a"))
print(add_bad("b"))
['a']
['a', 'b']

2回目の呼び出しに、1回目の "a" が残っています。デフォルト値は関数を定義したときに1度だけ作られ、呼び出しのたびに同じリストが使い回されるためです。

Noneを目印にして、関数の中で作る

# n6.py(抜粋)
def add_good(item, bucket=None):
    if bucket is None:
        bucket = []
    bucket.append(item)
    return bucket

print(add_good("a"))
print(add_good("b"))
['a']
['b']

「デフォルトは None、関数の先頭で if x is None: を見て新しく作る」が定番の形です。型ヒントを付けるなら bucket: list[str] | None = None と書きます。

bucket or [] と書くと変わること

# n6.py(抜粋)
def add_or(item, bucket=None):
    bucket = bucket or []
    bucket.append(item)
    return bucket

shared = []
add_or("x", shared)
print("shared:", shared)
add_good("x", shared)
print("shared:", shared)
shared: []
shared: ['x']

bucket or [] は、呼び出し側が渡した空リストも「偽」とみなして新しいリストに置き換えます。 そのため shared には何も追加されませんでした。渡されたリストに追記したい関数では is None で判定します。

「Noneを渡した」と「省略した」を区別する

None 自体に意味がある引数(「値を消す」など)では、専用の番兵オブジェクトをデフォルトにします。

# n6.py(抜粋)
_MISSING = object()

def update(name, nickname=_MISSING):
    if nickname is _MISSING:
        return f"{name}: ニックネームは変更しない"
    if nickname is None:
        return f"{name}: ニックネームを消す"
    return f"{name}: ニックネームを {nickname} にする"

print(update("sato"))
print(update("sato", None))
print(update("sato", "さとう"))
sato: ニックネームは変更しない
sato: ニックネームを消す
sato: ニックネームを さとう にする

object() で作った値は他のどの値とも同一にならないので、is で確実に見分けられます。

dataclassでの書き方

# n11.py(抜粋)
from dataclasses import dataclass, field

@dataclass
class Task:
    title: str
    due: str | None = None
    tags: list[str] = field(default_factory=list)

t = Task("掃除")
print(t, t.due is None)
Task(title='掃除', due=None, tags=[]) True

「未設定がありうる項目」は X | None = None、リストのように毎回新しく作りたい項目は field(default_factory=list) を使います。

リスト・辞書の中のNoneを扱うコード集

# n8.py(抜粋)
items = [3, None, 0, "", None, "a"]

print([x for x in items if x is not None])   # None だけ除く
print([x for x in items if x])               # 偽の値をすべて除く
print(list(filter(None, items)))             # 同上
print(items.count(None), None in items)
print(any(x is None for x in items), all(x is not None for x in items))
print(sorted([3, None, 1], key=lambda x: (x is None, x)))
[3, 0, '', 'a']
[3, 'a']
[3, 'a']
2 True
True False
[1, 3, None]
やりたいこと 書き方 注意点
None だけ取り除く [x for x in items if x is not None] 0 や空文字は残る
偽の値をまとめて取り除く [x for x in items if x] / filter(None, items) 0 や空文字も消える
None の個数 items.count(None)
None が含まれるか None in items / any(x is None for x in items)
None を最後に回して並べ替え sorted(items, key=lambda x: (x is None, x)) None 以外は互いに比較できる型にそろえる

辞書では、「キーがない」と「キーはあるが値が None」を分けて考えます。

# n11.py(抜粋)
d = {"a": None}
print("a" in d, d.get("a") is None, d.get("b") is None, "b" in d)
True True True False

d.get(key) is None はどちらの場合も True になります。キーの有無を知りたいときは key in d を使います。また、d.get("retries", "default") のように既定値を渡しても、キーが存在して値が None の場合は None が返ります(実行して確認しました)。

match 文でも None を直接書けます。

match value:
    case None:
        print("値がない")
    case _:
        print("値あり")

Noneと文字列の"None"を取り違えないために

# n5.py(抜粋)
print(str(None), repr(None), f"{None}", "None" == None, str(None) == "None")
None None None False True

str(None) や f-string に None を入れると、文字列の "None" になります。 画面やファイルに None と出ていても、それが None なのか文字列なのかは見た目では区別できません。確かめるときは repr(x) や type(x) を使います。

値 repr() is None bool()
None None True False
"None" 'None' False True
"null" 'null' False True

CSV やフォームから読んだ "None"、"null"、"" を None として扱いたい場合は、読み込みの入口で明示的に変換しておくと、その後の判定を is None に統一できます。

def to_none(text: str) -> str | None:
    return None if text.strip() in ("", "None", "null") else text

チェックリスト

  • [ ] None との比較は is None / is not None で書いた
  • [ ] 0 や空文字が有効な値になりうる変数に if not x: や x or 既定値 を使っていない
  • [ ] None かもしれない値は、len() やメソッド呼び出しの前に is None で分岐した
  • [ ] 戻り値が None になりうる関数に X | None の型ヒントを付けた
  • [ ] リスト・辞書のデフォルト引数は None にして関数内で作った
  • [ ] NaN の判定に == ではなく math.isnan() / pd.isna() を使った
  • [ ] NumPy 配列・pandas の値に == None や not x を使っていない

よくある質問

Q. is None と == None はどちらが速いですか? A. is はオブジェクトが同じかどうかを見るだけで、== は __eq__ の呼び出しを伴います。速度よりも大切なのは、is None ならクラスの __eq__ 実装に左右されず、常に正しい結果になる点です。

Q. if x: と if x is not None: はどう違いますか? A. if x: は None のほか、0・空文字・空リスト・False でも偽になります。if x is not None: は None のときだけ偽です。0 や空文字を「値がある」と扱いたい変数では後者を使います。

Q. 空文字と None はどう使い分けますか? A. 「まだ設定されていない・該当がない」は None、「入力されたが中身が空だった」は空文字、と分けると意味がはっきりします。区別する必要がない場合は、入口でどちらかに統一してから if not x: で判定すると簡潔です。

Q. pandas の DataFrame で None を探すには? A. df.isna() を使います。数値の列では None が NaN に変換されて格納されるため、== None や is None では見つかりません。isna() は None・NaN・pd.NA・pd.NaT をまとめて欠損として扱います。

まとめ

  • None の判定は x is None / x is not None。None はただ1つのオブジェクトなので同一性で調べる
  • == None は __eq__ 次第で結果が変わる。NumPy 配列では要素ごとの比較になり、if に渡すと ValueError
  • if not x: は None・空文字・空リスト・0・False をまとめて偽と扱う。0 や空文字が有効な値なら is None
  • NaN は None とは別物で、bool(nan) は True。判定は math.isnan() / pd.isna()
  • pandas の数値列では None が NaN に変わる。欠損の判定は isna() に統一する
  • 型ヒントは X | None。is None で分岐すると型チェッカーが型を絞り込む
  • 変更可能なデフォルト引数は None にして関数内で作る。None に意味があるときは番兵オブジェクトを使う

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Python None判定はis Noneで|空文字・空リスト・0との違い早見表」

株式会社RJCでは、PythonのNone判定のような基礎を仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?