Documentation Python

概要

この記事では、Pythonでリストが空かどうかを確認する方法を解説します。データ処理やAPI応答の検証など、リストが空かどうかをチェックする場面は頻繁にあります。Pythonでは複数の方法がありますが、最もPythonic(Pythonらしい)なアプローチを理解することで、より読みやすく効率的なコードを書くことができます。

方法の比較

方法コード例推奨度備考
暗黙的ブール評価if not a:PEP 8推奨
len()を使用if len(a) == 0:冗長
空リストと比較if a == []:新しいリストを生成
is演算子if a is []:×常にFalse(非推奨)

推奨: 暗黙的ブール評価(if not)

Pythonでは空のシーケンス(リスト、文字列、タプルなど)はFalseと評価される「真偽値テスト」という仕組みがあります。

a = []

if not a:
    print("リストは空です")
else:
    print("リストには要素があります")

真偽値の評価ルール

# False と評価されるもの
bool([])        # False - 空リスト
bool('')        # False - 空文字列
bool(())        # False - 空タプル
bool({})        # False - 空辞書
bool(set())     # False - 空セット
bool(0)         # False - ゼロ
bool(None)      # False - None

# True と評価されるもの
bool([1, 2, 3]) # True - 要素のあるリスト
bool('hello')   # True - 文字列
bool([0])       # True - 0を含むリストも True
bool([None])    # True - Noneを含むリストも True

len()を使ったチェック

len()を使ってリストの長さを比較する方法もあります。

a = []

if len(a) == 0:
    print("リストは空です")

この方法も正しく動作しますが、PEP 8では推奨されていません。

いつlen()を使うべきか

特定の長さを確認したい場合はlen()が適切です。

items = [1, 2, 3]

# 空かどうかを確認(if not が推奨)
if not items:
    print("空です")

# 特定の長さを確認(len() が適切)
if len(items) >= 3:
    print("3個以上の要素があります")

# 要素数が1つかどうか(len() が適切)
if len(items) == 1:
    print("要素が1つだけです")

Noneと空リストの違い

Noneと空リスト[]は異なります。両方を考慮する必要がある場合は注意が必要です。

def process_items(items):
    # items が None の場合もチェック
    if items is None:
        print("リストが渡されていません")
        return

    if not items:
        print("リストは空です")
        return

    print(f"{len(items)}個の要素を処理します")

# 使用例
process_items(None)   # リストが渡されていません
process_items([])     # リストは空です
process_items([1, 2]) # 2個の要素を処理します

Noneと空リストを同時にチェック

def get_first_item(items):
    """最初の要素を取得(None/空の場合はNoneを返す)"""
    if not items:  # None も [] も False と評価される
        return None
    return items[0]

# 使用例
print(get_first_item(None))    # None
print(get_first_item([]))      # None
print(get_first_item([1, 2]))  # 1

型ヒントを使った実装

Python 3.9以降の型ヒントを使った例です。

from typing import Optional

def safe_first(items: list | None) -> Optional[any]:
    """安全に最初の要素を取得する"""
    if not items:
        return None
    return items[0]

def filter_empty_lists(lists: list[list]) -> list[list]:
    """空でないリストのみを抽出する"""
    return [lst for lst in lists if lst]

# 使用例
data = [[1, 2], [], [3], [], [4, 5]]
result = filter_empty_lists(data)
print(result)  # [[1, 2], [3], [4, 5]]

実践例

APIレスポンスの検証

import json

def handle_api_response(response_text: str) -> list:
    """APIレスポンスを処理する"""
    try:
        data = json.loads(response_text)
        items = data.get('items', [])

        if not items:
            print("データがありません")
            return []

        print(f"{len(items)}件のデータを取得しました")
        return items

    except json.JSONDecodeError:
        print("JSONの解析に失敗しました")
        return []

# 使用例
response = '{"items": []}'
result = handle_api_response(response)  # データがありません

データ処理パイプライン

def process_pipeline(data: list) -> list:
    """データ処理パイプライン"""
    if not data:
        print("処理するデータがありません")
        return []

    # フィルタリング
    filtered = [x for x in data if x > 0]

    if not filtered:
        print("条件に合うデータがありません")
        return []

    # 変換処理
    transformed = [x * 2 for x in filtered]

    return transformed

# 使用例
result = process_pipeline([-1, 0, 1, 2, 3])
print(result)  # [2, 4, 6]

result = process_pipeline([-1, -2, 0])
# 条件に合うデータがありません
print(result)  # []

デフォルト値の設定

def get_config(user_settings: list | None = None) -> list:
    """設定を取得(デフォルト値付き)"""
    default_settings = ['option1', 'option2']

    # None または空リストの場合はデフォルトを使用
    if not user_settings:
        return default_settings

    return user_settings

# 使用例
print(get_config())          # ['option1', 'option2']
print(get_config([]))        # ['option1', 'option2']
print(get_config(['custom'])) # ['custom']

よくある間違い

is演算子の誤用

a = []

# NG: 常に False になる
if a is []:  # 異なるオブジェクトなので False
    print("空です")

# OK: 値の比較
if a == []:
    print("空です")

# 最も推奨
if not a:
    print("空です")

明示的なTrueとの比較

a = [1, 2, 3]

# NG: 冗長
if bool(a) == True:
    print("要素があります")

# NG: 冗長
if (len(a) > 0) == True:
    print("要素があります")

# OK: シンプル
if a:
    print("要素があります")

Pythonicなコードとは?

Pythonicという言葉は、Pythonの文化やコーディングスタイルに従った書き方を意味します。PEP 8(Pythonスタイルガイド)では、シーケンスの空判定について以下のように述べています。

シーケンス(文字列、リスト、タプル)の場合、空のシーケンスがFalseであることを利用してください。

# 推奨
if not seq:
    pass

if seq:
    pass

# 非推奨
if len(seq):
    pass

if not len(seq):
    pass

まとめ

状況推奨コード
リストが空か確認if not items:
リストに要素があるか確認if items:
Noneも考慮した空チェックif not items: (両方Falseになる)
特定の長さを確認if len(items) == n:

リストが空かどうかを確認する最もPythonicな方法は、if notを使用することです。この方法はシンプルで効率的であり、PEP 8でも推奨されています。len()を使う方法は特定の長さを確認する場合に限定し、空判定には使わないようにしましょう。

参考文献

円