本記事では、Pythonでオブジェクトの型を判定する方法を解説します。Pythonでは変数の型を確認する場面が多くあります。例えば、関数に渡された引数が期待する型かどうかを確認したり、異なる型に対して異なる処理を行ったりする場合です。型を判定する主な方法はisinstance()とtype()の2つあり、これらについて詳しく説明します。
isinstance()
isinstance()関数は、オブジェクトが指定したクラスのインスタンスであるか、またはそのサブクラスのインスタンスであるかを判定します。継承関係を考慮した型チェックを行いたい場合に適しています。
構文
isinstance(object, classinfo)
object
: 型を判定したいオブジェクトclassinfo
: クラスまたはクラスのタプル
戻り値は、objectがclassinfoのインスタンスまたはサブクラスのインスタンスであればTrue、そうでなければFalseです。
例
以下に、isinstance()関数の使用例を示します。
# 基本的な使い方
x = 10
print(isinstance(x, int)) # True
print(isinstance(x, float)) # False
print(isinstance(x, (int, float))) # True(タプルで複数の型を指定)
# 継承関係の確認
class Parent:
pass
class Child(Parent):
pass
obj = Child()
print(isinstance(obj, Child)) # True
print(isinstance(obj, Parent)) # True(継承関係を認識)
# 組み込み型の階層関係
my_list = [1, 2, 3]
print(isinstance(my_list, list)) # True
print(isinstance(my_list, object)) # True(すべてのオブジェクトはobjectのインスタンス)
type()
type()関数は、オブジェクトの正確な型(クラス)を返します。継承関係を考慮せず、オブジェクトの直接の型のみを判定します。
構文
type(object)
object
: 型を取得したいオブジェクト
戻り値は、objectの型(クラス)です。
また、type()は型を比較する目的でも使用できます。
type(object) is class
例
以下に、type()関数の使用例を示します。
# 基本的な使い方
x = 10
print(type(x)) # <class 'int'>
print(type(x) is int) # True
print(type(x) is float) # False
# 継承関係の確認
class Parent:
pass
class Child(Parent):
pass
obj = Child()
print(type(obj)) # <class '__main__.Child'>
print(type(obj) is Child) # True
print(type(obj) is Parent) # False(継承関係を考慮しない)
# 様々な型の確認
print(type([1, 2, 3])) # <class 'list'>
print(type({"name": "Alice"})) # <class 'dict'>
print(type(lambda x: x*2)) # <class 'function'>
isinstance() と type() の違い
isinstance()とtype()の主な違いを表形式でまとめます。
特性 | isinstance() | type() |
---|---|---|
継承関係 | 考慮する | 考慮しない |
戻り値 | ブール値(TrueまたはFalse) | クラスオブジェクト |
複数型の判定 | タプルで複数の型を指定可能 | 直接比較では1つの型のみ |
使用目的 | 型の互換性チェック | 正確な型の取得・比較 |
抽象基底クラス | 対応している | 対応していない |
パフォーマンス | やや遅い(継承チェックのため) | やや速い |
どちらを使うべきか
Pythonの公式ドキュメントでは、オブジェクトの型をテストするためにはisinstance()関数を使用することが推奨されています。(参照)
これには以下のような理由があります:
- 継承関係を考慮する: isinstance()は継承関係を考慮するため、オブジェクト指向プログラミングの原則に沿っています。
- ダックタイピングの原則: Pythonは「もしそれがアヒルのように歩き、アヒルのように鳴くなら、それはアヒルである」という原則に基づいています。isinstance()は抽象基底クラスとの互換性チェックをサポートしており、この原則に適しています。
- 柔軟性: isinstance()はタプルで複数の型を指定できるため、より柔軟な型チェックが可能です。
isinstance()を使うべき一般的な場合:
- 継承関係を考慮した型チェックが必要な場合
- 「このオブジェクトはリストとして扱えるか」など、互換性を確認したい場合
- 複数の型のいずれかであるかを確認したい場合
- 抽象基底クラス(collections.abc等)との互換性を確認したい場合
# 数値型かどうかを確認(intもfloatも数値として扱う)
def process_number(num):
if isinstance(num, (int, float)):
return num * 2
else:
raise TypeError("数値を入力してください")
type()が適している特定のケース:
- オブジェクトの正確な型を知りたい場合(型の表示や診断目的)
- 継承関係を無視して、厳密に特定の型かどうかを確認する必要がある特殊なケース
- メタプログラミングで新しい型を作成する場合
# 型に応じて異なる処理を行う(特殊なケース)
def describe_type(obj):
if type(obj) is int:
return "整数です"
elif type(obj) is float:
return "浮動小数点数です"
elif type(obj) is str:
return "文字列です"
else:
return "その他の型です"
ただし、上記のコードは以下のようにisinstance()を使って書き直すことが推奨されます:
# isinstance()を使った推奨される書き方
def describe_type_better(obj):
if isinstance(obj, int):
return "整数です"
elif isinstance(obj, float):
return "浮動小数点数です"
elif isinstance(obj, str):
return "文字列です"
else:
return "その他の型です"
まとめ
Pythonでオブジェクトの型を判定するには、主にisinstance()とtype()の2つの方法があります。
- isinstance(object, classinfo) は継承関係を考慮して型チェックを行い、オブジェクトが指定した型またはそのサブクラスのインスタンスであればTrueを返します。
- type(object) はオブジェクトの正確な型(クラス)を返し、継承関係は考慮しません。
一般的には、型チェックを行う場合はisinstance()を使用することが推奨されています。これは、Pythonのダックタイピングの原則に沿っており、「オブジェクトが特定の振る舞いをするかどうか」を確認するのに適しているためです。
ただし、オブジェクトの正確な型を知りたい場合や、継承関係を無視して厳密に型をチェックしたい場合はtype()が適しています。
どちらの関数も状況に応じて適切に使い分けることで、より堅牢なPythonプログラムを作成することができます。