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