N00bの質問かもしれませんが、私は現在、イテレータを実装するクラスを持っているので、次のようなことができます
for i in class():
しかし、私は同様にインデックスでクラスにアクセスできるようにしたい
class()[1]
どうやってやるの?
ありがとう!
__iter__()
と __getitem__()
などのメソッドの両方を実装します。
@Ignacio Vazquez-Abramsからの現在の 受け入れられた回答 で十分です。ただし、この質問に興味のある人は、 abstract base class(ABC
) ( 標準モジュール_collections.abc
_ )。これは多くのことを行います( おそらく他にもあります ):
isinstance(myobject,SomeABC)
が正しく機能するようにします。(上記に加えて、独自のABC
を作成すると、オブジェクト内の特定のメソッドまたはメソッドセットの存在をテストし、これに基づいてそのオブジェクトを宣言することができます。 ABC
のサブクラスであるオブジェクトがABC
directlyを継承しない場合でも。 この回答を参照詳細については。 )
list
を使用して、読み取り専用のABC
のようなクラスを実装する例として、元の質問のクラスにABC
を選択して実装しましょう。次の2つの要件があります。
明らかに、このクラスはある種のコレクションになります。そこで、 collection
ABCのメニュー を見て適切なABC
を見つけます( numeric
ABCs もあります)。適切なABC
は、クラスで使用する抽象メソッドによって異なります。
メソッド__iter__()
を使用したい場合、 Iterable
が後のものであることがわかります。これは、_for o in myobject:
_のようなことを行うために必要なものです。ただし、Iterable
にはメソッド__getitem__()
が含まれません。これは_myobject[i]
_のようなことを行うために必要なものです。したがって、別のABC
を使用する必要があります。
抽象基本クラスの_collections.abc
_メニューを見ると、 Sequence
が必要な機能を提供する最も単純なABC
であることがわかります。そして-あなたはそれを見ていただけますか-Iterable
機能をmixinメソッドとして取得します-つまり、自分で定義する必要はありません-無料です!また、___contains__
_、___reversed__
_、index
、およびcount
も取得します。考えてみると、これはすべてのshouldがインデックス付きオブジェクトに含まれているものです。あなたがそれらを含めるのを忘れていたなら、あなたのコードのユーザー(潜在的にあなた自身を含む!)はかなりイライラするかもしれません(私はそうするでしょう)。
ただし、2番目のABC
もあり、この機能の組み合わせ(反復可能で、_[]
_でアクセス可能)があります: Mapping
。どちらを使用しますか?
要件はオブジェクトにアクセスできることであることを思い出してくださいby index(list
やTuple
のような)、つまりnotby key(dict
のような)。したがって、Sequence
ではなくMapping
を選択します。
補足:Sequence
は読み取り専用(Mapping
と同様)であるため、_myobject[i] = value
_やrandom.shuffle(myobject)
のようなことはできません。そのようなことができるようにしたい場合は、ABC
sのメニューを続行し、 MutableSequence
(または MutableMapping
)を使用する必要があります。メソッド。
これでクラスを作成できます。定義し、Sequence
から継承します。
_from collections.abc import Sequence
class MyClass(Sequence):
pass
_
それを使用しようとすると、インタープリターは使用する前に実装する必要があるメソッドを教えてくれます(メソッドはPython docsページにもリストされていることに注意してください):
_>>> 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__
_
これは、先に進んで___getitem__
_および___len__
_を実装すると、新しいクラスを使用できるようになることを示しています。 Python 3:
_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!
_