python操作符详解_操作符详解之成员测试(Python)

成员测试使用 in 和 not in 作为操作符。如果 x 是 s 中的一员,x in s 便会返回 True ;否则返回 False。x not in s与 x in s 的真值相反。所有内置序列(sequences)和集合(set)类型都支持成员测试;字典也支持该操作,不过字典将键(key)作为测试对象。对于容器类型(如 list、tuple、set、frozenset、dict 或 collections.deque),表达式 x in y 相当于 any(x is e or x == e for e in y)。

另外,对于 string 和 bytes 类型,仅当 x 是 y 的子串(substring)时,x in y 会返回 True。在这种情况下,成员测试等效于 y.find(x) != -1。由于空字符串被视作任何字符的子串,所以 "" in "abd" 将会返回 True。

对某个对象进行成员测试时,依据对象所持方法的不同,可分为如下三种情况:

第一种情况是在用户(user-defined)定义类中已定义了 __contains__() 方法。那么在进行成员测试时,便会调用该方法。x in y 与 y.__contains__(x) 的真值相同,也就是说如果后者返回 True,前者也会返回 True。

class Fib(object):

def __reset(self):

self.a = 1

self.b = 1

def __init__(self):

self.__reset()

def __contains__(self, item):

print("调用 __contains__")

self.__reset()

while True:

self.a, self.b = self.b, self.a + self.b

if item == self.a:

return True

elif item < self.a:

return False

def __reset(self):

self.a = 1

self.b = 1

a_fib = Fib()

print(3 in a_fib)

输出:

调用 __contains__

True

第二种情况是在用户定义类中并没有定义 __contains__(),但定义了 __iter__()。那么在执行 x in y 时,便会通过 __iter__() 对 y 进行迭代,如果在迭代过程中产生了与 x 相等的值,就会返回 True。在迭代过程中,只要确定存在与 x 相等的值,便会停止迭代,不会执行完全部的迭代过程。如果在迭代过程中引发了异常,则如同在成员测试中引发的异常一样。

class Fib(object):

def __reset(self):

self.a = 1

self.b = 1

def __init__(self):

self.__reset()

def __iter__(self):

"""测试该方法前,请删除__contains__"""

print("调用 __iter__()")

self.__reset()

return self

def __next__(self):

self.a, self.b = self.b, self.a + self.b # 计算下一个值

if self.a > 100000: # 退出循环的条件

print("停止迭代")

raise StopIteration()

return self.a # 返回下一个值

a_fib = Fib()

print(3 in a_fib)

输出:

调用 __iter__()

True

第三种情况是 __contains__()和 __iter__() 都没有定义,但定义了 __getitem__()。那么在执行 x in y 时,便会通过 __getitem__() 对 y 中各项逐一索引,仅当存在 x == y[i]( i 为非负整数)时,会返回 True。如果在迭代过程中引发了异常,则如同在成员测试中引发的异常一样。

tips:定义了 __getitem__() ,但没有定义 __iter__()时,会尝试使用旧式迭代协议,也就是通过 __getitem__() 逐一索引各个元素的方式,进行迭代。另外,我没有看懂文档中的这句话:"all lower integer indices do not raise IndexError exception. "

class Fib(object):

def __reset(self):

self.a = 1

self.b = 1

def __init__(self):

self.__reset()

def __getitem__(self, item):

"""测试该方法前,请删除__contains__和__iter__"""

self.__reset()

print("调用 __getitem__")

for x in range(item):

self.a, self.b = self.b, self.a + self.b

if self.a > 100000: # 退出循环的条件

print("停止迭代")

raise StopIteration()

return self.a

a_fib = Fib()

print(3 in a_fib)

输出:

调用 __getitem__

True

小结:综合以上三种情况,可见成员测试会优先使用 __contains__,如果没有定义该方法才会使用 __iter__(),如果前面两个方法都未定义才会尝试 __getitem__。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值