概要(type は「その値が何者か」を一瞬で教えてくれる基本関数)
type は、オブジェクト(数値、文字列、リスト、関数、クラスのインスタンスなど)の「型(クラス)」を返す組み込み関数です。Python は動的型付けなので、コードを書いている途中で「この値は今、何の型なの?」を確認する場面がよくあります。type を使うとデバッグも分岐も一気にクリアになります。
print(type(10)) # <class 'int'>
print(type(3.14)) # <class 'float'>
print(type("hello")) # <class 'str'>
print(type([1, 2, 3])) # <class 'list'>
Python基本の使い方(ここが重要)
1引数の type(obj) は「その場の正確な型」を返す
type にオブジェクトを渡すと、その“正確な(実体の)型”を返します。返ってくるものは「型オブジェクト」なので、表示すると <class ‘…’> という形になります。
def greet(): pass
class User: pass
u = User()
print(type(greet)) # <class 'function'>
print(type(u)) # <class '__main__.User'>
Python条件分岐やデバッグでの即効性
「この値、文字列なら前後をトリムしたい」「辞書ならキー一覧を出したい」など、分岐前に type を見て判断ができます。ログに型情報を残すのも有効です。
def normalize(x):
print("DEBUG:", type(x))
if type(x) is str:
return x.strip()
return x
Pythonisinstance との使い分け(重要ポイントの深掘り)
厳密判定が欲しいなら type、継承を含めた判定なら isinstance
type は“実体がその型そのものか”を厳密に見ます。isinstance は“その型、またはそのサブクラスか”を含めて判定します。継承関係を考慮する場面(抽象型、インターフェース的な使い方)では isinstance が実務的に正解です。
class Animal: pass
class Dog(Animal): pass
d = Dog()
print(type(d) is Animal) # False(実体は Dog)
print(isinstance(d, Animal)) # True(Animalのサブクラス)
Python典型的な落とし穴(bool は int のサブクラス)
Python の bool は int のサブクラスです。type(x) == int では True/False を取りこぼします。数値全般を受けたいなら isinstance(x, (int, float)) のように複数型を許容しましょう。
print(type(True) is int) # False(厳密には bool)
print(isinstance(True, int)) # True(継承を考慮)
Python実務での活用(デバッグ・分岐・ロギング・入力検証)
デバッグの初動として「値と型」を並べて見る
入力や中間値が想定と違うとき、型情報を一緒に出すと原因特定が速くなります。
def parse_amount(x):
print(f"value={x!r}, type={type(x)}")
if isinstance(x, str) and x.isdigit():
return int(x)
if isinstance(x, (int, float)):
return int(x)
raise TypeError("数値または数字文字列を渡してください")
Python安全な分岐とフォールバック
type で厳密判定、isinstance で広め判定。状況に応じた線引きを持つと、意図が明確なコードになります。
def total(v):
if isinstance(v, dict):
return sum(v.values())
if isinstance(v, (list, tuple, set)):
return sum(v)
raise TypeError("合計の出し方が定義されていない型です")
Python応用:type の三引数で「動的にクラスを作る」(概念だけ触る)
type は「type(name, bases, dict)」という三引数で“新しいクラス”を作る機能も持っています。メタプログラミング寄りで初心者向けではありませんが、仕組みを知っておくと世界が広がります。
# name='Point'、bases=(object,)、属性dict={'move': ...} のクラスを生成
Point = type("Point", (object,), {"move": lambda self, dx, dy: (dx, dy)})
p = Point()
print(p.move(3, 4)) # (3, 4)
Python「型そのものもオブジェクト」である、という Python の柔軟さを象徴する機能です。実務では通常の class 構文を使えば十分です。
つまずきやすい点と安全策
type(x) == ではなく「is」を使う(同一性で比較)
type が返すのは“型オブジェクト”なので、同一性比較の is が適切です。とはいえ、継承を考慮しない厳密判定が必要か、常に自問しましょう。
if type(x) is str:
...
Pythonライブラリの独自型(例:numpy 配列など)は isinstance が無難
外部ライブラリの型は独自クラスが多いので、「配列っぽいもの」全体を受けたいときは抽象基底クラスやタプルで複数許容するのが現実的です。
from collections.abc import Sequence
def head(xs):
if not isinstance(xs, Sequence):
raise TypeError("シーケンスを渡してください")
return xs[0] if xs else None
Python値の変換の前に「型を確認」する癖を持つ
特にユーザー入力や外部データでは、型を決め打ちすると事故ります。最初に type/isinstance で受け入れ可能範囲を絞るだけで、バグの再発率が劇的に下がります。
例題で身につける(定番から一歩先まで)
例題1:型に応じて処理を切り替える正統派
def to_str(x):
if isinstance(x, str):
return x
if isinstance(x, (int, float, bool)):
return str(x)
raise TypeError("文字列へ変換できる想定外の型です")
print(to_str(10), to_str(True), to_str("ok"))
Python例題2:デバッグプリントに型も載せる
def debug_val(x, label="val"):
print(f"{label}={x!r} ({type(x)})")
debug_val({"a": 1}, "payload")
Python例題3:厳密な型ガードと広い許容の両立
def square(x):
if type(x) is bool: # 厳密に除外
raise TypeError("bool は数値扱いしません")
if isinstance(x, (int, float)):
return x * x
raise TypeError("数値のみ受け付けます")
print(square(3.5)) # 12.25
Python例題4:関数・クラス・インスタンスの型を見る
def f(): pass
class A: pass
a = A()
print(type(f)) # <class 'function'>
print(type(A)) # <class 'type'>(クラスの型は type)
print(type(a)) # <class '__main__.A'>
Pythonまとめ
type は「この値は何者か」を即座に可視化する道具で、動的型付けの Python では心強い相棒です。厳密判定が必要なら type、継承を含めた実務的な判定なら isinstance を選ぶ。bool が int のサブクラスという落とし穴、外部ライブラリの独自型、入力検証の型ガード——このあたりを意識するだけで、初心者のコードは一段クリアになります。型を味方につけて、意図が伝わる分岐と堅牢なデバッグを習慣化しましょう。
