python inspect.getmembersソース分析

12481 ワード

個人ブログ
getmembersの役割
getmembers(object,predicate=None)メソッドinspectモジュール
getmembers(object,predicate=None)メソッドは、objectオブジェクト内のすべてのメンバーを抽出し、(メンバー1名,メンバー1値)、(メンバー2名,メンバー2値)、...)に再編成する形で返します.predicateパラメータは、predicateがNoneでない場合、predicateで判断されたメンバーのみを返します.
import inspect


class Foo(object):
    a1 = 1
    a2 = 2

    def __init__(self):
        self.a3 = 2
        self.a4 = 3

    def f1(self):
        pass

    @classmethod
    def f2(cls):
        pass

    @staticmethod
    def f3(cls):
        pass


for item in inspect.getmembers(Foo):
    print(item)
実行結果:
('__class__', )
('__delattr__', )
('__dict__', mappingproxy({'__module__': '__main__', 'a1': 1, 'a2': 2, '__init__': , 'f1': , 'f2': , 'f3': , '__dict__': , '__weakref__': , '__doc__': None}))
('__dir__', )
('__doc__', None)
('__eq__', )
('__format__', )
('__ge__', )
('__getattribute__', )
('__gt__', )
('__hash__', )
('__init__', )
('__init_subclass__', )
('__le__', )
('__lt__', )
('__module__', '__main__')
('__ne__', )
('__new__', )
('__reduce__', )
('__reduce_ex__', )
('__repr__', )
('__setattr__', )
('__sizeof__', )
('__str__', )
('__subclasshook__', )
('__weakref__', )
('a1', 1)
('a2', 2)
('f1', )
('f2', >)
('f3', )
getmembersの実装手順
  • objectのすべてのメンバーの名前を取得し、objectの親クラスのメンバーを含み、namesリスト
  • に格納する.
  • objectのベースクラスからDynamicClassAttributeタイプのメンバーを取得し、namesリストの
  • に追加
  • namesリストを巡り、getattrメソッドでobject内のすべての属性の値を取得します.getattr(x,‘y’)はx.y
  • に相当します.
  • predicateでメンバー値を判断し、判断したメンバーをresultsというリストに(メンバー名、メンバー値)として
  • に追加する.
  • resultsリストをメンバー名でソート
  • getmembersのソースコード
    ソースファイルはC:/Program Files/Python 36/Lib/inspect.py,C:/Program Filesはpythonのインストールディレクトリです
    def getmembers(object, predicate=None):
        """Return all members of an object as (name, value) pairs sorted by name.
        Optionally, only return members that satisfy a given predicate."""
        if isclass(object):
            mro = (object,) + getmro(object)
        else:
            mro = ()
        results = []
        processed = set()
        #    object         ,   object       
        names = dir(object) 
        # :dd any DynamicClassAttributes to the list of names if object is a class;
        # this may result in duplicate entries if, for example, a virtual
        # attribute with the same name as a DynamicClassAttribute exists
        #   object        DynamicClassAttribute      ,    names    
        try:
            for base in object.__bases__:
                for k, v in base.__dict__.items():
                    if isinstance(v, types.DynamicClassAttribute):
                        names.append(k)
        except AttributeError:
            pass
        ##    names   ,   getattr      object        
        for key in names:
            # First try to get the value via getattr.  Some descriptors don't
            # like calling their __get__ (see bug #1785), so fall back to
            # looking in the __dict__.
            try:
                value = getattr(object, key)
                # handle the duplicate key
                if key in processed:
                    raise AttributeError
            except AttributeError:
                for base in mro:
                    if key in base.__dict__:
                        value = base.__dict__[key]
                        break
                else:
                    # could be a (currently) missing slot member, or a buggy
                    # __dir__; discard and move on
                    continue
            if not predicate or predicate(value):
              	#     predicate       , (   ,    )       results      
                results.append((key, value))
            processed.add(key)
        #   results     key     
        results.sort(key=lambda pair: pair[0])
        return results