
武蔵野個別指導塾の特徴
高校情報I 配列と添字—位置と値を分けて端の要素まで安全に取り出す|武蔵野個別指導塾

棚の在庫から指定位置を読み、0始まりの添字と要素数の違いを空リストや範囲外の例で確かめます。
よくあるのは、高校生が要素数と最後の添字を同じにする場面です。棚に4種類の品物が並ぶと、最後を4番と呼びたくなります。しかし、先頭の位置を0とする約束なら、最後の位置は3です。位置と個数を別の量として書き出すと、端の取り違えを防げます。
何を入力し、何を返すか
配列は順序を持つ値の集まりとして考えます。ここではPythonのリストを使い、棚の各区画の在庫数を先頭から記録します。区画の位置は0から始まり、各値はその区画の個数です。実際の棚に貼る番号が1から始まるなら、取り出しの前に対応を決めなければなりません。
問われ方には、指定された位置の値を読む型、先頭や末尾の添字を求める型、範囲外の指定を安全に扱う型があります。いずれも最初に長さと起点を確認します。値が同じ区画があっても、位置が同じとは限りません。取り出しは位置指定であり、値を探す処理ではないので、同値の優先や未発見の位置は必要ありません。
以下の取り出しでは、位置は整数、在庫は整数のリストとします。空リストを許し、有効な位置なら在庫の整数を返します。負の位置や長さ以上の位置なら「範囲外」を返します。Pythonには負の添字で末尾から数える機能がありますが、ここでは使いません。範囲外を表す文字列と在庫の整数は型で区別できます。
位置の列と値の列を重ねる
長さは要素の個数で、Pythonでは len で得ます。長さを n とすると、0始まりの有効な添字は0以上n未満です。空でなければ最後はnから1を引いた位置です。長さ0のとき、この式を使って存在する末尾を表すことはできません。要素そのものがないからです。
図1のように、添字は上段、在庫数は下段に置きます。添字2に対応する値は8です。値8を添字として読み直す必要はありません。

図1の4区画は0、1、2、3の順です。長さ4は区画の数であり、添字4に区画があるという意味ではありません。リストを横に描き、添字を先に振る方法は、値が0や3のように添字と似ていても混同しないために役立ちます。
空リストでは長さが0なので、0以上かつ0未満の整数はありません。単一要素なら長さ1、有効な添字は0です。二つの場合を比べると、先頭の0さえ常に有効とは限らないことが見えます。範囲の確認は取り出しより先に行います。
基本例題:棚の指定位置を読む
棚の在庫を [6, 3, 8, 5] とします。位置は0始まりです。位置2の在庫を整数で返し、位置が範囲外なら文字列「範囲外」を返してください。空リストも入力できます。手で見ると位置0が6、位置1が3、位置2が8なので期待値は8です。
図2のように、長さ4と位置2を比較してから、対応する箱を読みます。図2の矢印は位置2から値8への対応を表します。

def stock_at(stock, pos):
n = len(stock)
if 0 <= pos < n:
return stock[pos]
return "範囲外"
print(stock_at([6, 3, 8, 5], 2))
1行目でリストと位置を受け取る関数を定義します。2行目は要素数をnに記録します。3行目は位置が0以上で、同時にn未満かを判定します。真なら4行目でその位置の値を返し、偽なら5行目へ進んで文字列を返します。最後の行は返された値を表示します。
入力が上記のとき、nは4、判定は真、返り値は8です。Python 3.15.0で実行した出力も 8 です。元の棚に戻して位置0から数えると3区画目が8で、期待値と一致します。位置が2という整数と、取り出した8という整数は別の役割です。
この判定は空リストにも適用できます。nが0なら位置0は0未満ではないため、添字の参照に進みません。一方、Pythonのリストに存在しない正の添字を直接指定するとIndexErrorが発生します。先に範囲を調べる目的は、例外が出てから偶然処理を続けることではなく、仕様に沿った返り値を用意することです。
端と範囲外を並べて試す
同じ関数に対し、次の自作入力を試します。表の「期待」は手で先に決めた返り値、「実際」はPython 3.15.0の出力です。各行は独立した呼出しで、リストは変更しません。
リスト 位置 期待 実際
[6, 3, 8, 5] 0 6 6
[6, 3, 8, 5] 3 5 5
[9] 0 9 9
[4, 4] 1 4 4
[] 0 範囲外 範囲外
[9] 1 範囲外 範囲外
[6, 3, 8, 5] -1 範囲外 範囲外
[4, 4] 2 範囲外 範囲外
前半の4行は成功する指定です。先頭、末尾、単一要素、重複を含むリストを調べています。重複の行では位置1の値を返します。位置0にも同じ値があることは、位置1を指定する規則に影響しません。
後半の4行は失敗する指定です。空リスト、単一要素の直後、負の位置、長さに等しい位置を調べています。どれも範囲外を返し、リストを参照しません。Pythonで負の添字を直接使うと末尾を取り出せるため、負を拒む条件が特に重要です。数例が通ることと一般に正しいことは別です。位置が0以上n未満なら定義上その要素が存在し、それ以外なら参照前に拒むという場合分けが成立の理由です。
応用:人が数える棚番号を変換する
棚の案内に1から始まる番号を使う場合を考えます。棚番号1は添字0に対応し、番号から1を引くと添字になります。在庫 [7, 2, 10] に対して棚番号3を指定し、在庫を整数で返してください。番号が1未満または区画数を超える場合は「範囲外」です。番号は整数とします。
def shelf_at(stock, number):
pos = number - 1
return stock_at(stock, pos)
print(shelf_at([7, 2, 10], 3))
このコードは先ほど定義した stock_at と同じプログラム内に置きます。1行目は棚番号を受け取る関数、2行目は0始まりの位置への変換、3行目は検査と取り出しの委譲です。最後の行では番号3から位置2となり、長さ3のリストの最後の値10を返します。期待値も実際の出力も 10 です。棚番号を振り直すと1、2、3の3番目が10なので、場面にも戻せます。
番号0は位置-1、番号4は位置3となり、どちらも「範囲外」です。空の棚に番号1を指定しても位置0は無効です。番号の変換と範囲判定を別の段階として考えると、1始まりと0始まりの約束を途中で混ぜずに済みます。
少し難しい例:入力の型も確認する
位置が整数という前提を外すと、文字列や小数を比較した時点で例外が起こり得ます。外から渡される値を扱う場合は、整数型かどうかも参照前に確かめます。ここでは真偽値を位置として認めず、整数以外は「型エラー」、整数だが範囲外なら「範囲外」を返すと決めます。リスト自体は整数のリストであるとします。
def checked_at(stock, pos):
if type(pos) is not int:
return "型エラー"
return stock_at(stock, pos)
print(checked_at([7, 2, 10], 1))
print(checked_at([7, 2, 10], "1"))
このコードも stock_at の定義に続けます。型が整数と一致しなければ2行目の判定が真になり、3行目で終了します。整数なら4行目で範囲を確認し、対応する結果を返します。期待値は順に2と「型エラー」、実際の出力も 2 と 型エラー です。文字列の「1」を自動で数に変える仕様ではありません。
検査の順序には意味があります。型が違う入力に先に大小比較を行うと、結果を返す前にTypeErrorとなる場合があります。整数かを確かめてから範囲を検査すれば、失敗の種類を返り値で区別できます。空リストへの整数0は「範囲外」、空リストへの文字列は「型エラー」です。型と位置がともに不適切な場合は型エラーを優先する設計です。
この関数は壊れたリスト自体の検査や、読み込みに使う外部の道具の停止を扱いません。実際のシステムで読み込みに失敗した場合、空リストに置き換えると、空の棚と読込失敗を区別できなくなります。読み込みの成否を別に受け取り、失敗なら位置参照に進まない仕様が必要です。時間切れも同じく、在庫0や範囲外と決めつけず、呼出し側に失敗として伝えます。
誤答から参照の順序を直す
図3のように、長さ4のリストで最後を位置4と考えると、有効範囲の外へ進みます。図3では正しい末尾の3と、誤った4を分けて示します。

例えば次の誤った参照は例外になります。Python 3.15.0で実行すると例外の種類は IndexError です。
stock = [6, 3, 8, 5]
try:
print(stock[len(stock)])
except IndexError:
print("IndexError")
1行目で4要素を用意し、2行目から例外を捕まえる範囲に入ります。3行目の長さは4ですが、添字4は存在しません。そこで4行目が例外を捕まえ、5行目に種類を表示します。捕まえる仕組みは原因を観察するためのもので、誤った添字が正しくなるわけではありません。
原因は個数をそのまま末尾の位置にしたことです。修正するには空でないことを確認し、長さから1を引きます。基本例の関数なら、位置3を指定して範囲を確かめたうえで参照できます。入力 [6, 3, 8, 5] と位置3の期待値は5、実際も5です。空リストで位置-1を作っても有効な末尾にはならず、関数は「範囲外」を返します。誤りを直した後も、通常の末尾と空の両方を再実行します。
自分で試す5問
いずれも位置は0始まり、値は整数、リストは変更しません。範囲外は文字列「範囲外」、型が整数でなければ「型エラー」とします。答えの形は各問に示します。
- 花の鉢数
[12, 1, 6]の位置1の値を整数で答えてください。 - カードの枚数
[11]の長さと最後の添字を、それぞれ整数で答えてください。 - 空のリストに位置0を指定したとき、
stock_atの返り値を答えてください。 - 部品数
[2, 9, 2, 7, 9]で、人が数える1始まりの棚番号5を指定します。shelf_atの返り値を整数で答えてください。 - 記録
[3, 8]と文字列の位置"0"をchecked_atに渡します。返り値を文字列で答えてください。
答えと確かめ方
- 答えは1です。添字0、1、2に12、1、6を順に対応させると、位置1は中央の鉢数です。
stock_at([12, 1, 6], 1)の期待値と実際の出力はともに1です。 - 長さは1、最後の添字は0です。要素が1個なので先頭と末尾は同じ位置です。
len([11])とlen([11]) - 1の出力は順に1、0で、位置0の値は11です。 - 答えは「範囲外」です。長さ0では位置0が長さ未満になりません。
stock_at([], 0)の期待値と実際の出力はともに範囲外で、存在しない区画を読んでいません。 - 答えは9です。番号5から1を引き位置4に変換します。5区画の最後は添字4で、そこに9があります。
shelf_at([2, 9, 2, 7, 9], 5)の期待値と実際の出力は9です。同じ値が別の位置にもありますが、指定された棚番号から位置を決めます。 - 答えは「型エラー」です。文字列は整数型ではなく、大小の範囲判定に進みません。
checked_at([3, 8], "0")の期待値と実際の出力は型エラーです。文字の0を位置0として扱う変換は指定していません。
覚えておくこと
- 0始まりで長さnなら、有効な位置は0以上n未満です。
- 空でなければ末尾の添字はnから1を引いた数です。
- 位置と値を別々に記録し、型と範囲を参照前に調べます。
- 範囲外や読込失敗の結果を、実在する在庫数と区別します。
どこで迷ったかを見つける
最後の値を誤るときは、本人に箱を描いてもらい、箱の数と各箱の添字を別の行に書いて説明してもらいます。最初の箱を0としたまま最後まで数えられるかを見ると、個数と位置の混同を見分けられます。空の箱列でも同じ説明を試し、末尾が存在するという前提が紛れていないかを確かめます。
個別指導では、範囲判定の直前にある長さと位置、判定の真偽、返り値を処理表に記入してもらいます。正しい値を偶然返した場合も、負の位置や長さと同じ位置を試せば、どの条件が必要かを説明できます。棚の区画を数える起点が、取り出しの結果を決めます。
読んで終わりにするか、ここから変えるか。
武蔵境駅徒歩30秒、講師1人に生徒1人の完全1対1。授業のあいだ、先生は隣を離れません。いまの詰まりを、無料相談でそのまま話してください。
まず15分だけ電話で話したい方は、無料電話相談(15分)から。塾からお電話を差し上げます。
本気になった日が、入塾の日。
お子様の教育、迷ったら「丸投げ」してください。必ず、期待以上の結果で返します。武蔵野で育む、武蔵境で学ぶ。
電話は年中無休。365日、24時間、お電話可能。




