『Python入門』for文とin演算子でrangeオブジェクトを操ろう

Python プログラミング Python

ここではfor文のループに使うrangeについての解説と、使い方を簡単なコードを通して解説していきます。

range関数とは

range は組込み関数でインポートをしなくても呼び出すことのできる関数です。

イミュータブルな整数のシーケンスを表すことができ、一般的にfor文において指定した回数のループをさせるために使われます

Python2ではrange関数はlist型のオブジェクトを返していましたが、Python3からrange型のオブジェクトを返すようになりました。

range型のオブジェクトはジェネレータオブジェクトとも言い、イテレータの一種になります。ジェネレータオブジェクトは要求されるごとに処理を実行して要素を作成できます。

Python2ではrange関数でリストオブジェクトを作成していたため、大きなリストオブジェクトになるとメモリを消費する問題がありましたが、Python3からはジェネレータオブジェクトを作成するようになったため、1つの要素しか返さなくなり、メモリの使用量が軽減されるようになりました。

Pyhon2にはジェネレータオブジェクトを返すxrange関数がありましたが、range関数に機能がまとめられたため、Python3では使うことが出来ません。そしてrange関数でリストオブジェクトを返すことが出来なくなったので、リストオブジェクトを返したい場合はlist関数による変換が必要になりました。

Python2

range関数の戻り値はlist型のオブジェクトになります。

xrange関数を利用でき、戻り値はxrange型のオブジェクトになります。

 

Python3

Python3では、range関数の戻り値はlist型ではなくrange型のオブジェクトになります。

list型のオブジェクトにするにはlist関数でキャストする必要があります。

また、xrange関数は定義されていない為エラーになります。

 

range関数の引数

range関数に指定した引数を基に、シーケンシャルなrange型のオブジェクトを作成します。引数にはstart、stop、stepを指定でき、それぞれの引数には整数のみが指定可能となります。

またstopは必須となり、stepを指定したい場合は、全ての引数を指定する必要があります。

start 開始 指定しない場合、デフォルトの0
stop 終了 必須。
指定しない場合エラー(TypeError)
stepがプラスの場合は、startより大きい値、stepがマイナスの場合、startより小さい値を指定。
step 増減の量 指定しない場合、デフォルトの1
指定する場合、全ての引数を指定する必要がある。
0を指定した場合はエラー(ValueError)

上記の制約を満たさない場合はrange型のオブジェクトは作成されますが、要素は空となります

1行目:第1引数(start)に10、第2引数(stop)に1を指定しているため要素のない空のrange型のオブジェクトを生成。

4行目:実際に空のオブジェクトなのかをindexに0を指定して参照すると「範囲外のインデックスですよぉ」エラー発生。

9行目:わかりやすくlist型にキャストすると、空のリストを生成。

 

range関数の引数の渡し方には2通りあります。

range(stop)
range(start, stop[, step])
 
range(stop)
stopのみを指定した場合です。
start が指定されていないのでデフォルトの 0 が start になります。
stepが指定されていないのでデフォルトの 1 を増加する値とします。
これにより、0 から stop で指定した数値の1つ前までの連続したrange型のオブジェクトを返します。

range型のオブジェクトの各要素をリストで確認してみましょう。

1行目:range型のオブジェクトを変数rに代入

2行目:変数rがrange型であることをtype関数で確認

4行目:変数rがrange型のオブジェクトであることを確認

6行目:range型のオブジェクトをlist関数でlist型のオブジェクトにキャスト

リストの要素が、0から4までの連続した数値であることが分かります。

 

range(start, stop[, step])
startからstopで指定した数値までの連続したrange型のオブジェクトを返します。
stepを指定することで、増減の量を指定できます。
stepは必須ではないので、指定しない場合は増減の量はデフォルトの1となります。
range型のオブジェクトの各要素をリストで確認してみましょう。

stepを指定しない場合:

startに1、stopに5を指定しているので、1から5を超えない範囲で連続する値を要素に持つリストを生成します。stepを指定しない場合はデフォルトで増減は1になります。


stepを指定した場合:

startに1、stopに10、stepに2を指定しているので1から10を超えない範囲で2つづつ増加する値を要素に持つリストを生成します。

 

rangeでループする仕組み

range関数は、「イミュータブルな整数のシーケンスを表す」と言いました。

for文の演算子inでrange型のオブジェクトであるジェネレータオブジェクトの要素を1つづつ取得しながらループしています。

「演算子in」については、以下の記事を参考にしてください。

『Python入門』if文の演算子inを使っていろいろなオブジェクトを比較してみた
ここではPythonのif分の条件式のうち、「演算子in」について解説します。 「演算子in」を使えば、いろいろな型のオブジェクトを比較できるようになります。 また、for文でも同じく「演算子in」が使われるので、ここで基本を身に付けち...

では、簡単な実例で見て行きましょう。

 

range(stop)の実例

ループを5回行う場合を見ていきます。

コードとしては以下になります。

では順番に見ていきます。

1. range関数の引数で指定した条件を基に、range型のオブジェクトが作成されます。

type関数で型を確認するとrange関数で作成されるオブジェクトは、range型のオブジェクトであることが分かります。list関数でリストにキャストすると0から4まで連続する値を要素に持つリストであることが分かります。すなわちインデックスを指定することで各要素の値に参照できることが出来ます。

 

2. 作成されたオブジェクトの要素の数だけループする。

演算子inでrange型のオブジェクトに所属する要素を順番に取得していきます。

オブジェクトに所属する要素の数をlen関数で確認すると、要素数は5であるることが分かります。

このことから演算子inでは5つの要素を取得するまでfor文でループすることになります。

range(0, 5)だったので、0~4の要素を持つので要素数は5

 

3. range型のオブジェクトの要素を要素数分ループして取得

作成したrange型のオブジェクトの要素数は5であることが分かりました。

これによりfor文によるループが5回行われることになります。

作成されたオブジェクトはrange型であり、シーケンス型の1つになります。

シーケンス型はオブジェクトの要素はindexで参照することが出来ます。

演算子inはシーケンス型のオブジェクト(range型のオブジェクト)の要素を順番にindexで参照します。

このことから、range型のオブジェクトの要素数分だけfor文でループしながら、演算子inでrange型のオブジェクトの要素を順番に取得していきます。

以下は作成したrange型のオブジェクトの要素をindexを指定して順番に5回取得しています。

このように、range関数からオブジェクトを作成し、オブジェクトの要素の数だけ、要素を順番取得しながらループする流れになっています。

 

range(start,stop,step)の実例

1から10の間で2ずつ増加させてみましょう。

コードとしては以下になります。

stopのみを指定した例と動きはほとんど同じなので簡単に説明します。

range関数でrange型のオブジェクトを作成します。start,stop,stepが指定されているので、この条件により(1,3,5,7,9)の5つの要素が取得できるオブジェクトになります

このrange型のオブジェクトを演算子inで順番にindexを指定することで要素数分のループを行いながらrange型のオブジェクトの要素を取得しています。

 

オブジェクトの要素数分ループさせる

オブジェクトの要素数分のループをしたい場合があります。

普通にオブジェクトを渡してループさせて要素を1つづ取得する方法の他に、range関数でオブジェクトのindexを1つづつ取得していく方法があります。range関数を使ってindexを取得していきたい場合はlen関数で要素数を取得してrange関数に渡します。この数値がstopとなります。

リストのオブジェクトを例に実際に違いを見てみましょう。

リストオブジェクトの要素を取得:

 

リストオブジェクトのindexを取得:

 

まとめ

range関数は引数に指定した条件を基に連続した整数を返すことができるのでfor文との相性が良さそうですね。

また、Pyhon3からはリストオブジェクトではなく、range型のオブジェクト(ジェネレータオブジェクト)を返すため、メモリーの使用量についても気になることがなくなりました。

ただし、Python2ではリストオブジェクトが返るので注意が必要ですね。

range関数には負数を渡すことも出来るので色々試してみましょう。

 

タイトルとURLをコピーしました