python';当它通过`u getitem `(`';触发时,` in`函数工作;?

python';当它通过`u getitem `(`';触发时,` in`函数工作;?,python,membership,Python,Membership,指示python首先尝试通过\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。 例如: 链接文档表明,如果存在任何非负索引i,使得x[i]==y,则结果为TrueelseFalse。 它如何在所有这些i上执行搜索?对“所有”正数的线性遍历似乎是不可能的。线性遍历必须有一定的界限(对

指示python首先尝试通过
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。
例如:

链接文档表明,如果存在任何非负索引
i
,使得
x[i]==y
,则结果为
True
else
False

它如何在所有这些
i
上执行搜索?对“所有”正数的线性遍历似乎是不可能的。线性遍历必须有一定的界限(对于列表,它应该是0到len()。这些界限是如何确定的

这就是它的工作原理。下面是一个使用
列表的演示:

$ for a in `seq 6`; do python3 -m timeit -s "a = 10**$a" 'a in list(range(a))'; done
1000000 loops, best of 3: 0.84 usec per loop
100000 loops, best of 3: 3.04 usec per loop
10000 loops, best of 3: 57.7 usec per loop
1000 loops, best of 3: 639 usec per loop
100 loops, best of 3: 6.74 msec per loop
10 loops, best of 3: 70.3 msec per loop
您可以观察到时间复杂度随着容器的大小成比例增加

它如何在所有这些
i
上执行搜索

这在很大程度上取决于执行搜索的对象的数据结构。例如,如果您有一个
列表
对象,则成员身份检查的复杂度为O(n),如果您有一个使用哈希表访问其项(如dictionary或set的
\uuuuu getitem\uuuuu
属性)的数据结构,则复杂度约为O(1)


因此,一般来说,对于用户定义的对象,它可以按照文档中的说明工作。对于没有哈希表的对象,它是线性搜索;对于有哈希表的对象,它是常量搜索

这些特殊方法的目的是为数据结构的设计者提供一种适合您情况的快速查找方法。例如,您可以从
列表
派生一个类,该类通过反向索引进行增强,以便按值快速查找。(显然,这会降低插入速度,因为索引需要更新,但让我们假设您将进行大量查找,因此您知道这是值得的。)


如果您的类无法改进默认访问,则不需要定义特殊方法。Python将依赖于任何可用的工具,包括顺序搜索。

aah,我想我能得到它。。。您想知道如何获得密钥来迭代自定义容器上既没有
\uuuuu contains\uuuuuu()
也没有
\uuuuuuu iter\uuuuuuu()
的所有元素-很简单,它完全使用线性迭代,直到遇到为止,如文档中所述:

。。。如果一个类定义了
\uu getitem\uu()
y中的x
True
当且仅当存在一个非负整数索引
i
,使得
x==y[i]
所有较低的整数索引都不会引发
索引器
异常。(如果引发任何其他异常,就好像在引发该异常一样)

例如:

class CustomClass(object):

    def __getitem__(self, item):
        if item > 20:  # lets force the break so that it doesn't go to sys.maxsize
            raise IndexError()
        print(item)  # print the item requested
        # implied: return None so it doesn't match 5

result = 5 in CustomClass()  # this will keep printing numbers until 20

没有
\uuuu的对象的迭代包含\uuuu
\uuuu iter\uuuu
。序列扫描发生。使用
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu,所以问题不存在了。线性遍历的替代方法是什么?魔法?@moooeeep当我想到这个问题时,我指的是。请参见页面上的
class IndexableNode
。它以
0
开始并不断添加
1
,直到找到项目或获得
索引器。如果它得到一个
索引器
,它将停止并返回
False
,但问题不在于列表,因为
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu包含
是为列表明确定义。这是自定义类。是的,这句话本身我并不清楚。既然你这么说,我看起来很傻:(
class CustomClass(object):

    def __getitem__(self, item):
        if item > 20:  # lets force the break so that it doesn't go to sys.maxsize
            raise IndexError()
        print(item)  # print the item requested
        # implied: return None so it doesn't match 5

result = 5 in CustomClass()  # this will keep printing numbers until 20