You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中使用set作为成员名查找表相比list、dict的优势

问题背景

我在查阅Python标准库inspect.py模块的源码时,看到了如下getmembers函数的实现代码:

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()
    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
    try:
        for base in object.__bases__:
            for k, v in base.__dict__.items():
                if isinstance(v, types.DynamicClassAttribute):
                    names.append(k)
    except AttributeError:
        pass
    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):
            results.append((key, value))
        processed.add(key)
    results.sort(key=lambda pair: pair[0])
    return results

阅读源码后发现,代码中实例化set类作为已处理成员名的存储结构,后续通过if key in processed:语句执行键的存在性查找。
核心疑问:与list、dict等其他Python内置数据结构相比,使用set存储成员名并执行存在性查找具备哪些优势?

set用于该场景的优势
  • 查找效率是最核心的优势。set底层基于哈希表实现,做x in set这类存在性判断的平均时间复杂度是O(1),性能不会随着存储的元素数量增长出现明显下降。如果换用list存储已处理的key,每次查重都要从头遍历整个列表,平均时间复杂度是O(n),处理成员多、继承层级深的对象时,两者的性能差距会非常明显。
  • 场景语义匹配度更高。这段逻辑里我们只需要记录「哪些成员名已经被处理过」,不需要给每个名字绑定额外的关联值,也不需要在这个中间存储结构里维持元素顺序(最终返回的结果本来就要单独按名称做排序)。如果用dict虽然查找效率也能达到O(1),但必须给每个key硬塞一个无意义的value(比如统一存True),平白浪费内存,也不如set直接表达「已处理键的集合」这个含义直观。
  • 原生适配去重需求。这段代码本身就会在补录基类的DynamicClassAttribute时,往names列表里追加重复的键名,set天生就是存储不重复元素的结构,标记已处理键直接调用add()方法即可,不需要像操作list那样每次添加前额外做一次存在判断,代码更简洁,也不容易写出重复处理的逻辑bug。
  • 不存在使用限制。这个场景下存储的成员名都是字符串,属于Python内置的可哈希类型,完全满足set对元素的类型要求,不会触发类型错误。

内容的提问来源于stack exchange,提问作者BlueJupiter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 12:36:27