Pythonクラスのメソッドのリストを取得するにはどうすればよいですか?


331

1
ソース.....ソース...
RickyA 2013年

4
@JonCrowellそれはフォースが機能する方法ではありません。
ケンウィリアムズ

Cythonの場合、コンパイラディレクティブを使用して動作しbindingます:stackoverflow.com/a/46041480/1959808
Ioannis Filippidis

4
python3オン:[f for f in dir(ClassName) if not f.startswith('_')]またはちょうどdir(ClassName)すべてのため
Seraf

@Serafコメントに回答を投稿しないでください。代わりに回答を投稿してください。
wjandrea

回答:


332

例(optparse.OptionParserクラスのメソッドのリスト):

>>> from optparse import OptionParser
>>> import inspect
#python2
>>> inspect.getmembers(OptionParser, predicate=inspect.ismethod)
[([('__init__', <unbound method OptionParser.__init__>),
...
 ('add_option', <unbound method OptionParser.add_option>),
 ('add_option_group', <unbound method OptionParser.add_option_group>),
 ('add_options', <unbound method OptionParser.add_options>),
 ('check_values', <unbound method OptionParser.check_values>),
 ('destroy', <unbound method OptionParser.destroy>),
 ('disable_interspersed_args',
  <unbound method OptionParser.disable_interspersed_args>),
 ('enable_interspersed_args',
  <unbound method OptionParser.enable_interspersed_args>),
 ('error', <unbound method OptionParser.error>),
 ('exit', <unbound method OptionParser.exit>),
 ('expand_prog_name', <unbound method OptionParser.expand_prog_name>),
 ...
 ]
# python3
>>> inspect.getmembers(OptionParser, predicate=inspect.isfunction)
...

getmembers2つのタプルのリストを返すことに注意してください。最初の項目はメンバーの名前、2番目の項目は値です。

インスタンスをgetmembers以下に渡すこともできます:

>>> parser = OptionParser()
>>> inspect.getmembers(parser, predicate=inspect.ismethod)
...

4
完璧です。述語部分が重要です。それ以外の場合は、追加のメタ情報を使用してdictと同じものを取得します。ありがとう。
Purrell、2009

2
これは、クラス内のすべてのメソッドのリストを生成しますか(他のクラスから継承されたものを含む)、またはそのクラスで明示的に定義されたメソッドのみをリストしますか?
アンダーソングリーン

10
inspect.isroutine より適切な述語かもしれません。 inspect.ismethodすべてのオブジェクトのメソッドに対して機能するわけではありません。
Gavin S. Yancey 2017

1
これは、クラスのインスタンスを使用する場合にのみ機能しました(例も同様)。これは予想される動作ですか?
Christian Reall-Fluharty

2
Python 3.7では少なくともこれは機能しません。クラスをインスタンス化する必要があります
kederrac

222

そこには dir(theobject)リストのすべてのフィールドと(タプルとして)あなたのオブジェクトのメソッドへの方法は、と(「「」で)そのドキュメントのフィールドやメソッドを一覧表示する(codeape書き込みなど)モジュールを点検します。

Pythonではすべて(フィールドも含む)が呼び出される可能性があるため、メソッドのみをリストする組み込み関数があるかどうかはわかりません。あなたがオブジェクトなら試してみたいかもしれません取得しdir呼び出し可能か。


3
dir(object)は、私が使用した最も簡単なソリューションです。
lstodd

@skjerns入力するには5つの記号が必要です。:)
Dr_Zaszuś

117

外部ライブラリなしのPython 3.xの回答

method_list = [func for func in dir(Foo) if callable(getattr(Foo, func))]

ダンダー除外結果:

method_list = [func for func in dir(Foo) if callable(getattr(Foo, func)) and not func.startswith("__")]

38

リストクラスに関連するすべてのメソッドを知りたいとしましょう。

 print (dir(list))

上記はリストクラスのすべてのメソッドを提供します


2
これが最良の解決策です
Zeeshan Ahmad

3
print([ m for m in dir(my_class) if not m.startswith('__')])
Evhz

32

プロパティを試してください__dict__


16
私はあなたが口述を意味すると思います。しかし、それはメソッドではなくインスタンスの属性をリストします。
me_and 2009

1
…それも私にはうまくいきませんでした。Markdown構文を調べたので、私は__dict__を意味すると思います。
me_and 2009

3
@me_andあなたはおそらく「self .__ dict__」を行っているか、より一般的にはのインスタンスバージョンを呼び出しています__dict__。ただし、クラスに__dict__もあり、クラスメソッドを表示する必要があります:)
Seaux

21

タイプからFunctionTypeをインポートして、それをでテストすることもできますclass.__dict__

from types import FunctionType

class Foo:
    def bar(self): pass
    def baz(self): pass

def methods(cls):
    return [x for x, y in cls.__dict__.items() if type(y) == FunctionType]

methods(Foo)  # ['bar', 'baz']

これは私にとってはうまくいきました。and not x.startswith('_')リストの最後に、__init__とプライベートメソッドを無視するための理解を追加しました。
クリストファーピアソン

2
あなたが取り除くことができますimportFunctionTypeで使い捨てのラムダを使用することによりtype()type(lambda:0)
Tersosauros

isinstancetype(y) == FunctionTypeここより良いでしょう
Gloweye 2018年

13

継承された(オーバーライドされていない)基本クラスのメソッドを結果に含めるかどうかを検討する必要があることに注意してください。dir()およびinspect.getmembers()操作は、基本クラスのメソッドが含まれませんが、使用__dict__属性がありません。


3

これも機能します:

mymodule.py

def foo(x)
   return 'foo'
def bar()
   return 'bar'

別のファイル

import inspect
import mymodule
method_list = [ func[0] for func in inspect.getmembers(mymodule, predicate=inspect.isroutine) if callable(getattr(mymodule, func[0])) ]

出力:

['foo', 'bar']

Pythonドキュメントから:

inspect.isroutine(オブジェクト)

Return true if the object is a user-defined or built-in function or method.

2
def find_defining_class(obj, meth_name):
    for ty in type(obj).mro():
        if meth_name in ty.__dict__:
            return ty

そう

print find_defining_class(car, 'speedometer') 

Pythonを考える210ページ


3
5のインデント?キーワードを大文字にしますか?非pep8スタイルの間隔?
Florrie、2015

1
コーディング規約のナチスがこれに到達したことは一度もありません!
rbennell 2017

1
これはどのように質問に答えますか?
Aran-Fey

2

このアプローチがあります:

[getattr(obj, m) for m in dir(obj) if not m.startswith('__')]

クラスインスタンスを処理する場合、名前だけではなく、メソッド参照を含むリストを返す方がよいでしょう。それがあなたの目標であるなら

  1. いいえを使用して import
  2. __init__リストからプライベートメソッド(例:)を除外する

役に立つかもしれません。一言で言えば、クラスのような

class Ghost:
    def boo(self, who):
        return f'Who you gonna call? {who}'

インスタンスの取得は、

>>> g = Ghost()
>>> methods = [getattr(g, m) for m in dir(g) if not m.startswith('__')]
>>> print(methods)
[<bound method Ghost.boo of <__main__.Ghost object at ...>>]

したがって、すぐに呼び出すことができます。

>>> for method in methods:
...     print(method('GHOSTBUSTERS'))
...
Who you gonna call? GHOSTBUSTERS

useユースケース:

これを単体テストに使用しました。すべてのメソッドが同じプロセスのバリエーションを実行するクラスを持っていた-これは長いテストにつながり、それぞれが他のものから微調整されただけでした。DRYは遠い夢でした。

すべてのメソッドに対して単一のテストが必要だと思ったので、上記の反復を行いました。

とにかく、コード自体をDRY準拠にリファクタリングする必要があることに気づきましたがこれは、将来的にランダムな気まぐれな魂に役立つ可能性があります。


2

最高評価の回答が明確でないため、これをそのまま保持しますます。

これは、Enumに基づく通常のクラスではない単純なテストです。

# -*- coding: utf-8 -*-
import sys, inspect
from enum import Enum

class my_enum(Enum):
    """Enum base class my_enum"""
    M_ONE = -1
    ZERO = 0
    ONE = 1
    TWO = 2
    THREE = 3

    def is_natural(self):
            return (self.value > 0)
    def is_negative(self):
            return (self.value < 0)

def is_clean_name(name):
    return not name.startswith('_') and not name.endswith('_')
def clean_names(lst):
    return [ n for n in lst if is_clean_name(n) ]
def get_items(cls,lst):
    try:
            res = [ getattr(cls,n) for n in lst ]
    except Exception as e:
            res = (Exception, type(e), e)
            pass
    return res


print( sys.version )

dir_res = clean_names( dir(my_enum) )
inspect_res = clean_names( [ x[0] for x in inspect.getmembers(my_enum) ] )
dict_res = clean_names( my_enum.__dict__.keys() )

print( '## names ##' )
print( dir_res )
print( inspect_res )
print( dict_res )

print( '## items ##' )
print( get_items(my_enum,dir_res) )
print( get_items(my_enum,inspect_res) )
print( get_items(my_enum,dict_res) )

そしてこれが出力結果です。

3.7.7 (default, Mar 10 2020, 13:18:53) 
[GCC 9.2.1 20200306]
## names ##
['M_ONE', 'ONE', 'THREE', 'TWO', 'ZERO']
['M_ONE', 'ONE', 'THREE', 'TWO', 'ZERO', 'name', 'value']
['is_natural', 'is_negative', 'M_ONE', 'ZERO', 'ONE', 'TWO', 'THREE']
## items ##
[<my_enum.M_ONE: -1>, <my_enum.ONE: 1>, <my_enum.THREE: 3>, <my_enum.TWO: 2>, <my_enum.ZERO: 0>]
(<class 'Exception'>, <class 'AttributeError'>, AttributeError('name'))
[<function my_enum.is_natural at 0xb78a1fa4>, <function my_enum.is_negative at 0xb78ae854>, <my_enum.M_ONE: -1>, <my_enum.ZERO: 0>, <my_enum.ONE: 1>, <my_enum.TWO: 2>, <my_enum.THREE: 3>]

だから私たちが持っているもの:

  • dir 完全ではないデータを提供する
  • inspect.getmembers 完全ではないデータを提供し、アクセスできない内部キーを提供する getattr()
  • __dict__.keys()完全で信頼できる結果を提供する

なぜ投票がそれほど間違っているのですか?そして、どこが間違っているのですか?そして、答えを間違っている他の人々が投票率が低いのはどこですか?


1
methods = [(func, getattr(o, func)) for func in dir(o) if callable(getattr(o, func))]

と同じリストを与える

methods = inspect.getmembers(o, predicate=inspect.ismethod)

します。


0

あなたの方法が「通常の」方法でありstatimethodclassmethodなどで
はない場合、私が思いついた小さなハックがあります-

for k, v in your_class.__dict__.items():
    if "function" in str(v):
        print(k)

これは、if対応する条件の「関数」を変更することにより、他のタイプのメソッドに拡張できます。
Python 2.7でテスト済み。


1
なぜこれが反対票だったのかわからない...それは実際に私が抱えていた問題を解決しました。
redspidermkv

0

次のコードを使用して、Pythonクラスのすべてのメソッドをリストできます

dir(className)

これは、クラス内のメソッドのすべての名前のリストを返します


-1

私はこれが古い投稿であることを知っていますが、この関数を書いただけでここに残します。

def classMethods(the_class,class_only=False,instance_only=False,exclude_internal=True):

    def acceptMethod(tup):
        #internal function that analyzes the tuples returned by getmembers tup[1] is the 
        #actual member object
        is_method = inspect.ismethod(tup[1])
        if is_method:
            bound_to = tup[1].im_self
            internal = tup[1].im_func.func_name[:2] == '__' and tup[1].im_func.func_name[-2:] == '__'
            if internal and exclude_internal:
                include = False
            else:
                include = (bound_to == the_class and not instance_only) or (bound_to == None and not class_only)
        else:
            include = False
        return include
    #uses filter to return results according to internal function and arguments
    return filter(acceptMethod,inspect.getmembers(the_class))

このコードは、公開されたとおりの動作をしません。class_onlyまたはinstance_onlyを指定すると、リストが空になります。
Oz123

-2

これは単なる観察です。「encode」は文字列オブジェクトのメソッドのようです

str_1 = 'a'
str_1.encode('utf-8')
>>> b'a'

ただし、str1のメソッドを検査すると、空のリストが返されます。

inspect.getmember(str_1, predicate=inspect.ismethod)
>>> []

だから、私は間違っているかもしれませんが、問題は単純ではないようです。


1
'a'タイプがのオブジェクトですstr。を実行すると、これを確認できますtype('a')inspect.getmember()型パラメーターを受け取るため、呼び出してinspect.getmember(str)、期待どおりのものを表示する必要があります。
ラソン

-3
class CPerson:
    def __init__(self, age):
        self._age = age

    def run(self):
        pass

    @property
    def age(self): return self._age

    @staticmethod
    def my_static_method(): print("Life is short, you need Python")

    @classmethod
    def say(cls, msg): return msg


test_class = CPerson
# print(dir(test_class))  # list all the fields and methods of your object
print([(name, t) for name, t in test_class.__dict__.items() if type(t).__name__ == 'function' and not name.startswith('__')])
print([(name, t) for name, t in test_class.__dict__.items() if type(t).__name__ != 'function' and not name.startswith('__')])

出力

[('run', <function CPerson.run at 0x0000000002AD3268>)]
[('age', <property object at 0x0000000002368688>), ('my_static_method', <staticmethod object at 0x0000000002ACBD68>), ('say', <classmethod object at 0x0000000002ACF0B8>)]

-4

Pythonクラスのメソッドのみを一覧表示する場合

import numpy as np
print(np.random.__all__)

1
これはモジュールではなく、クラスです。
Aran-Fey

@ Aran-Feyこれはすべてのクラスに適用され、すべてすべてのクラスに存在します
Rakesh Chaudhari

2
いいえ、ありません。すべてのモジュールに存在するわけではありません。
Aran-Fey
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.