Python inspect.getmembers()の使い方|predicateでメソッド・クラスだけ取り出す
inspect.getmembers(object, predicate)は、オブジェクトが持つ属性を(名前, 値)のタプルのリストにして、名前順で返す関数です。第2引数のpredicateにinspect.isfunctionなどを渡すと、メソッドだけ・クラスだけのように絞り込めます。
この記事では、predicateの使い方と選び方(isfunctionとismethodの違い)、モジュールからクラスを集める例、プロパティが実行されてしまう落とし穴とgetmembers_static()までを、実行結果つきで解説します。コードはPython 3.12で実行し、Python 3.15の公式ドキュメント(2026年10月18日確認)と照らし合わせています。
inspect.getmembers()の基本
例として、親クラスを継承し、通常のメソッド・staticmethod・classmethod・propertyを持つクラスを用意します。この記事のコードはすべてこのクラスを使います。
import inspect
class Base:
base_attr = 1
def base_m(self): pass
class Calc(Base):
"""計算クラス"""
version = "1.0"
def add(self, a, b): return a + b
def sub(self, a, b): return a - b
@staticmethod
def helper(): return "help"
@classmethod
def create(cls): return cls()
@property
def name(self): return "calc"
members = inspect.getmembers(Calc)
print(len(members))
print([n for n, v in members][:4])
実行結果:
35
['__class__', '__delattr__', '__dict__', '__dir__']
自分で書いた属性は8つほどなのに、35件返ってきます。objectから継承した__class__や__eq__などの特殊属性も全部入るためです。並びは名前順なので、アンダースコアで始まる特殊属性が先頭に来ます。実際に使うときは、ほぼ必ず第2引数で絞り込みます。
predicate(第2引数)で絞り込む
predicateには「値を受け取って真偽を返す関数」を渡します。公式ドキュメントのとおり、各メンバーの値に対して呼ばれ、真を返したものだけが残ります。inspectモジュールには、そのまま渡せる判定関数が用意されています。
| predicate | 残るもの | 上のCalcクラスで残る名前 |
|---|---|---|
inspect.isfunction |
Pythonで定義した関数 | add, base_m, helper, sub |
inspect.ismethod |
束縛されたメソッド | create(クラスに対して使った場合) |
inspect.isroutine |
関数・メソッド・組み込み関数すべて | 上記すべて+特殊メソッド |
inspect.isclass |
クラス | __class__ |
inspect.ismodule |
モジュール | (モジュールに対して使う) |
inspect.isdatadescriptor |
propertyなどのデータディスクリプタ | __weakref__, name |
print([n for n, v in inspect.getmembers(Calc, inspect.isfunction)])
print([n for n, v in inspect.getmembers(Calc, inspect.ismethod)])
print([n for n, v in inspect.getmembers(Calc, inspect.isroutine) if not n.startswith("_")])
実行結果:
['add', 'base_m', 'helper', 'sub']
['create']
['add', 'base_m', 'create', 'helper', 'sub']
「メソッドを全部取りたい」なら、isroutineで取ってから_で始まる名前を除くのが一番取りこぼしがありません。
isfunctionとismethodの違い(クラスかインスタンスか)
同じメソッドでも、クラスから見るかインスタンスから見るかで判定が変わります。「getmembersでメソッドが取れない」というつまずきの多くはこれが原因です。
c = Calc()
print("クラス + isfunction :", [n for n, v in inspect.getmembers(Calc, inspect.isfunction)])
print("インスタンス + ismethod :", [n for n, v in inspect.getmembers(c, inspect.ismethod)])
print("インスタンス + isfunction:", [n for n, v in inspect.getmembers(c, inspect.isfunction)])
実行結果:
クラス + isfunction : ['add', 'base_m', 'helper', 'sub']
インスタンス + ismethod : ['add', 'base_m', 'create', 'sub']
インスタンス + isfunction: ['helper']
| 定義の仕方 | クラスから見ると | インスタンスから見ると |
|---|---|---|
| 普通のメソッド | 関数(isfunction) |
メソッド(ismethod) |
@classmethod |
メソッド(ismethod) |
メソッド(ismethod) |
@staticmethod |
関数(isfunction) |
関数(isfunction) |
@property |
どちらでもない(isdatadescriptor) |
値そのもの(プロパティが実行される) |
クラスを調べるならisfunction、インスタンスを調べるならismethodが基本です。staticmethodはselfを受け取らないので、インスタンスから見てもただの関数のままです。
predicateは自分で書ける
predicateはただの関数なので、lambdaで好きな条件を書けます。たとえば文字列のクラス変数だけ、propertyだけを取り出せます。
for name, value in inspect.getmembers(Calc, lambda x: isinstance(x, str)):
print(name, "=", value)
print([n for n, v in inspect.getmembers(Calc, lambda v: isinstance(v, property))])
実行結果:
__doc__ = 計算クラス
__module__ = __main__
version = 1.0
['name']
isdatadescriptorだと__weakref__も混ざりますが、isinstance(v, property)ならpropertyだけになります。特殊属性を除きたいときは、if not n.startswith("_")を内包表記に足すのが定番です。
モジュールからクラスを集める(プラグインの自動登録)
モジュールを渡すと、モジュールの中身を調べられます。ただし、そのモジュールがimportしただけのものも混ざります。そのモジュールで定義されたものだけに絞るには、__module__を見ます。
import collections
import inspect
names = [n for n, v in inspect.getmembers(collections, inspect.isclass)]
def defined_in(mod):
return lambda o: inspect.isclass(o) and o.__module__ == mod.__name__
own = [n for n, v in inspect.getmembers(collections, defined_in(collections))]
print(names[:6])
print("importしただけのクラス:", set(names) - set(own))
実行結果(Python 3.12):
['ChainMap', 'Counter', 'OrderedDict', 'UserDict', 'UserList', 'UserString']
importしただけのクラス: {'_itemgetter', '_repeat', '_chain', '_starmap'}
この仕組みを使うと、「ある基底クラスを継承したクラスを全部見つけて登録する」処理が書けます。
import inspect
import sys
class Plugin: pass
class A(Plugin): pass
class B(Plugin): pass
mod = sys.modules[__name__]
found = [n for n, v in inspect.getmembers(
mod, lambda o: inspect.isclass(o) and issubclass(o, Plugin) and o is not Plugin)]
print(found)
実行結果:
['A', 'B']
同じ考え方で、名前の規則に合うメソッドをまとめて呼ぶこともできます。
class Checks:
def check_a(self): return "a ok"
def check_b(self): return "b ok"
def other(self): return "x"
for name, method in inspect.getmembers(Checks(), inspect.ismethod):
if name.startswith("check_"):
print(name, "->", method())
実行結果:
check_a -> a ok
check_b -> b ok
注意:インスタンスに使うとpropertyが実行される
getmembers()は内部でgetattr()を使って値を取り出すので、インスタンスに使うとpropertyの中身が実行されます。重い処理や、失敗するpropertyがあると困ったことになります。
class Slow:
@property
def data(self):
print(" dataを計算しました")
return 42
class Broken:
@property
def x(self):
raise RuntimeError("ここで失敗")
print("getmembers:")
print(" data =", dict(inspect.getmembers(Slow()))["data"])
try:
inspect.getmembers(Broken())
except RuntimeError as e:
print("RuntimeError:", e)
実行結果:
getmembers:
dataを計算しました
data = 42
RuntimeError: ここで失敗
propertyの中で例外が起きると、getmembers()全体が止まります。
getmembers_static()で実行せずに調べる(Python 3.11以降)
Python 3.11で追加されたinspect.getmembers_static()は、ディスクリプタや__getattr__を経由した動的な取得をせずにメンバーを返します。propertyは実行されず、property オブジェクトのまま返ります。
print(" data =", dict(inspect.getmembers_static(Slow()))["data"])
print([n for n, v in inspect.getmembers_static(Broken()) if not n.startswith("_")])
実行結果:
data = <property object at 0x10591f5b0>
['x']
公式ドキュメントによると、getmembers_static()は動的に作られる属性などgetmembers()が取れるものを取れない場合があり、逆にAttributeErrorを出すディスクリプタのようにgetmembers()では見つからないものを見つける場合もあります。値を使いたいならgetmembers()、名前と種類だけを安全に調べたいならgetmembers_static()と使い分けます。
dir()・vars()との使い分け
dir() |
vars() |
inspect.getmembers() |
|
|---|---|---|---|
| 戻り値 | 名前のリスト | そのオブジェクト自身の__dict__ |
(名前, 値)のリスト |
| 継承した属性 | 含む | 含まない | 含む |
| 絞り込み | できない | できない | predicateで可能 |
| 向いている用途 | 対話モードでざっと見る | そのクラスで定義したものだけ見る | 取り出した値をその場で使う |
名前を確認するだけならdir()で十分です。そのクラスで定義したものだけならvars(Calc)が簡単です。値を呼び出したり登録したりする処理ではgetmembers()が便利です。inspectモジュール全体はinspectモジュールの使い方にまとめています。
よくある質問
Q. getmembers()でメソッドが取れないのはなぜですか?
クラスに対してismethodを使っている可能性があります。クラスから見た普通のメソッドは関数なのでisfunctionを、インスタンスから調べるならismethodを使います。
Q. 特殊属性(__で始まるもの)を除くには?
内包表記でif not name.startswith(“_”)を付けて除きます。predicateの中で名前は受け取れないので、名前での絞り込みは結果に対して行います。
Q. getmembers()の結果の並び順は?
名前順にソートされたリストで返ります。定義した順番が必要なときはvars()でクラスの__dict__を見ます。
Q. getmembers()とgetmembers_static()はどちらを使えばいいですか?
値を取り出して使うならgetmembers()です。propertyや__getattr__を実行させたくないときは、Python 3.11以降で使えるgetmembers_static()を使います。
まとめ
inspect.getmembers()は(名前, 値)のリストを名前順で返す- 絞り込まないと特殊属性まで数十件出るので、predicateを渡す
- クラスは
isfunction、インスタンスはismethod。漏れなく取るならisroutine - predicateは
lambdaで自作できる - インスタンスに使うとpropertyが実行される。避けたいときは
getmembers_static()


