質問するログイン新規登録

Q&A

解決済

2回答

1398閲覧

__getitem__メソッドを持っていないのに呼び出せるのはなぜか。

exnjinia

総合スコア16

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2023/06/11 16:52

編集2023/06/11 17:01

0

0

お聞きしたいこと

Python3.9を利用しています。
forループ中の__getitem__の挙動で質問です。

「初めてのPython(オライリー)」において、forループについて以下の解説がありました。

反復処理が行われる場合には、ビルトイン関数iterが呼び出されて、__iter__メソッドが探されます。__iter__メソッドが存在すれば、イテレータオブジェクトが戻されます。__iter__メソッドが存在しない場合には、__getitem__メソッドが使用されます。IndexError例外が発生するまで、インデクシングが繰り返し行われるのです。

そこで、試しに__getitem__メソッドを搭載したクラスを作成してみました。

Python

1class My_getitem: 2 def __getitem__(self, i): 3 print("__getitem__が呼ばれました") 4 if 2 < i: 5 raise IndexError 6 return i 7 8x = My_getitem() 9for i in x: 10 print(f'forの中です{i=}')

結果は以下のとおりです。

__getitem__が呼ばれました forの中ですi=0 __getitem__が呼ばれました forの中ですi=1 __getitem__が呼ばれました forの中ですi=2 __getitem__が呼ばれました

ここまでは解説通りであることが理解できました。

そこで、forループ内で呼び出されているというiter関数の挙動を確認したく、以下のコードを実行しました。

Python

1class My_getitem: 2 def __getitem__(self, i): 3 print("__getitem__が呼ばれました") 4 if 2 < i: 5 raise IndexError 6 return i 7 8x = My_getitem() 9y = iter(x) 10print(dir(x)) 11print(dir(y)) #yから__getitem__が消えている。 12for i in y: #yには__getitem__が存在しないはずだが、なぜか__getitem__を呼び出すことができている 13 print(f'forの中です{i=}')

結果は以下のとおりです。

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__'] ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__length_hint__', '__lt__', '__ne__', '__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__'] __getitem__が呼ばれました forの中ですi=0 __getitem__が呼ばれました forの中ですi=1 __getitem__が呼ばれました forの中ですi=2 __getitem__が呼ばれました

ここでお聞きしたいのですが、なぜオブジェクトyには__getitem__メソッドが存在しないのに、forループ内で呼び出すことができるのでしょうか。
forループの内部で何が起こっているのか教えていただけないでしょうか。
よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

guest

回答2

0

ベストアンサー

y__iter____next__から、x__getitem__が呼び出されています。

組み込み関数iter()のリファレンスの説明参照。

投稿2023/06/11 17:40

otn

総合スコア86645

exnjinia

2023/06/12 13:12

回答ありがとうございました! もうお一方が書いてくださっていたnext(y)の実行結果と併せて確認したことで、「y」の__iter__や__next__から、「x」の__getitem__が呼び出されているということを実感しました。
guest

0

PEP 234 – Iterators – Python API Specification

The two methods correspond to two distinct protocols:

  1. An object can be iterated over with for if it implements __iter__() or __getitem__().
  2. An object can function as an iterator if it implements next().

y はイテレータなので(y = iter(x))、__iter__() メソッドが存在します。

python

1>>> y.__iter__ 2<method-wrapper '__iter__' of iterator object at 0x7f9513d96a40> 3>>> next(y) 4__getitem__が呼ばれました 50

投稿2023/06/11 18:11

melian

総合スコア21745

exnjinia

2023/06/12 13:01

ありがとうございました! 動作結果も記載いただいて大変分かりやすかったです!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.25%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問