>>> class Thing(object):
... def __index__(self):
... return 1
...
>>> thing = Thing()
>>> list_ = ['abc', 'def', 'ghi']
>>> list_[thing]
'def'
>>> dict_ = {1: 'potato'}
>>> dict_[thing]
# KeyError
thing
は、リストからアクセスされたときに自分自身を1として表すことをどのように知っていますか?両方の魔法の方法は__getitem__
を通過しませんか?リストに示されている使用法は、代わりに__int__
を通過する可能性があるので、とにかく__index__
の-raisond'êtreは何ですか?
Dict andListは__getitem__
を同じように実装していません。 Dictオブジェクトは、オブジェクトの__eq__
の比較(__hash__
)を、__getitem__
で使用するキーとして使用します。
Thing
をdictで使用できるようにするには、hashとeqの両方を実装する必要があります。
@BenoîtLatinierは彼が言ったとき正しかった:
Dict and Listは_
__getitem__
_を同じように実装していません。
ただし、もう少し情報を追加したいと思います。 ドキュメント によると:
object.__index__(self)
operator.index()
を実装するために呼び出され、Pythonがスライスなどで数値オブジェクトを整数オブジェクト()に無損失で変換する必要があるときはいつでも、または組み込みのbin()
、hex()
およびoct()
関数)。このメソッドの存在は、数値オブジェクトが整数型であることを示します。整数。
太字の部分が重要です。リストのインデックス作成とスライスは、どちらも同じ方法(つまり、___getitem__
_)で処理されます。したがって、_Thing.__index__
_がスライスのために呼び出された場合、同じメソッドを使用しているため、同様にインデックス作成のために呼び出されます。この意味は:
_list_[thing]
_
ほぼ同等です:
_list_[thing.__index__()]
_
ただし、ディクショナリの場合、_Thing.__index__
_は呼び出されません(ディクショナリをスライスできないため、呼び出す理由はありません)。代わりに、_dict_[thing]
_を実行すると、Pythonは、辞書内でthing
インスタンス自体であるキーを見つけるように指示されます。これは存在しないため、KeyError
が発生します。
おそらく、デモンストレーションが役立つでしょう:
_>>> class Thing(object):
... def __index__(self):
... print '__index__ called!'
... return 1
...
>>> thing = Thing()
>>> list_ = ['abc', 'def', 'ghi']
>>> list_[thing] # __index__ is called
__index__ called!
'def'
>>>
>>> dict_ = {1: 'potato'}
>>> dict_[thing] # __index__ is not called
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: <__main__.Thing object at 0x01ACFC70>
>>>
>>> dict_ = {thing: 'potato'} # Works if thing is a key
>>> dict_[thing]
'potato'
>>>
_
そもそもなぜ___index__
_が存在するのか、その理由は PEP 0375 に徹底的に記載されています。ここではすべてを繰り返すことはしませんが、基本的には、任意のオブジェクトを整数として機能させるためです。これは、スライスやその他のいくつかのアプリケーションで必要です。
さらに理解するための別の例として、ここでは _ MolsToGridSVG リスト引数を取ります。リストをある程度の長さに制限したかったのです。ここでpythonリスト、スライスインデックスを使用する必要があります。次の実装で解決しました。基本的にここでインデックスはPythonリストに使用されています。
def __index__(self):
return 1
imagesInOneFile = int(len(smilesMolList) / noOfFiles)
svg = Draw._MolsToGridSVG(smilesMolList[:imagesInOneFile.__index__()], subImgSize=(400, 200), molsPerRow=2)
また、imagesInOneFile
は整数でなければならないことを覚えておく必要があります。