2.33. イントロスペクション

実行中のプログラムが自分自身(扱っている値、それらの値が存在する名前空間、クラス間の関係)を調べられるようにする組み込み関数がいくつかあります。呼び出し側が主張する内容ではなく、オブジェクトが 実際に何であるか に基づいて判断を下す必要があるときに使ってください。

2.33.1. 同一性とハッシュ

  • id() -- オブジェクトが生きている限りそのオブジェクトを識別する一意の整数。同じオブジェクトを束縛する2つの名前は同じ id を返し、等しいが別個の2つのオブジェクトは返しません。

>>> a = [1, 2, 3]
>>> b = a
>>> c = [1, 2, 3]
>>> id(a) == id(b)        # same list
True
>>> id(a) == id(c)        # equal but distinct
False

id は実行をまたいで移植可能ではなく、「同じオブジェクトか別のオブジェクトか」以上の意味は持ちません。

  • hash() -- オブジェクトのハッシュ値で、dictset がそれを検索するために使うのと同じ数値。等しい2つのオブジェクトは同じ値にハッシュされます。そもそもハッシュ可能な型(主に不変の値)のみが機能します。

>>> hash("abc")           # some integer, build-dependent
-1600925533
>>> hash([1, 2])
TypeError: unhashable type: 'list'

2.33.2. 型と呼び出し可能性の問い合わせ

  • type() -- 値の正確なクラス。type(x) is int は「x はちょうど int か」を問います(サブクラスは含みません)。通常は代わりに isinstance() が望むものです。

  • isinstance() -- 「x はこのクラスのインスタンスか、またはそのサブクラスか?」関数内で型に基づくディスパッチを行うための標準的なツールです。

  • issubclass() -- クラスレベルの対応物。インスタンスではなく2つのクラスを取ります。

  • callable() -- 引数が () で呼び出せる場合は True。関数かもしれないし単純な値かもしれない引数を受け取るときに便利です。

>>> isinstance(3, int)
True
>>> isinstance(True, int)        # bool is a subclass of int
True
>>> issubclass(bool, int)
True
>>> callable(len)
True
>>> callable(10)
False

callable を使うパターン:

def call_or_return(x):
    return x() if callable(x) else x

2.33.3. スコープを覗く

  • globals() -- モジュールのグローバル名前空間を dict として返します。そこから読み取るのは問題ありません。書き込むのは実際に反映されますが、REPLでの探索以外でそうするとプログラムが追いにくくなります。

  • locals() -- 呼び出し箇所のローカル名前空間。関数内ではローカル変数を反映します。返された辞書を 変更 しても、実際のローカル変数に書き戻される保証はありません(実装定義の挙動です)。

name = "OpenMV"

def f():
    x = 10
    print(globals()["name"])    # OpenMV
    print(locals())             # {'x': 10}

この2つはデバッグや、何が定義されているかを発見する必要があるツールにとって便利です。通常のコードでは控えめに使ってください。globals() を変更する関数は、Pythonで最も推論しにくいものの一つです。

2.33.4. 関連項目

debugging で扱う dir()help() は、未知のオブジェクトの表面を探索するための日常的なイントロスペクションツールです。