タプルを反転し、リストを反転すると、異なる型のオブジェクトが返されます。
>>> reversed((1,2))
<reversed at 0x7fffe802f748>
>>> reversed([1,2])
<list_reverseiterator at 0x7fffebdd4400>
彼らは同じdirです。どちらの型も他方のサブクラスではありません。
何故ですか?一方ができて他方ができないことは何ですか?
タプルを反転し、リストを反転すると、異なる型のオブジェクトが返されます。
>>> reversed((1,2))
<reversed at 0x7fffe802f748>
>>> reversed([1,2])
<list_reverseiterator at 0x7fffebdd4400>
彼らは同じdirです。どちらの型も他方のサブクラスではありません。
何故ですか?一方ができて他方ができないことは何ですか?
基本的に、リストは__reversed__メソッドを実装し、特殊なオブジェクトを返しますが、任意のシーケンスtupleのデフォルトの実装にフォールバックします:reversed
>>> list.__reversed__
<method '__reversed__' of 'list' objects>
>>> tuple.__reversed__
AttributeError: type object 'tuple' has no attribute '__reversed__'
さて、リストがデフォルトでシーケンス オブジェクトにならない理由はreversed、リスト オブジェクト自体のソース コードで見つける必要があります。おそらく、いくつかの内部list属性に直接アクセスすることで、いくつかの最適化が可能になります。
実際に C コードを見ると、違いはほとんどなく、特に目立ったものはありません。
特別なリストの実装は、 実際に他の Python シーケンスを a にコピーする__reversed__Python2 の時代の残り物 だと思います。タプルには十分でした)。reversedlistenumreverse
__reversed__のスロットをコメントアウトするだけ でlistobject.c、Python とそのリストが何も起こらなかったかのように機能し、デフォルトで一般的なケースになると確信していますreversed。
Pythonのドキュメントによると:
object.__reversed__(self)
reversed()逆反復を実装するために組み込みによって呼び出されます (存在する場合) 。コンテナー内のすべてのオブジェクトを逆の順序で繰り返す新しい iterator オブジェクトを返す必要があります。
__reversed__()メソッドが提供されていない場合、reversed()ビルトインはシーケンス プロトコル (__len__()および__getitem__()) を使用するようにフォールバックします。シーケンス プロトコルをサポートするオブジェクトは、__reversed__()によって提供される実装よりも効率的な実装を提供できる場合に のみ提供する必要がありreversed()ます。