getitem 方法被添加到 Python 中,作为序列和映射协议的一部分。通过这个魔术方法,标准集合(如列表、元组、字典等)支持通过索引、键和切片访问。在用户定义的类中,该方法允许对象表现得像“集合”。
没有实现 getitem 的用户定义类不支持索引和 for 循环迭代。如果只为简单的索引实现该方法,则在希望完整支持切片时是不适用的,而忽略不同类型的索引会导致错误。
实现 getitem 来支持索引和切片对象,并将其处理分开。这允许在标准 Python 结构中使用用户定义的对象(例如,支持切片 your_obj[1:5])。
代码示例:
class MyRange: def __init__(self, n): self.n = n def __getitem__(self, item): if isinstance(item, int): # 单个索引 if 0 <= item < self.n: return item * 2 raise IndexError('索引超出范围') elif isinstance(item, slice): # 切片 return [self[i] for i in range(*item.indices(self.n))] else: raise TypeError('无效的参数类型:{}'.format(type(item))) mr = MyRange(10) print(mr[3]) # 6 print(mr[2:5]) # [4, 6, 8]
关键特点:
仅实现 getitem 是否可以通过索引赋值?
不可以。为了支持赋值(your_obj[i] = value),需要实现 setitem。getitem 仅负责读取。
getitem 是否必须像列表那样在切片上返回列表?
不可以。主要是返回“序列”,考虑到类的含义(可以返回相同类型或例如,元组)。最重要的是,这在上下文中是有意义的。
为什么有时会出现 TypeError 错误:'MyClass' 对象不可下标?
如果您尝试执行 my_obj[0],而类没有实现 getitem,就会出现该消息。为了使类可下标(支持 []),该方法是必须的。
只为 int 实现了 getitem,忘记了切片。任何尝试 my_obj[2:5] 的行为都会导致 TypeError 并导致整个集合处理算法失败。
优点:
缺点:
getitem 已经实现了单独处理 slice 和 int。切片和索引有效,list()、map() 和迭代方法在没有额外努力的情况下得到支持。
优点:
缺点: