wbzxz 发表于 2023-6-22 20:48:30

请教关于in代偿的问题

本来魔法方法就够难啦, 还要加上代偿,真的很晕, 关于 in 语句 的代偿问题请教如下:

>>> class C:
        def __init__(self, data):
                self.data = data
                self.num = 'agcd'
        def __contains__(self, item):
                print('hi')
                return item in self.data

       
>>> c = C()
>>> 3 in c
hi
True

以上是正常调用代码:在使用in语句时(3 in c), 调用了魔法方法__contains__,其中 “ 3 对应参数 item”,“c 对应参数 self。



>>> class C:
        def __init__(self, data):
                self.data = data
                self.num = 'agcd'
        def __iter__(self):
                print('iter', end='->')
                self.i = 0
                return self
        def __next__(self):
                print('Next', end='->')
                if self.i == len(self.data):
                        raise StopIteration
                item = self.data
                self.i += 1
                return item

>>> c = C()
>>> 3 in c
iter->Next->Next->Next->True


以上是代偿代码一:主要的疑惑是,在使用in语句时(3 in c) , ”3"对应的是哪个魔法方法的哪个参数,“c“ 对应的是哪个魔方方法的哪个参数



>>> class C:
        def __init__(self, data):
                self.data = data
        def __getitem__(self, index):
                print('Getitem', end=' ')
                return self.data

       
>>> c = C()
>>> 3 in c
Getitem Getitem Getitem True
以上是代偿代码一:同样的疑惑是,在使用in语句时(3 in c) , ”3"对应的是哪个魔法方法的哪个参数,“c“ 对应的是哪个魔方方法的哪个参数

isdkz 发表于 2023-6-22 20:54:21

在Python中,对于表达式x in y ,解释器会先尝试调用 y 对象的__contains__()方法。如果 y 对象没有实现__contains__()方法,那么 Python 解释器会尝试使用其他方式来检查 x 是否在 y 中。

对于你的第二个和第三个例子, 3 in c将尝试使用__iter__()或__getitem__()方法作为代偿(fallback)的方式,因为你的类 C 没有定义__contains__()方法。

在第二个例子中,Python将调用 c 的 __iter__() 方法来得到一个迭代器,然后通过调用这个迭代器的 __next__() 方法来遍历 c 中的所有元素,直到找到等于3的元素,或者所有元素都被遍历完。这里,"3"对应的就是每次调用 __next__() 方法返回的元素,"c"对应的是调用 __iter__() 方法的对象。

在第三个例子中,Python将反复调用 c 的 __getitem__() 方法,每次将递增的整数(从0开始)作为索引参数,直到找到等于3的元素,或者 __getitem__() 抛出 IndexError 异常。在这个例子中,"3"对应的是每次调用 __getitem__() 方法返回的元素,"c"对应的是调用 __getitem__() 方法的对象。

所以,虽然这两个例子中的 3 in c 看起来和第一个例子一样,但是它们的工作方式实际上是完全不同的,因为它们分别使用了不同的方法来查找元素3。

陶远航 发表于 2023-6-22 21:07:34

in语句的魔法方法是contains,它定义了对象是否包含某个元素的行为。例如,如果你写了3 in c,那么Python会调用c.__contains__(3)来检查c是否包含3。

如果对象没有定义contains方法,那么Python会尝试使用iter或者getitem方法来代偿2。这两个方法都可以让对象支持迭代,也就是说可以用for循环遍历对象的元素。例如,如果你写了3 in c,而c没有定义contains方法,但是定义了iter方法,那么Python会调用c.__iter__()来获取一个迭代器,并且用next()函数来逐个检查元素是否等于3。如果c没有定义iter方法,但是定义了getitem方法,那么Python会调用c.__getitem__(0),c.__getitem__(1)等等来逐个检查元素是否等于3。

所以,在你的例子中:

代偿代码一中,”3"对应的是next()函数返回的元素,“c“ 对应的是c.__iter__()返回的迭代器。
代偿代码二中,”3"对应的是c.__getitem__(index)返回的元素,“c“ 对应的是c.__getitem__(0),c.__getitem__(1)等等返回的索引。
希望这能帮助你理解in语句的魔法方法和代偿机制。
页: [1]
查看完整版本: 请教关于in代偿的问题