为了完整起见,该in
运算符可以用作布尔运算符来测试属性成员资格。因此它可以在 if..else
声明中使用(请参阅下面的完整文档摘录)。
使用in
运算符时,(例如obj in container
)解释器首先查看是否container
有 __contains__
方法。如果没有,但如果container
定义了__iter__
方法,python 将迭代对象中包含的所有值并测试是否相等,即它基本上会执行类似的操作
for value in container:
if value == obj:
return True
return False
最后,如果两个方法都没有定义,解释器会寻找__getitem__
迭代容器的方法,并且仍然会测试任何值是否与obj
. 您还可以查看比较运算符文档。
现在,在您的情况下,range([start], stop[, step])
函数[documentation]实际上返回一个列表(请注意,此列表不包含最后一个元素 so range(1, 5) == [1, 2, 3, 4]
),它定义了__contains__
方法:
>>> type(range(1, 10))
list
>>> hasattr(list, '__contains__')
True
>>> 4 in range(1, 10)
True
所以这是完全授权写x in range(1, 10)
的。正如其他答案所指出的那样,您的问题实际上是通过将输入数据转换为整数来解决的类型问题(如"3" == 3
False 一样)。但是,如果您只打算测试输入值是否正确有界,我强烈建议您使用比较运算符
>>> if 1 <= x < 10:
... print 'ok'
... else:
... print 'ko'
因为它看起来更具可读性,并且您没有构建过时的列表,因此您可以最大限度地减少内存占用。
请注意,为了避免列表的隐式构造,您可以使用xrange
返回迭代器而不是列表的函数,并且在这种情况下,由于值是惰性求值的,xrange
它没有定义__contains__
方法,但它定义了__iter__
方法,所以一切仍然工作正常!
>>> type(xrange(1, 10))
xrange
>>> hasattr(xrange, '__contains__')
False
>>> hasattr(xrange, '__iter__')
True
>>> 4 in xrange(1, 10)
True
最后,这里是关于操作符的 python 文档的摘录in
运算符 in 和 not in 测试集合成员资格。如果 x 是集合 s 的成员,则 x in s 评估为 true,否则为 false。x not in s 返回 x in s 的否定。集合成员资格测试传统上与序列绑定。如果集合是一个序列并且包含与该对象相等的元素,则该对象是该集合的成员。但是,对于许多其他对象类型来说,支持成员资格测试而不是序列是有意义的。特别是,字典(用于键)和集合支持成员资格测试。
对于列表和元组类型,当且仅当存在索引 i 使得 x == y[i] 为真时,x in y 为真。
对于 Unicode 和字符串类型,当且仅当 x 是 y 的子字符串时,x in y 为真。等效测试是 y.find(x) != -1。注意,x 和 y 不必是同一类型;因此,'abc' 中的 u'ab' 将返回 True。空字符串总是被认为是任何其他字符串的子字符串,因此 "abc" 中的 "" 将返回 True。
在 2.3 版更改: 以前,x 必须是长度为 1 的字符串。
对于定义了__contains__
() 方法的用户定义类,x in y 当且仅当 y 为真。__contains__
(x) 是真的。
对于未定义__contains__
() 但定义__iter__
() 的用户定义类,如果在迭代 y 时产生具有 x == z 的某个值 z,则 x in y 为真。如果在迭代过程中引发异常,就好像引发了该异常。
最后,尝试旧式迭代协议:如果一个类定义了__getitem__
(),x in y 为真当且仅当存在一个非负整数索引 i 使得 x == y[i],并且所有小整数索引不会引发 IndexError 异常。(如果引发任何其他异常,就好像引发了该异常)。
运算符 not in 被定义为具有 in 的反真值。
运算符 is 和 is not 测试对象身份:当且仅当 x 和 y 是同一个对象时,x is y 为真。x is not y 产生逆真值。[7]