閉じる

PythonのNoneとは?意味と使い方: 基本と注意点を解説

PythonのNoneは、プログラムの中で「ここにはまだ値がない」「結果が見つからなかった」という状態をはっきり示すための特別な値です。

未初期化の印として使ったり、関数の戻り値に使って処理の分岐を明確にしたりと、初心者でも早い段階から出会います。

この記事では、Noneの基本から判定方法、つまずきやすいエラー回避までを実行例とともに解説します。

PythonのNoneとは 何もない値の基本

Noneの意味

直感的な説明

Noneは「何もない」「未設定」を表す特別なオブジェクトです。

ゼロや空文字のように「具体的な値があるけれど空っぽ」という意味ではなく、「値そのものが存在しない」という意味になります。

例(未設定を示す)

Python
# 変数をまだ決められないときにNoneを入れておく
user = None  # ログイン済みならユーザー情報が入る想定

print(user)          # 何も決まっていない
print(user is None)  # Noneかどうかの判定
実行結果
None
True

型はNoneTypeで唯一の値

NoneTypeとは

Noneの型はNoneTypeです。

NoneTypeのインスタンスはNoneただ1つしか存在しません。

つまりNoneは唯一無二のシングルトンです。

例(唯一性の確認)

Python
# Noneの型名は"NoneType"
print(type(None).__name__)

# Noneは唯一のオブジェクトなので、isで同一性比較してもTrue
a = None
b = None
print(a is b)      # 同じ唯一のNoneを指している
print(a == b)      # 等価比較でもTrueだが、Noneにはisを使うのが慣例
実行結果
NoneType
True
True

Noneは偽になる

真偽値コンテキスト

if文やbool()に渡すと、Noneは偽(False)として扱われます。

存在チェックや条件分岐で便利ですが、他の偽と区別したい場面ではis Noneで明確に判定しましょう。

例(条件分岐)

Python
x = None

print(bool(x))  # Falseとして扱われる

if x:
    print("真です")
else:
    print("偽です(Noneは偽)")
実行結果
False
偽です(Noneは偽)

0や空とNoneの違い

意味の違い

0や空文字""、空リスト[]は「値はあるが中身が空」という意味です。

一方、Noneは「値そのものがない」です。

使い分けることで、状態の意図がコードから読み取りやすくなります。

代表的な値の比較表

意味真偽値(bool(…))Noneかどうか
NoneNoneType値が存在しないFalseTrue
0int数量がゼロFalseFalse
“”str文字数がゼロFalseFalse
[]list要素数がゼロFalseFalse
Falsebool偽という値FalseFalse

例(判定の違い)

Python
values = [None, 0, "", [], False, "text", [1]]
for v in values:
    print(
        f"value={repr(v):>6}, "
        f"type={type(v).__name__:>8}, "
        f"bool={bool(v)!s:>5}, "
        f"is None={v is None}"
    )
実行結果
value=  None, type= NoneType, bool=False, is None=True
value=     0, type=     int, bool=False, is None=False
value=    '', type=     str, bool=False, is None=False
value=    [], type=    list, bool=False, is None=False
value= False, type=    bool, bool=False, is None=False
value='text', type=     str, bool=True, is None=False
value=  [1], type=    list, bool=True, is None=False

Noneの使い方 基本パターン

未初期化の値にNone

説明

まだ値が決められないが、変数自体は用意しておきたいときにNoneを入れておきます。

後で実際の値が入ったかどうかをis Noneで簡単に判定できます。

例(ログイン前後の状態)

Python
current_user = None  # まだログインしていない

if current_user is None:
    print("ログインしていません")

# ログインが完了してユーザー名が入る
current_user = "alice"

if current_user is not None:
    print(f"ログイン中のユーザー: {current_user}")
実行結果
ログインしていません
ログイン中のユーザー: alice

戻り値がない関数はNone

説明

returnがない、またはreturnに値を指定しない関数は自動的にNoneを返します。

戻り値を使う処理では、Noneになる可能性を意識しましょう。

例(printするだけの関数)

Python
def greet(name):
    # 返り値を明示しない(=Noneが返る)
    print(f"Hello, {name}!")

ret = greet("Bob")
print("返り値:", ret)
print("ret is None:", ret is None)
実行結果
Hello, Bob!
返り値: None
ret is None: True

見つからないときの返り値にNone

説明

検索や取得処理で「該当なし」を表すのにNoneを返すのは定番です。

呼び出し側はis Noneで見つからなかったケースを分岐できます。

例(最初に見つかった偶数の位置を返す)

Python
# 見つかればインデックス(int)、なければNoneを返す
def find_first_even(nums):
    for i, n in enumerate(nums):
        if n % 2 == 0:
            return i
    return None  # 見つからなかった

print(find_first_even([1, 3, 5]))      # None
print(find_first_even([1, 3, 6, 7]))   # 2

idx = find_first_even([1, 3, 5])
if idx is None:
    print("偶数は見つかりませんでした")
else:
    print(f"最初の偶数の位置: {idx}")
実行結果
None
2
偶数は見つかりませんでした

デフォルト引数はNoneで遅延初期化

典型パターン

ミュータブル(書き換え可能)なオブジェクトをデフォルト引数に直接置くと、関数呼び出し間で「共有」される落とし穴があります。

Noneを置いて、関数内で新規作成する「遅延初期化」が安全です。

悪い例(リストが共有されてしまう)

Python
# 悪い例: デフォルトのリストは関数定義時に1度だけ作られ、呼び出し間で共有される
def append_item_bad(item, bucket=[]):
    bucket.append(item)
    return bucket

print(append_item_bad("A"))  # 期待: ["A"]
print(append_item_bad("B"))  # 期待: ["B"] だが実際は["A", "B"]に溜まる
実行結果
['A']
['A', 'B']

良い例(Noneで遅延初期化)

Python
# 良い例: Noneをデフォルトにして、必要なときに新規作成する
def append_item_good(item, bucket=None):
    if bucket is None:
        bucket = []  # 呼び出しごとに新しいリスト
    bucket.append(item)
    return bucket

print(append_item_good("A"))          # ["A"]
print(append_item_good("B"))          # ["B"]
print(append_item_good("C", ["X"]))   # 既存のリストを渡すこともできる
実行結果
['A']
['B']
['X', 'C']

Noneの判定と比較 isを使うのが基本

None比較はisを使う

isと==の違い

isは「同一のオブジェクトか」を調べ、==は「等しいか」を調べます。

==はクラスによって振る舞いが上書きされ得るため、Noneの判定は常にis(またはis not)を使うのが安全です。

例(==が誤解を招くケース)

Python
class AlwaysEqual:
    # どんな相手とも等しいと答える、極端な実装
    def __eq__(self, other):
        return True

obj = AlwaysEqual()

print(obj == None)   # Trueになってしまう(等価演算子が上書きされているため)
print(obj is None)   # False(同一オブジェクトではない)
実行結果
True
False

if x is None と if not x の違い

説明

if not x0""[]Falseなど「空や偽の値」もまとめて偽と見なします。

Noneだけを区別したいときはif x is Noneを使います。

例(混同しないための比較)

Python
tests = [None, 0, "", [], False, 1]
for x in tests:
    print(
        f"x={repr(x):>4}, not x -> {not x}, x is None -> {x is None}"
    )
実行結果
x=None, not x -> True, x is None -> True
x=   0, not x -> True, x is None -> False
x=  '', not x -> True, x is None -> False
x=  [], not x -> True, x is None -> False
x=False, not x -> True, x is None -> False
x=   1, not x -> False, x is None -> False

Noneを返す関数の扱い

型ヒントで明示する

int | None(Python 3.10以降)やOptional[int](typing)のように、戻り値がNoneになる可能性を型で示すと、呼び出し側でのチェック漏れを減らせます。

例(パースに失敗したらNone)

Python
# 文字列が整数ならint、失敗したらNoneを返す
def parse_int(s: str) -> int | None:
    try:
        return int(s)
    except ValueError:
        return None

for text in ["42", "forty two"]:
    n = parse_int(text)
    if n is None:
        print(f"{text!r} は整数に変換できません")
    else:
        print(f"{text!r} -> {n} (n+1={n+1})")
実行結果
'42' -> 42 (n+1=43)
'forty two' は整数に変換できません

Noneの注意点とよくあるエラー

Noneにメソッドを呼んで失敗

エラーの例と対策

Noneはメソッドを持ちません。

None.upper()のような呼び出しはAttributeErrorになります。

値がNoneの可能性があるなら、先にガードしましょう。

Python
s = None

# そのまま呼ぶとエラーになるが、ここでは例外を捕捉して表示
try:
    print(s.upper())
except Exception as e:
    print(type(e).__name__, ":", e)

# 安全な呼び方の一例
def safe_upper(text: str | None) -> str:
    if text is None:
        return ""  # 仕様に合わせて空文字などを返す
    return text.upper()

print("安全な結果:", safe_upper(s))
print("安全な結果:", safe_upper("hello"))
実行結果
AttributeError : 'NoneType' object has no attribute 'upper'
安全な結果: 
安全な結果: HELLO

Noneとの演算でTypeError

エラーの例と対策

None + 1のような演算は定義されておらずTypeErrorになります。

演算前にNoneかどうかを確認し、置き換えるか分岐しましょう。

Python
x = None

try:
    print(x + 1)
except TypeError as e:
    print(type(e).__name__, ":", e)

# ガードしてから使う
x = 0 if x is None else x
print("計算結果:", x + 1)
実行結果
TypeError : unsupported operand type(s) for +: 'NoneType' and 'int'
計算結果: 1

早期returnでNoneが混ざる

説明

関数の分岐のどこかでreturnを書き忘れて、暗黙にNoneが返ることがあります。

呼び出し元で数値計算に使ってTypeError……というのはよくあるミスです。

すべての分岐で戻り値の型を揃えましょう。

例(バグのある実装と修正版)

Python
# バグのある実装: 負値のときに値を返していない(=None)
def discounted_price(price: float) -> float | None:
    if price < 0:
        return  # Noneが返る
    if price > 100:
        return price * 0.9
    return price

# 問題の再現
p = discounted_price(-5)
print("戻り値:", p)
try:
    print("合計:", p + 10)  # TypeError
except TypeError as e:
    print(type(e).__name__, ":", e)

# 修正版: すべての経路でfloatを返す
def discounted_price_fixed(price: float) -> float:
    if price < 0:
        return 0.0  # 仕様として0に丸めるなど、一貫した型を返す
    if price > 100:
        return price * 0.9
    return price

p2 = discounted_price_fixed(-5)
print("修正版の合計:", p2 + 10)
実行結果
戻り値: None
TypeError : unsupported operand type(s) for +: 'NoneType' and 'int'
修正版の合計: 10.0

まとめ

Noneは「値が存在しない」状態を表す唯一のオブジェクト(NoneType)で、真偽値コンテキストでは偽として扱われます。

0や空文字と混同せず、意味の違いを意識することが読みやすいコードにつながります。

判定は==ではなくis(またはis not)を使い、if not xではなくif x is Noneで明確に分岐しましょう。

典型パターンとしては、未初期化の印、見つからないときの返り値、そしてデフォルト引数の遅延初期化が挙げられます。

よくあるエラー(メソッド呼び出しや演算での例外、早期returnでのNone混入)は、事前のガードと一貫した戻り値設計、そして型ヒントの活用で防げます。

まずは本記事のサンプルを写経し、Noneを安全に扱う感覚を身につけてください。

この記事を書いた人
エーテリア編集部
エーテリア編集部

人気のPythonを初めて学ぶ方向けに、文法の基本から小さな自動化まで、実際に手を動かして理解できる記事を書いています。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!