Skip to content

Python 3.9 で | 演算子が使えないエラーの解決方法

問題の説明

Python 3.9 でデータクラスを定義する際、str | None のような型ヒントを使用すると、次のエラーが発生します:

TypeError: unsupported operand type(s) for |: 'type' and 'NoneType'

この問題が発生する典型的なコード例は以下の通りです:

python
from dataclasses import dataclass

@dataclass
class InventoryItem:
    name: str | None = None
    unit_price: float
    quantity_on_hand: int = 0

Python 3.9 の制限事項

根本原因| 演算子を使ったユニオン型の記法(TypeA | TypeB | TypeC)は Python 3.10 で導入された機能です。Python 3.9 ではサポートされていません。

解決策

Python 3.9 では typing.Optional または typing.Union を使用します:

方法1:Optional を使用する(推奨)

None を持ちうる型("None許容型")には Optional が最適です:

python
from dataclasses import dataclass
from typing import Optional  # 追加インポート

@dataclass
class InventoryItem:
    name: Optional[str] = None  # Optionalで明示的に宣言
    unit_price: float
    quantity_on_hand: int = 0

方法2:Union を使用する(複合型の場合)

複数の型の組み合わせ(str | int | None)が必要な場合は Union を使用します:

python
from dataclasses import dataclass
from typing import Union  # 追加インポート

@dataclass
class Item:
    name: Union[str, int, None] = None  # 複数の型を許容
    unit_price: float
    stock: int = 0

命名規則のベストプラクティス

OptionalUnion の使い分け:

  • Optional[Type]Type または None (特にデフォルト値がNoneのフィールド向け)
  • Union[Type1, Type2] = 2種類以上の型を受け入れる場合(Noneを含む複合型も可)

解決策の技術的背景

型ヒントの互換性問題

Pythonの型ヒント記法はバージョンごとに進化しています:

バージョンユニオン型の記法備考
Python 3.9Union[Type1, Type2]`
Python 3.10+`Type1Type2`

バージョン間互換性が必要な場合

  • 複数バージョン対応が必要なら typing モジュールを常に使う
  • Python 3.10+専用なら | 演算子の方が簡潔

OptionalとUnionの関係性

実は Optional[str] は公式に Union[str, None] のエイリアスとして定義されています:

python
# typing.pyの内部実装(概念)
Optional = Union[TypeVar('T'), NoneType]

ただし、可読性と意図の明確化のため、None を許容する場合は Optional の使用が推奨されます。

移行ガイド(Python 3.10以降ユーザーへ)

将来的に3.10+に移行予定の場合のアドバイスです:

  1. 現在の3.9環境ではOptional/Unionを使う
  2. 移行後はコードのリファクタリングが可能
    python
    # Python 3.10+ での推奨記法
    class NewItem:
        name: str | None = None
        price: float
  3. 両対応する場合は __future__ を活用
    python
    from __future__ import annotations  # トップに追加
    
    class CompatibleItem:
        name: str | None  # 3.9でもエラーにならない

Pythonの進化と型ヒント

Python 3.10で導入された | 演算子記法は、型ヒントをより直感的にするための重要な進化です。プロジェクトのPythonバージョンに合わせて適切な記法を選択しましょう。