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()

あわせて読みたい

対面・無料|東京・永田町で毎週土曜日13時

1回の参加で、プログラミングの構造がわかる

ゼロからはじめるPython入門講座

8年間・累計600回開催/これまで全国で2万人以上が参加

「やはり対面で聞けるのはとても気づきがあり、価値があると思います」

参加者の声

  • 本当に初心者からの講座です。プログラミングに触ったことがなくて大丈夫です
  • 対面だから、その場で聞けます。つまずいた所を持ち帰らずに解決できます
  • 講座は1時間。そのあとも残って学習を続けられ、講師にも質問できます
  • 独学で挫折した方も。糸口が見つかって、講座のあと会員になる方が多くいます

無料で参加する|開催日程を見る

参加費は無料です