可由迭代器和索引访问的Python类

可由迭代器和索引访问的Python类,python,list,iterator,Python,List,Iterator,可能是一个n00b问题,但我目前有一个实现迭代器的类,因此我可以执行以下操作 for i in class(): 但是我希望能够通过索引访问类,就像 class()[1] 我该怎么做 谢谢 实施这两种方法等。来自@Ignacio Vazquez Abrams的电流足够。然而,对这个问题感兴趣的其他人可能会考虑从类中继承类(如在其中找到的类)。这可以做很多事情(): 确保将对象视为“像一个____;一样”所需的所有方法都存在 它是自文档化的,因为阅读您的代码的人能够立即知道您打算让您的对象“

可能是一个n00b问题,但我目前有一个实现迭代器的类,因此我可以执行以下操作

for i in class():
但是我希望能够通过索引访问类,就像

class()[1]
我该怎么做

谢谢

实施这两种方法等。

来自@Ignacio Vazquez Abrams的电流足够。然而,对这个问题感兴趣的其他人可能会考虑从类中继承类(如在其中找到的类)。这可以做很多事情():

  • 确保将对象视为“像一个____;一样”所需的所有方法都存在
  • 它是自文档化的,因为阅读您的代码的人能够立即知道您打算让您的对象“像一个____;一样”
  • 允许isinstance(myobject,SomeABC)正常工作
  • 通常自动提供方法,因此我们不必自己定义它们
(请注意,除上述内容外,创建您自己的
ABC
可以允许您测试任何对象中是否存在特定方法或方法集,并基于此声明该对象是
ABC
的子类,,即使该对象不是直接从
ABC
继承的)


示例:使用
ABC
现在作为一个例子,让我们为原始问题中的类选择并实现一个
ABC
。有两个要求:

  • 这门课太难了
  • 按索引访问类
  • 显然,这门课将是一种收藏。因此,我们要做的是查看我们的应用程序,以找到合适的
    ABC
    (请注意,也有)。适当的
    ABC
    取决于我们希望在类中使用的抽象方法

    如果我们想使用方法
    \uuu iter\uuu()
    ,我们看到an就是我们所追求的,这就是我们需要做的事情,比如在myobject中为o执行
    。但是,
    Iterable
    不包括方法
    \uuu getitem\uuuu()
    ,这是我们执行类似
    myobject[i]
    的操作所需要的。因此,我们需要使用不同的
    ABC

    在抽象基类的
    collections.abc
    菜单下,我们看到a是提供我们所需功能的最简单的
    abc
    。而且-你能看看吗-我们作为一个mixin方法获得了
    Iterable
    功能-这意味着我们不必自己定义它-免费!我们还得到了
    \u包含
    \u反向
    索引
    ,和
    计数
    。仔细想想,所有这些都应该包含在任何索引对象中。如果您忘记包含它们,代码的用户(可能包括您自己!)可能会非常恼火(我知道我会的)

    但是,还有第二个
    ABC
    ,它也提供了这种功能组合(可通过
    []
    访问):a。我们想用哪一种

    我们记得,要求能够通过索引(如
    列表
    元组
    )访问对象,即通过键(如
    dict
    )。因此,我们选择
    Sequence
    而不是
    Mapping


    侧栏:需要注意的是,
    序列
    是只读的(正如
    映射
    ),因此它不允许我们执行诸如
    myobject[i]=value
    random.shuffle(myobject)
    之类的操作。如果我们想做这样的事情,我们需要继续沿着
    ABC
    s的菜单并使用a(或a),这将需要实现几个额外的方法


    示例代码 现在我们可以上课了。我们定义它,并让它继承自
    序列

    from collections.abc import Sequence
    
    class MyClass(Sequence):
        pass
    
    如果我们尝试使用它,解释器将告诉我们在使用它之前需要实现哪些方法(请注意,这些方法也列在Python文档页面上):


    p.s.数据当然包含一个list属性,我可以做class().list[1]但是我可以做class()[1]吗?不相关,但是如果你像那样使用
    class
    ,你肯定会出错。你会发现Internetz上的一些Pythonistas似乎不喜欢将抽象类和方法作为语言的一部分(为了总结/模仿他们的推理,Python应该是“不是Java!”)。但是,它们似乎非常有用,所以我很高兴它们在那里。另外:请务必查看,它允许您创建自己的ABC。这似乎是Python 3特有的。感谢您指出这一点,我只是想实现索引,但我想我将继续使用ABC。非常方便!抽象基类在Python3中,ses从collections移动到collections.abc。在Python2中,只需使用
    from collections import Sequence
    ,您能提供一个如何实现这些的示例吗?
    >>> myobject = MyClass()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: Can't instantiate abstract class MyClass with abstract methods __getitem__, __len__
    
    from collections.abc import Sequence
    
    class MyClass(Sequence):
        def __init__(self,L):
            self.L = L
            super().__init__()
        def __getitem__(self, i):
            return self.L[i]
        def __len__(self):
            return len(self.L)
    
    # Let's test it:
    myobject = MyClass([1,2,3])
    try:
        for idx,_ in enumerate(myobject):
            print(myobject[idx])
    except Exception:
        print("Gah! No good!")
        raise
    # No Errors!