リファクタリングをPythonで実践!基本手法とコード例・注意点まで
- 1.enumerate()関数とは?
- 2.enumerate()関数の使い方
- 3.enumerate()関数を使うときの注意点
- 4.for文と組み合わせて使う
- 5.さまざまなデータ型に使用する
- 6.ほかの関数と組み合わせて使う
Pythonのwhile文やfor文と合わせて学習しておくと便利な関数に、enumerate()関数があります。enumerate()関数のメリットや使い方をご紹介します。
1.enumerate()関数とは?
enumerate()関数は、Python標準の組み込み関数の一つで、Pythonの実行環境があればすぐに利用できます。
enumerate()関数を利用することで、for文内のループ処理にインデックス番号を付与できるのです。
enumerate()関数を使わない場合と使う場合で比較してみると、enumerate()関数のメリットを理解しやすいでしょう。
enumerate()関数なし |
|
enumerate()関数あり |
|
どちらの場合も出力は同じ結果で、以下のとおりになります。
結果
インデックス: 0 内容: 1番目
インデックス: 1 内容: 2番目
インデックス: 2 内容: 3番目
for文内でインデックス番号を利用する、という同じ目的に対して、enumerate()関数を利用する方が2行短く、またインデックス番号の制御も関数に任せられるので安心です。
2.enumerate()関数の使い方
enumerate()関数の基本的な使い方をご紹介します。
① 基本構文
enumerate()関数の引数には、配列やタプル、辞書型、文字型などが割り当てられます。
基本的な記述としては、
enumerate(配列など)
もしくは
enumerate(配列など, インデックス開始番号)
になります。
プログラムで様子を確認してみましょう。
my_text = 'まいど'
my_array = [ '1番目', '2番目', '3番目']
my_tuple = ('1番目', '2番目', '3番目')
my_dict = {'No.1': 'first', 'No.2': 'second', 'No.3': 'third'}
print( list(enumerate(my_text)) )
print( list(enumerate(my_array)) )
print( list(enumerate(my_tuple)) )
print( list(enumerate(my_dict, 100)) )
結果
[(0, 'ま'), (1, 'い'), (2, 'ど')]
[(0, '1番目'), (1, '2番目'), (2, '3番目')]
[(0, '1番目'), (1, '2番目'), (2, '3番目')]
[(100, 'No.1'), (101, 'No.2'), (102, 'No.3')]
enumerate()関数を使用することで、各データにインデックス番号を付与できていることが確認できます。
最後だけインデックスの開始番号が違いますね。また最後は辞書型で、この場合はキーの値を取得していることが確認できます。
② パラメーター(引数)
enumerate()関数には、第一引数と第二引数の2つを割り当てることができます。
第一引数は必須で、第二引数(インデックス開始番号)は任意になります。
第二引数がない場合は、インデックス番号が0からスタート。
また、第二引数を設定する場合は、整数(int)を割り当てる必要があります。
③ 戻り値
enumerate()関数の戻り値は、クラス型の列挙オブジェクトになります。
試しに配列型データをenumerate()関数で処理してみます。
my_array = ['first', 'second', 'third']
enumerate_obj = enumerate(my_array, 1)
print(type(enumerate_obj))
print(enumerate_obj)
結果
<class 'enumerate'>
<enumerate object at 0x7fadd8bddb90>
enumerate()関数だけでは出力内容がわからないですね。以下のように関数で処理した結果を展開するとデータとして扱いやすくなります。
my_array = ['first', 'second', 'third']
enumerate_obj = enumerate(my_array, 1)
my_obj = {}
for i, val in enumerate_obj:
my_obj[ 'No.' + str(i) ] = val
print(type(my_obj))
print(my_obj)
結果
<class 'dict'>
{'No.1': 'first', 'No.2': 'second', 'No.3': 'third'}
3.enumerate()関数を使うときの注意点
enumerate()関数は使い方を間違えていればエラーを出力してくれるので安心です。しかし、関数特有の処理内容を知っておくとより安心してプログラミングできるでしょう。
① 第一引数はイテラブルオブジェクトのみ利用可能
enumerate()関数を利用する際、第一引数に配列などのデータを割り当てますが、これはイテラブルオブジェクトである必要があります。
イテラブルオブジェクト・・・繰り返し処理可能なオブジェクト。
配列や辞書型、タプル型、文字型などはenumerate()関数で処理できますが、数値型、float型などの非イテラブルオブジェクトはenumerate()関数で処理できません。
② インデックス番号は1ずつ
一般的にはインデックス番号は、1ずつ上がることで要件を満たす場合が多いです。
しかし、まれに2ずつや3ずつインデックス番号を上げたいときもあるかもしれません。
その場合は、enumerate()関数で出力するインデックス番号とは別の数字を足す必要があります。
インデックス番号を1ずつ上げるケース |
結果
|
インデックス番号を3ずつ上げるケース |
結果
|
enumerate()関数に依存する変数iとは別の変数countを設けることで、3ずつインデックス番号を増やせていることが確認できます。
③ インデックス番号の変数を記述しない場合はタプル型に
一般的にenumerate()関数を使用する際は、インデックス番号用の変数 i などを使用します。
しかし、 変数i を使わない場合はどうなるでしょうか。サンプルコードで確認します。
my_array = [ '1番目', '2番目', '3番目']
for d in enumerate(my_array):
print( d )
結果
(0, '1番目')
(1, '2番目')
(2, '3番目')
enumerate()関数使用時にインデックス番号用の変数を使用しないときは、タプル型で出力されます。
インデックス番号用の変数を設定すべきかどうか検討する際に役立つでしょう。
4.for文を組み合わせて使う
enumerate()関数は、for文と組み合わせて使われることがほとんどです。サンプルコードを交えて様子をご紹介します。
① 基本構文
enumerate()関数をfor文と組み合わせて使う場合は、以下のように記述します。
my_array = ['first', 'second', 'third']
for i, val in enumerate(my_array):
print(type(i))
print(i)
print(type(val))
print(val)
print('------')
結果
<class 'int'>
0
<class 'str'>
first
------
<class 'int'>
1
<class 'str'>
second
------
<class 'int'>
2
<class 'str'>
third
------
2行目のfor文内で書かれているi や val 、 enumerate()の部分を確認すると以下のようになります。
インデックス用の変数は、今回は i を使用していますが、indexやcountなど任意の変数名を使用できます。
またインデックス番号のデータ型は数値型(int)で出力されますので、必要に応じて文字型(str)などに変換する必要があるでしょう。
② インデックスと要素を同時に取得
少量の配列データを確認するときなどは、インデックスと要素を同時に取得、表示する方法を知っておくと便利でしょう。
サンプルコードは以下のようになります。
my_array = [ '1番目', '2番目', '3番目']
for d in enumerate(my_array, 1):
print( d )
結果
(1, '1番目')
(2, '2番目')
(3, '3番目')
for文の行で、インデックス用の変数を割り当てなかった場合、インデックスと要素を同時に取得できていることが確認できます。
出力結果は、タプル型になっていることが確認できますね。カッコ内の左側がインデックス番号、右側が要素になります。
③ インデックスと要素を別々に取得
一般的にはenumerate()関数を使用する際は、インデックスと要素を別々に取得します。
my_array = ['first', 'second', 'third']
for i, val in enumerate(my_array, 1):
print( str(i) + ' ' + val )
結果
1 first
2 second
3 third
インデックスと要素を別々に制御することで、「このインデックス番号のときは、この処理をしたい」という制御が可能に。
enumerate()関数の代表的な使い方になりますので、ご自身でも実際にプログラムを書いて様子を確かめておきましょう。
5.さまざまなデータ型に使用する
インデックス番号を確認したい対象データは配列になる場合が多いですが、場合によっては辞書型や文字列などのインデックス番号も確認したいときがあるでしょう。
5つのデータ型をenumerate()関数で処理する様子をご紹介します。
① list(リスト)のインデックスと要素を取得
enumerate()関数の代表的な使い方ですね。
サンプルコード
my_array = ['first', 'second', 'third']
print(type(my_array))
for i, val in enumerate(my_array, 1):
print( str(i) + ' ' + val )
結果
<class 'list'>
1 first
2 second
3 third
② tuple(タプル)のインデックスと要素を取得
タプルのデータをenumerate()関数で処理する場合も、文法は同じです。
my_tuple = ('first', 'second', 'third')
print(type(my_tuple))
for i, val in enumerate(my_tuple, 1):
print( str(i) + ' ' + val )
結果
<class 'tuple'>
1 first
2 second
3 third
③ dict(辞書)のインデックスと要素を取得
辞書型をenumerate()関数で処理するとキーしか出力してくれません。
キーと対になる値も取得したい場合は、以下のようにプログラムを書きましょう。
my_dict = {'No.1': 'first', 'No.2': 'second', 'No.3': 'third'}
print(type(my_dict))
for i, val in enumerate(my_dict, 1):
print( str(i) + ' ' + val + ' : ' + my_dict[val])
結果
<class 'dict'>
1 No.1 : first
2 No.2 : second
3 No.3 : third
各インデックスの値(バリュー)は、元の辞書型データにキーを指定することで取得できます。(最終行のmy_dict[val]の部分)
④ set(集合)のインデックスと要素を取得
set型は、enumerate()関数の基本的な書き方で処理できます。
my_set = {'first', 'second', 'third'}
print(type(my_set))
for i, val in enumerate(my_set, 1):
print( str(i) + ' ' + val )
結果
<class 'set'>
1 third
2 second
3 first
⑤ str(文字列)のインデックスと要素を取得
文字列型をenumerate()関数で処理すると以下のようになります。
my_text = 'まいど'
print(type(my_text))
for i, val in enumerate(my_text, 1):
print( str(i) + ' ' + val )
結果
<class 'str'>
1 ま
2 い
3 ど
6.ほかの関数と組み合わせて使う
実際のデータ処理を行う場合、いくつかの配列をまとめて処理したい、というときがあります(zip関数)。また配列の並びを逆にして処理したい、というときもあるでしょう(reversed関数)。
こうした配列処理を行うzip関数やreversed関数を使用する場合も、enumerate()関数でインデックスを取得できます。
① zip()関数と組み合わせて複数取得
2つの配列を同時にenumerate()関数で処理してみます。
my_array_1 = ['香川', '沖縄', '北海道']
my_array_2 = ['うどん', 'ソーキそば', '札幌ラーメン']
for i, (prefucture, noodles) in enumerate(zip(my_array_1, my_array_2)):
print(i, prefucture, noodles)
結果
0 香川 うどん
1 沖縄 ソーキそば
2 北海道 札幌ラーメン
各都道府県の名物麺類が出力されましたね。
zip関数とenumerate関数を一緒に使う場合の注意点としては、各配列の要素数です。
2つの配列の要素数が異なる場合は、少ない要素数分だけ出力されます。
② reversed()関数と組み合わせて逆順に取得
配列の並びを逆さにするreversed関数とenumerate関数を同時に使用してみます。
my_array = ['first', 'second', 'third']
for i, val in enumerate( reversed(my_array), 1):
print( str(i) + ' ' + val )
結果
1 third
2 second
3 first
配列の並びが逆になって、インデックス表示されていることが確認できますね。