python inspect.getmembers 源码分析

本文详细分析了Python `inspect.getmembers`方法的作用、实现步骤和源码,阐述了如何获取对象成员并过滤指定条件的成员,以及源码中的关键操作,如获取成员名、判断成员和排序。

个人Hexo博客

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__', <class 'type'>)
('__delattr__', <slot wrapper '__delattr__' of 'object' objects>)
('__dict__', mappingproxy({'__module__': '__main__', 'a1': 1, 'a2': 2, '__init__': <function Foo.__init__ at 0x103714730>, 'f1': <function Foo.f1 at 0x10ff71b70>, 'f2': <classmethod object at 0x103722080>, 'f3': <staticmethod object at 0x103722048>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}))
('__dir__', <method '__dir__' of 'object' objects>)
('__doc__', None)
('__eq__', <slot wrapper '__eq__' of 'object' objects>)
('__format__', <method '__format__' of 'object' objects>)
('__ge__', <slot wrapper '__ge__' of 'object' objects>)
('__getattribute__', <slot wrapper '__getattribute__' of 'object' objects>)
('__gt__', <slot wrapper '__gt__' of 'object' objects>)
('__hash__', <slot wrapper '__hash__' of 'object' objects>)
('__init__', <function Foo.__init__ at 0x103714730>)
('__init_subclass__', <built-in method __init_subclass__ of type object at 0x101d72d88>)
('__le__', <slot wrapper '__le__' of 'object' objects>)
('__lt__', <slot wrapper '__lt__' of 'object' objects>)
('__module__', '__main__')
('__ne__', <slot wrapper '__ne__' of 'object' objects>)
('__new__', <built-in method __new__ of type object at 0x100921560>)
('__reduce__', <method '__reduce__' of 'object' objects>)
('__reduce_ex__', <method '__reduce_ex__' of 'object' objects>)
('__repr__', <slot wrapper '__repr__' of 'object' objects>)
('__setattr__', <slot wrapper '__setattr__' of 'object' objects>)
('__sizeof__', <method '__sizeof__' of 'object' objects>)
('__str__', <slot wrapper '__str__' of 'object' objects>)
('__subclasshook__', <built-in method __subclasshook__ of type object at 0x101d72d88>)
('__weakref__', <attribute '__weakref__' of 'Foo' objects>)
('a1', 1)
('a2', 2)
('f1', <function Foo.f1 at 0x10ff71b70>)
('f2', <bound method Foo.f2 of <class '__main__.Foo'>>)
('f3', <function Foo.f3 at 0x10ff71c80>)

getmembers的实现步骤

  1. 获取 object 的所有成员的名字,包含 object 的父类的成员,存入 names 列表

  2. 从 object 的基类中获取 DynamicClassAttribute 类型的成员,添加到 names 列表中

  3. 遍历 names 列表,通过 getattr 方法获取 object 中所有属性的值,getattr(x, ‘y’) 相当于 x.y

  4. 用 predicate 判断成员值,把通过判断的成员,以(成员名, 成员值)的形式添加到 results 这个列表中

  5. 对 results 列表按 成员名 进行排序

getmembers的源码

源码文件是 C:/Program Files/Python36/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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值