为什么Python3的范围/切片对象不支持其他范围/切片的包含测试?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么Python3的范围/切片对象不支持其他范围/切片的包含测试?相关的知识,希望对你有一定的参考价值。
Python3的范围对象支持对整数进行O(1)包含检查(1) (2)
因此,人们可以做15 in range(3, 19, 2)
并得到正确答案True
但是,它不支持包含检查b / w两个范围
a = range(0, 10)
b = range(3, 7)
a in b # False
b in a # False, even though every element in b is also in a
a < b # TypeError: '<' not supported between instances of 'range' and 'range'
似乎b in a
被解释为'a'范围内的任何元素等于对象'b'?
但是,由于范围不能包含除整数之外的任何内容,因此range(...) in range(...)
将始终返回False
。恕我直言,这样的查询应该像范围'a'中范围'b'中的每个元素一样被回答?鉴于该范围仅存储开始,停止,步长和长度,该查询也可以在O(1)中回答。
切片对象也没有帮助。它没有实现__contains__
方法,而__lt__
方法只是compares two slices as tuples(这没有意义)
目前这些实施背后有原因,还是只是“它碰巧以这种方式实施”的事情?
看起来__contains__
对范围的实现是range_contains,它只是检查给定元素是否在迭代中,具有longs的特殊情况。
如你所知,e in b
返回true iff e
是b
中的一个元素。任何其他实现,例如检查e
是否是b
子集的实现,都是不明确的。这在Python中尤其成问题,它不需要迭代是同构的,并且允许嵌套列表/元组/集/可迭代。
考虑一个实现所需行为的世界。现在,假设我们有以下列表:
my_list = [1, 2, (3, 4), 5]
ele1 = (3, 4)
ele2 = (2, 5)
在这种情况下,ele1 in my_list
和ele2 in my_list
应该返回什么?你想要的行为使得编写诸如此类的代码变得冗长乏味
if e in my_iterable:
# ah! e must exist!
my_iterable.remove(e)
更安全,更好的方法是保持当前行为,而是使用不同的类型敏感运算符来实现子集谓词:
x = set([1])
y = set([1,2])
x < y # True
[1] < y # raises a TypeError
你把'b' containing 'a'
和'a' being a subset of 'b'
搞混了 - 这是两件不同的事情。
b containing a
意味着range(0, 10)
在b
内。让我们说:
a = [1, 2, 3]
和
b = [1, 2, 3, 4, 5]
a in b
只有真正的名单[1, 2, 3]
在[[1, 2, 3], 4, 5]
才是真的。所以你实际上是在检查列表本身是否在另一个列表中,而不是所有元素都在另一个列表中。
如果a
的所有元素都在b
内,则列表a
是b
的子集。在你的例子中,b
是a
的一个子集,是的,但实际列表b
不是IN a
。
如果要执行此类方法,则可能建议您使用set数据结构
Range对象实现collections.abc.Sequence,它支持包含测试。
a in b
b in a
在这种情况下,您正在搜索范围b中的Range对象a,反之亦然。应该是假的。
以上是关于为什么Python3的范围/切片对象不支持其他范围/切片的包含测试?的主要内容,如果未能解决你的问题,请参考以下文章