Pythonで型確認を行う方法と実践的テクニック【type関数, isinstance関数】
- 作成日: 2023-06-16
- 更新日: 2023-12-25
- カテゴリ: Python
Pythonで型確認を行う
Pythonは動的型付けの言語で型が内蔵されています。
この型を確認するにはtype
関数やisinstance
関数を使います。
この記事ではPythonの型確認の方法を解説していきます。
関連記事
Djangoでオブジェクトを一括作成・更新【bulk_create, bulk_update】
DjangoのModel.objects.filter()の使い方【QuerySet】
Djangoのmodelのcreate()の使い方【Python】
Django入門: ルートの設定 ~ 簡単な一行掲示板アプリを作る その4【Windows10】
NumPyのappend()の使い方: 配列の末尾に要素を追加
Numpyのarangeの使い方: 指定範囲の数列を生成する
Python3でYoutube Data APIを使ってキーワード検索する
PythonからC言語(my.puts)を呼び出して実行する
type関数
type
関数は変数の型を取得するときに使われます。
print(type(1))
# <class 'int'>
print(type(1.2))
# <class 'float'>
print(type(True))
# <class 'bool'>
print(type([]))
# <class 'list'>
print(type({}))
# <class 'dict'>
type()
で取得したオブジェクトはtype
型のオブジェクトです。
t = type(1)
print(type(t))
# <class 'type'>
type関数で型の判定
type
関数の返す型を使って型判定することが可能です。
is
演算子と合わせて使います。
print(type(1) is int)
# True
print(type(True) is dict)
# False
自作関数などを作ってわかりやすくする方法もあります。
たとえばis_int()
関数の定義です。
def is_int(v):
return type(v) is int
print(is_int(1))
# True
複数の型と判定を取りたい場合はin
演算子と併用します。
print(type(1) in [int, bool])
# True
print(type(True) in [int, bool])
# True
print(type([]) in [int, bool])
# False
これを使うと例えばis_int_or_bool()
関数みたいな定義もできます。
def is_int_or_bool(v):
return type(v) in [int, bool]
print(is_int_or_bool(1))
# True
print(is_int_or_bool(True))
# True
print(is_int_or_bool([]))
# False
取得した型から値を生成
type
関数で取得した型から値を生成することも出来ます。
t = type(1)
print(t())
# 0
print(t(100))
# 100
これはたとえば自作クラスなどにも応用できます。
クラスの宣言が無くても値から型を取得すればその型のオブジェクトを作れるということです。
class Animal:
def __init__(self):
self.age = 20
an = Animal()
t = type(an)
print(t())
# <__main__.Animal object at 0x000001C9D59E70D0>
isinstance関数
isinstance
関数は2つの引数を取ります。
1つ目に判定したいオブジェクト、2つ目に判定したい型を指定します。
オブジェクトが指定した型であればTrue
を返し、違っていればFalse
を返します。
print(isinstance(1, int))
# True
print(isinstance(True, bool))
# True
複数の型と判定する
isinstance
関数の第2引数には複数の型を指定できます。
その場合はいずれかの型とマッチしていたらTrue
を返します。
print(isinstance(1, (int, bool)))
# True
print(isinstance(True, (int, bool)))
# True
print(isinstance([], (int, bool)))
# False
スーパークラスへのマッチ
またisinstance
関数はスーパークラスともマッチします。
たとえばbool
はint
のサブクラスなので以下のコードのような結果になります。
(issubclass()
は第1引数が第2引数のサブクラスかどうか判定する関数です)
print(isinstance(True, int))
# True
# boolはintのサブクラス
print(issubclass(bool, int))
# True
型確認を使った実践的テクニック
Pythonの型確認を使った実践的なテクニックを紹介します。
- 防御的プログラミング
- プロパティにおける型チェック
- typeによる依存関係の解消
防御的プログラミング
防御的プログラミングとは外部からの入力を念入りにチェックしてエラーなどを発生させる処理を言います。
Pythonでは動的型付けが採用されていますので関数の引数には型判定がありません。
ですので関数内で引数の型をチェックし、許容できない型の場合はエラーを発生させる、というのが防御的な手法になります。
たとえば以下のようにです。
def mul3(n: int):
if not isinstance(n, int):
raise TypeError('invalid type')
return n * 3
print(mul3(2))
# 6
print(mul3(True))
# 3
try:
print(mul3([]))
except TypeError as e:
print(e)
# invalid type
防御的プログラミングは開発コストが上がる特性がありますが、型チェックを行うためその分プログラムが堅牢になるというメリットがあります。
セキュアな処理が必要なプログラムなどでは導入してみる価値はあるかと思います。
プロパティにおける型チェック
クラスにはプロパティが定義できます。
プロパティを定義するとオブジェクトの属性への代入を監視できます。
この監視のさいにセッターに型チェックを入れておくとプログラムが堅牢になります。
class Animal:
def __init__(self):
self._age = 20
@property
def age(self):
return self._age
@age.setter
def age(self, age: int):
if type(age) is not int:
raise TypeError('invalid type')
self._age = age
an = Animal()
an.age = 30
print(an.age)
# 30
try:
an.age = []
except TypeError as e:
print(e)
# invalid type
仮にセッターでage
にリストなどを指定しても型チェックでエラーになるのでバグが早期発見可能になります。
typeによる依存関係の解消
例えば以下のようなプロジェクトを考えます。
# animal.py
class Animal:
def __init__(self):
self._age = 20
# sub.py
def hello(animal):
Animal = type(animal)
an = Animal()
print(an)
# <animal.Animal object at 0x000001EFF731B910>
# main.py
import animal
import sub
an = animal.Animal()
sub.hello(an)
sub.py
ではAnimal
を参照してますがimport
等は使っていません。
しかしAnimal
クラスからオブジェクトは生成できています。
これはmain.py
でAnimal
のオブジェクトをsub.py
に注入し、sub.py
ではtype()
を使ってAnimal
型を参照しているからです。
このようにtype()
を使うと実行時にオブジェクトからクラス(型)をインポートできます。
モジュールが循環参照などしている場合は解決策の1つとして使えるかもしれません。
おわりに
今回はPythonの型確認の方法について解説しました。
なにか参考になれば幸いです。
🦝 < 型チェック!
🦝 < Pythonにも型はあったんや