オブジェクトのメソッドと属性の完全なリストを取得するにはどうすればよいですか?


230
dir(re.compile(pattern)) 

リストの要素の1つとしてパターンを返しません。つまり、次を返します:

['__copy__', '__deepcopy__', 'findall', 'finditer', 'match', 'scanner', 'search', 'split', 'sub', 'subn']

マニュアルによると、それは含まれているはずです

オブジェクトの属性の名前、そのクラスの属性の名前、およびそのクラスの基本クラスの属性の再帰。

それはまた言う

リストは必ずしも完全なものではありません。

完全なリストを取得する方法はありますか?私はいつもdirが完全なリストを返すと思っていましたが、どうやらそうではありません...

また、属性のみを一覧表示する方法はありますか?またはメソッドのみですか?

編集:これは実際にはPythonのバグです->おそらく3.0ブランチで(そしておそらく2.6でも)修正されています


5
使用dir()または検査モジュールは、一般的にそれを行うための正しい方法です。reモジュールを例として使用しましたか、それとも特別な目標を達成したいですか?

1
パターンは、コンパイル後に実際にデータとして保持されますか?パターンをコンパイルするポイントは、与えられたパターンを解析するために必要な有限状態オートマトンを生成することであるという印象を受けました。
カイルストランド

@hopはクラスによって回避できませんか?たとえば、彼らは彼らをオンにすることができます__dir__()
ytpillai 2015

ytpillai:正しいが、唯一のPython 3でそうであっても、問題は、このようなクラスは、「一般的なケース」に該当するかどうか、である

回答:


140

属性の完全なリストについては、簡単な答えは「いいえ」です。問題は、属性がgetattr組み込み関数によって受け入れられる引数として実際に定義されていることです。ユーザーはを再実装でき__getattr__、突然あらゆる種類の属性を許可できるため、そのリストを生成する一般的な方法はありません。dir関数は、内のキーを返し__dict__た場合、すなわち、アクセス可能なすべての属性、属性__getattr__メソッドが再実装されていません。

2番目の質問については、それは実際には意味がありません。実際、メソッドは呼び出し可能な属性であり、それ以上のものではありません。ただし、呼び出し可能な属性をフィルタリングし、inspectモジュールを使用してクラスのメソッド、メソッド、または関数を決定することもできます。


1
inpect.getmembers(re.compile(pattern))もパターンをメンバーとして生成しないため、おそらく内部でdirを使用します...これはうんざりです!
BartoszRadaczyński2008年

callableを使用してそれらがメソッドであるかどうかを確認することもできますが、それは重要ではありません... dirが実際に公開されている属性のリストを返すことさえ信頼できない...
BartoszRadaczyńskiOct

2
inspectは、dir()と「少なくとも同じくらい」信頼できることを意味します。一方、再非常に複雑なモジュールである

「公に見える」とはどういう意味ですか?「アクセスできる」という意味の場合、それは、与えられた理由により失われた原因です。それ以外の場合、「dir」は常にgetattrのデフォルト実装でアクセス可能な属性のリストを返します。
PierreBdR 2008年

2
dir(my_class)は、my_class .__ dict __。keys()とは異なるものを返します。前者はinitdoc
JuanPi

58

これが__dir__()、Python 2.6に新しいメソッドが追加された理由です。

見る:


私はこのエラーを受け取ります:>> dir __(pyrenderdoc)トレースバック(最後の最新の呼び出し):ファイル "<string>"、1行目<モジュール>内NameError:名前 '__dir 'が定義されていません
Mona Jalal

__dir__()はオブジェクトのメソッドであり、関数ではありません-回答とこれの
Moe

すべての属性とその値をpprintするためのワンライナー:pprint({k:getattr(ojb,k) for k in obj.__dir__()})
チェコ語2018

21

以下は、PierreBdRとMoeの回答への実用的な追加です。

  • Python> = 2.6および新しいスタイルのクラスの場合、dir()十分なようです。
  • 以下のために古いスタイルのクラスは、我々は、少なくとも何ができる標準モジュールは、に加えて:タブ補完をサポートするために行いdir()、用を見て__class__、そしてそのために行きます__bases__

    # code borrowed from the rlcompleter module
    # tested under Python 2.6 ( sys.version = '2.6.5 (r265:79063, Apr 16 2010, 13:09:56) \n[GCC 4.4.3]' )
    
    # or: from rlcompleter import get_class_members
    def get_class_members(klass):
        ret = dir(klass)
        if hasattr(klass,'__bases__'):
            for base in klass.__bases__:
                ret = ret + get_class_members(base)
        return ret
    
    
    def uniq( seq ): 
        """ the 'set()' way ( use dict when there's no set ) """
        return list(set(seq))
    
    
    def get_object_attrs( obj ):
        # code borrowed from the rlcompleter module ( see the code for Completer::attr_matches() )
        ret = dir( obj )
        ## if "__builtins__" in ret:
        ##    ret.remove("__builtins__")
    
        if hasattr( obj, '__class__'):
            ret.append('__class__')
            ret.extend( get_class_members(obj.__class__) )
    
            ret = uniq( ret )
    
        return ret

(テストコードと出力は簡潔にするために削除されていますが、基本的には新しいスタイルのオブジェクトの場合と同じ結果が得られるget_object_attrs()ようですdir()。古いスタイルのクラスの場合、dir()出力への主な追加は__class__属性のようです。)


9

補足のみ:

  1. dir()最も強力な/基本的なツールです。(最も推奨
  2. の出力を処理する方法dir()提供する以外のソリューション。dir()

    2番目のレベルの属性をリストするかどうかにかかわらず、先頭にアンダースコアを付けて内部変数をふるい分けしたい__場合もあれば、__doc__doc-string が必要な場合もあるため、自分でふるいにかけることが重要です。

  3. __dir__()dir()同一のコンテンツを返します。
  4. __dict__dir()は異なります。__dict__不完全なコンテンツを返します。
  5. 重要:作成__dir__()者は、目的を問わず、関数、値、またはタイプで上書きされることがあります。

    次に例を示します。

    \\...\\torchfun.py in traverse(self, mod, search_attributes)
    445             if prefix in traversed_mod_names:
    446                 continue
    447             names = dir(m)
    448             for name in names:
    449                 obj = getattr(m,name)

    TypeError:オブジェクトの記述子に__dir__'object'引数が必要です

    PyTorchの作者は、__dir__()メソッドを引数を必要とするものに変更しました。この変更はdir()失敗します。

  6. 信頼性の高いスキームでオブジェクトのすべての属性をトラバースしたい場合は、すべてのPythonic標準をオーバーライドして保持できない可能性があり、すべての規則が信頼できない可能性があることに注意してください。


5

これは私がそれを行う方法であり、属性を追加し続ける単純なカスタムオブジェクトに役立ちます。

で作成されたオブジェクトobj = type("Obj",(object,),{})、または単に次のように作成されたオブジェクトがあるとします。

class Obj: pass
obj = Obj()

いくつかの属性を追加します。

obj.name = 'gary'
obj.age = 32

次に、カスタム属性のみを含む辞書を取得します。

{key: value for key, value in obj.__dict__.items() if not key.startswith("__")}

# {'name': 'gary', 'age': 32}

Python 3.xのすべての属性のリスト:{key:value for key、value in obj .__ dict __。items()if not if key.startswith( "__")} ['_ declared_fields']。keys()
above_c_level
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.