鱼C论坛

 找回密码
 立即注册
查看: 1653|回复: 4

[已解决]请教关于in代偿的问题

[复制链接]
发表于 2023-6-22 20:48:30 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本来魔法方法就够难啦, 还要加上代偿,真的很晕, 关于 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([1, 2, 3, 4, 5])
>>> 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]
                self.i += 1
                return item

>>> c = C([1, 2, 3, 4, 5])
>>> 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[index]

        
>>> c = C([1, 2, 3, 4, 5])
>>> 3 in c
Getitem Getitem Getitem True
以上是代偿代码一:同样的疑惑是,在使用in语句时(3 in c) , ”3"对应的是哪个魔法方法的哪个参数,“c“ 对应的是哪个魔方方法的哪个参数
最佳答案
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。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 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 22:23
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 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语句的魔法方法和代偿机制。

点评

非常感谢您的指点,在您的指点下受益匪浅。  发表于 2023-6-22 22:23
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-9-22 17:27

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表