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

如何在Python中扩展List类以支持整数/布尔列表式索引

扩展Python List类支持整数/布尔列表索引

你说得太对了!Python里的方括号[]操作,底层就是调用__getitem__(读取)和__setitem__(赋值)这两个特殊方法,继承list类后重写它们,完全是实现你需求的正确方向。咱们一步步来看你的实现过程和优化点:

最初代码的问题

你一开始写的版本有两个关键bug:

  • __getitem__里的循环直接return self[i],会在第一次循环就返回结果,只能拿到第一个索引对应的元素,而不是所有索引的集合
  • __setitem__的else分支里写错了变量,应该是list.__setitem__(self, index, item),而不是self[i] = item(这里的i是循环里的变量,else分支里根本不存在)

第一步:修复__getitem__实现

你后来修改的__getitem__思路很正确:调用父类的list.__getitem__来避免递归调用自己的方法,然后遍历索引列表收集所有结果返回,这样就能正常获取多个索引对应的元素了:

def __getitem__(self, index):
    if type(index) is list:
        res = [None]*len(index)
        for i,v in enumerate(index):
            res[i] = list.__getitem__(self, v)
        return res
    else:
        return list.__getitem__(self, index)

第二步:修复__setitem__实现

同样的,你修改后的__setitem__通过循环遍历索引和值的配对,调用父类方法逐个赋值,这就解决了批量赋值的问题:

def __setitem__(self, index, value):
    if type(index) is list:
        for i,v in zip(index, value):
            list.__setitem__(self,i,v)
    else:
        list.__setitem__(self,index,value)

第三步:添加布尔列表索引支持

你把布尔列表转换成对应的整数索引的思路非常巧妙——先筛选出True对应的位置索引,然后复用已有的整数列表索引逻辑,这样不用重复写赋值/读取的代码。不过这里可以提个小优化:用isinstance()代替type()会更灵活,比如能兼容布尔值的子类(虽然实际场景很少,但更符合Python的鸭子类型思想)。

最终完整实现

class MyList(list):
    def __getitem__(self, index):
        if isinstance(index, list):
            if index and isinstance(index[0], bool):
                # 把布尔列表转换为整数索引列表
                int_indices = [i for i, val in enumerate(index) if val]
                return self[int_indices]
            elif index and isinstance(index[0], int):
                res = []
                for idx in index:
                    res.append(list.__getitem__(self, idx))
                return res
        # 其他情况调用父类方法
        return list.__getitem__(self, index)

    def __setitem__(self, index, value):
        if isinstance(index, list):
            if index and isinstance(index[0], bool):
                # 布尔列表转整数索引后复用逻辑
                int_indices = [i for i, val in enumerate(index) if val]
                self[int_indices] = value
            elif index and isinstance(index[0], int):
                for idx, val in zip(index, value):
                    list.__setitem__(self, idx, val)
        # 其他情况调用父类方法
        list.__setitem__(self, index, value)

测试验证

咱们用你给出的测试案例验证一下:

# 测试整数列表索引
list1 = MyList(['a','b','c','d','e'])
list2 = MyList(['A','B','C','D','E'])
index1 = [0,1,3]
index2 = [1,2,4]
list1[index1] = list2[index2]
print(list1)  # 输出: ['B', 'C', 'c', 'E', 'e']

# 测试布尔列表索引
list1 = MyList(['a','b','c','d','e'])
index_bool1 = [True,True,False,True,False]
index_bool2 = [False,True,True,False,True]
list1[index_bool1] = list2[index_bool2]
print(list1)  # 输出: ['B', 'C', 'c', 'E', 'e']

完全符合你的预期结果!

额外小提示

  • 处理布尔列表时,要确保布尔列表的长度和原列表一致,否则会出现索引越界的问题
  • 用isinstance(index, list)比type(index) is list更健壮,因为它能识别继承自list的子类对象

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:04:53