python __getitem__ 魔法方法

方法说明

在 Python 中,__getitem__ 是一个特殊方法(也称为魔术方法或双下方法),它定义了序列类型(如列表、元组、字符串等)的索引行为。当你尝试通过索引访问一个对象的元素时,Python 会调用这个方法。

__getitem__ 方法的作用是允许对象支持索引操作,例如使用方括号 [] 来获取或设置元素。这个方法通常在自定义类中被重写,以便实现类似列表或字典的行为。

__getitem__ 方法的基本语法如下:

python 复制代码
def __getitem__(self, key):
    # 实现索引逻辑
    pass

这里的 self 是类的实例,key 是用于索引的键(对于序列类型通常是整数索引,对于字典类型则是键值)。

示例:自定义序列类

下面是一个简单的示例,展示了如何在自定义类中重写 __getitem__ 方法来实现列表类似的行为:

python 复制代码
class MySequence:
    def __init__(self, elements):
        self.elements = elements

    def __getitem__(self, index):
        if index < 0 or index >= len(self.elements):
            raise IndexError("Index out of range")
        return self.elements[index]

    def __len__(self):
        return len(self.elements)

# 创建一个 MySequence 实例
my_sequence = MySequence([1, 2, 3, 4, 5])

# 使用索引访问元素
print(my_sequence[0])  # 输出: 1
print(my_sequence[2])  # 输出: 3

# 尝试访问不存在的索引
try:
    print(my_sequence[5])
except IndexError as e:
    print(e)  # 输出: Index out of range

在这个例子中,MySequence 类重写了 __getitem__ 方法来支持索引访问。我们还重写了 __len__ 方法来支持 len() 函数,这是一个好习惯,因为它允许用户知道序列的长度。

当你尝试访问 my_sequence 的元素时,例如 my_sequence[0],Python 会自动调用 __getitem__ 方法,并传入索引 0。如果索引有效,方法返回相应的元素;如果索引无效,方法可以抛出 IndexError 异常。

__getitem__ 方法是实现序列协议的关键部分,它使得自定义对象可以像内置的序列类型一样被索引。

简单示例

python 复制代码
class Demo:

    def __init__(self):
        self.arr = range(10)

    def __len__(self):
        return len(self.arr)

    def __getitem__(self, index):
        print("__getitem__ is call")
        if 0 <= index < self.__len__():
            return self.arr[index]


demo = Demo()
print(demo[0])
print(demo[3])
>>>
__getitem__ is call
0
__getitem__ is call
3

__getitem__和迭代器

在 Python 中,for 循环实际上是通过迭代器(iterator)来实现的,而迭代器是支持一些特殊方法的对象。这些特殊方法包括:

  1. __iter__(self):返回迭代器对象自身。这个方法使得对象成为一个可迭代对象(iterable),可以在 for 循环中使用。
  2. __next__(self):返回迭代器的下一个值。当迭代器耗尽时,抛出 StopIteration 异常,通知 for 循环停止迭代。

在 for 循环中,Python 会自动调用可迭代对象的 __iter__() 方法来获取一个迭代器对象,然后通过调用迭代器对象的 __next__() 方法来获取值,直到迭代器耗尽为止。这样就实现了循环遍历可迭代对象的功能。

除了以上两个方法,还有一个相关的魔法方法是 __getitem__(self, key),它可以让对象支持通过索引访问元素,但这种方式不是 for 循环的底层实现方式,而是用于支持序列(sequence)类型的对象。

总结:

__getitem__方法和迭代器没有任何关系。

__getitem__实现的索引访问元素是随机的,迭代器实现的访问是顺序的。

iter方法

通过iter方法将一个实例变成可迭代对象,next取值的时候,优先通过__next__取值,如果没有__next__方法则通过__getitem__方法取值。

存在__next__方法

python 复制代码
class Demo:

    def __init__(self):
        self.arr = range(10)
        self.index = 0

    def __len__(self):
        return len(self.arr)

    def __getitem__(self, index):
        print("__getitem__ is call")
        if 0 <= index < self.__len__():
            return self.arr[index]

    def __iter__(self):
        return self

    def __next__(self):
        print("__next__ is call")
        if self.index >= len(self.arr):
            raise Exception("超出范围")

        res = self.arr[self.index]
        self.index += 1
        return res


demo = Demo()
iter_demo = iter(demo)
print(next(iter_demo))
print(next(iter_demo))
>>>
__next__ is call
0
__next__ is call
1

没有__next__方法则使用__getitem__方法

python 复制代码
class Demo:

    def __init__(self):
        self.arr = range(10)
        self.index = 0

    def __len__(self):
        return len(self.arr)

    def __getitem__(self, index):
        print("__getitem__ is call")
        if 0 <= index < self.__len__():
            return self.arr[index]

    # def __iter__(self):
    #     return self
    #
    # def __next__(self):
    #     print("__next__ is call")
    #     if self.index >= len(self.arr):
    #         raise Exception("超出范围")
    #
    #     res = self.arr[self.index]
    #     self.index += 1
    #     return res



demo = Demo()
iter_demo = iter(demo)
print(next(iter_demo))
print(next(iter_demo))
>>>
__getitem__ is call
0
__getitem__ is call
1
相关推荐
青少儿编程课堂14 分钟前
蓝桥杯青少组图形化 STEMA 省考(报名倒计时·11/22开考)+ 全国青少年信息素养大赛 2026—2027赛季 + 电子学会图形化考级:校园华容道大闯关
c++·python·算法·bfs·信息学竞赛
特创数字科技22 分钟前
写了个 Windows 下载器:一键拉 GitHub / Gitee 源码,带 SHA256 校验
python·github
白杨尚青31 分钟前
C++进阶篇(五):红黑树——四条规则、三种插入情况与旋转变色
开发语言·数据结构·c++·stl·红黑树·平衡二叉树
.道阻且长.38 分钟前
Linux基本开发工具:gdb和cgdb的使用
linux·运维·服务器·开发语言
starzy19901 小时前
深入理解Scala匿名函数:函数式编程基石
开发语言·scala
郝学胜-神的一滴2 小时前
AI 编程智能体 27:吃透MCP通信机制
人工智能·python·langchain·wpf·numpy·scikit-learn
天天被压力2 小时前
【A股分钟级高频数据完全手册 #09】A股历史分时交易数据接口:普通分时怎么批量下
java·人工智能·python
天天被压力2 小时前
【A股分钟级高频数据完全手册 #10】股票实时行情数据接口Python:公开源实时交易取数
java·人工智能·python
apcipot_rain2 小时前
C++转Java日记(05)
java·开发语言·c++
apcipot_rain11 小时前
C++转Java日记(04)
java·开发语言·c++