応用的プログラム

このページの内容は文科省の以下の資料を基に作成されたものです。

応用的プログラム


リストの利用例

a=[56,3,62,17,87,22,36,83,21,12]  # リスト a の定義
goukei = 0
goukei = a[3]+a[7]
print(goukei)
100

2行目の代入の意味が不明。

この章は指導する立場の教員の研修用教材としては、総じて変数の命名が雑。aはa,b,cの最初のaか?arrayの頭文字のaか?

datalist=[56,3,62,17,87,22,36,83,21,12]  # リスト datalist の定義
goukei = datalist[3]+datalist[7]
print(goukei)
100

ちなみに1行目のデータリストの変数名としてlistは使わない方がよい。listは組み込み関数list()の名前と重複する。また、配列と解釈してarrayという名前も使わない方がよい。本当の配列を処理するモジュールarrayの名前と重複するからである。


リスト要素の加算

リストを配列とみなし、共通テストの受験を視野に入れて配列に対する処理方法を示すという意味では適切なプログラム。データリストの変数名は変えた方がよい。

先の例と異なり、2行目の代入処理は、繰り返し処理の初期化処理として必ず必要。

a=[56,3,62,17,87,22,36,83,21,12]
goukei = 0
for i in range(0,10,1):
    goukei = goukei+a[i]           #a[0] ~ a[9] まで全て加えていく
print(goukei)
399

試験の回答としては上記の記述が適切に感じるが、実用プログラムとするためには、以下の例のようにrangeの第2引数をlen(a)として、処理対象のリストの要素数の変化に自動的に適合できるようにすべきである。

また、特別な意図もなく単純に0からの添え字を発生させたいだけならば、forの添え字生成はrange(len(a))の方が簡潔で良い。

a=[56,3,62,17,87,22,36,83,21,12]
goukei = 0
for i in range(0,len(a),1):
    goukei = goukei+a[i]           #a[0] ~ a[9] まで全て加えていく
print(goukei)
399

例えば、C言語でのfor文はwhile文の拡張構文だが、Pythonのwhileとforは全く別の発想に基づく文。Pythonのfor文はwhile文と異なり、集合を対象として、与えられた集合のすべての要素に同じ操作を行う集合操作のための文。結果的に繰り返し文とみなすことができるというだけ。range(a,b)は繰り返しの処理範囲を指定する記述ではなく、forの本来の機能に合わせて、処理の対象となる添え字の順序付き集合を生成する記述である。

例えば、range(10)は、0から9までの順序付けされた整数集合を生成する。

print(list(range(10)))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

while文を使う例は以下の通り。

datalist=[56,3,62,17,87,22,36,83,21,12]
goukei = 0
i = 0
while i < len(datalist):
    goukei = goukei+datalist[i]           #a[0] ~ a[9] まで全て加えていく
    i=i+1
print(goukei)
399

もしPythonらしい処理を示すのであれば、以下のようなプログラムが適切ではないか?(共通テストを受けるのであれば、混乱を避けるためあえて教えない方が良いとも感じる)

for文の集合処理記述という本来の機能を利用してリストから要素を取り出して合計を求める例。

datalist=[56,3,62,17,87,22,36,83,21,12]
goukei = 0
for v in datalist:                   # リストから要素を取り出して処理
    goukei = goukei+v                #a[0] ~ a[9] まで全て加えていく
print(goukei)
399

ちなみに、アルゴリズムの勉強が目的ではなく、リストの要素すべての要素の合計を求めたいだけであれば、組み込み関数sum()を使用すればよい。

datalist=[56,3,62,17,87,22,36,83,21,12]
print(sum(datalist))
399

乱数

import random             #random モジュールを読み込む

a = 5
r = random.randrange(10)  #0 ~ 9 までの整数をランダムに発生
if a==r:
    print(" 当たり ")
elif a>r:
    print("a の方が大きい ")
elif a<r:
    print("a の方が小さい ")
a の方が大きい

このプログラムの出力だと、乱数の値が分からないので、正しい結果かどうかわからない。

また、2つの数値のすべての関係を確認する比較はない。大きいか小さいかを確認すれば、残りは等しいしかないのであえて等値比較する必要はない。

出力を修正し、if文での比較を最適化(不必要な比較を削除)した例を示す。

比較に関しては、a==rではなく、上記のプログラムのif文の最後の比較のa<rを削除しても問題ない。

import random                #random モジュールを読み込む

a = 5
r = random.randrange(10)     #0 ~ 9 までの整数をランダムに発生
# print(r)                     # 出た数が分からないとね
print(f'a={a}, r={r}')     # このような出力処理ができる
if a>r:
    print("a の方が大きい ")
elif a<r:
    print("a の方が小さい ")
else:
    print(" 当たり ")
a=5, r=2
a の方が大きい

乱数の生成範囲

import random

r = random.randrange(10)+1
print(r)
9

1から10までの整数乱数を生成したいのであれば、素直にそのような関数randint()を使えばよい。

また、プログラムとしては正しいが、生成された乱数の範囲の正しさが、単発ではわからない。

乱数を複数生成してその範囲を確認できるようにした例。

import random

r = random.randint(1,10)
print(r)
rndlist = [random.randint(1,10) for _ in range(50)] # 生成された乱数列の確認
print(rndlist)
9
[2, 7, 8, 10, 6, 8, 3, 2, 1, 7, 3, 8, 7, 1, 4, 4, 8, 5, 10, 2, 6, 10, 6, 3, 5, 8, 6, 9, 6, 8, 8, 8, 6, 4, 5, 3, 5, 8, 7, 2, 3, 10, 1, 4, 9, 3, 2, 8, 4, 4]

生成された乱数の最大最小を確認したい場合には以下のようにすればよい。

import random

r = random.randint(1,10)
print(r)
rndlist = [random.randint(1,10) for _ in range(50)] # 生成された乱数列の確認
print(rndlist)
print(f'最大値:{max(rndlist)}, 最小値:{min(rndlist)}')
8
[3, 6, 9, 7, 9, 6, 5, 7, 6, 4, 5, 7, 2, 7, 2, 2, 10, 7, 1, 2, 8, 3, 9, 1, 4, 5, 4, 5, 7, 10, 8, 10, 4, 10, 4, 8, 9, 7, 9, 4, 6, 9, 8, 5, 7, 3, 6, 2, 9, 6]
最大値:10, 最小値:1

ちなみに、乱数なので、最大値と最小値が必ず10,1になる保証はない。

いっそのこと、乱数の数値ごとの出現回数を求めてみましょう。

def count_elements(lst):        # 与えられたリストの数値ごとの出現回数を辞書として返す
    vcount = {}                 # 辞書は最初は空
    for key in lst:
        if key in vcount:       # keyが辞書内にあるか?
            vcount[key] += 1    # keyが登録されていればカウントアップ
        else:
            vcount[key] = 1     # keyが登録されてなければ新たに登録
    return vcount

rndlist = [random.randint(1,6) for _ in range(100)]  # 1から6までの乱数リストを生成
result = count_elements(rndlist)                     # 乱数の数値ごとの出現回数を求める
print(result)

for key, count in result.items():
    print(f"{key}: {count}回")
{4: 170, 5: 177, 2: 150, 6: 142, 1: 172, 3: 189}
4: 170回
5: 177回
2: 150回
6: 142回
1: 172回
3: 189回

結構ばらつきがみられます。

乱数の数を100倍にして100から10000に変えると次のようになりました。

{1: 1679, 5: 1661, 6: 1678, 3: 1655, 4: 1679, 2: 1648}
1: 1679回
5: 1661回
6: 1678回
3: 1655回
4: 1679回
2: 1648回

だいぶばらつきがなくなったように見えます。

正確には、分散などを求めて比較してみるといいですね。

実は、Pythonはこんなこともできます。

from collections import Counter

rndlist = [random.randint(1,6) for _ in range(10000)]  # 1から6までの乱数リストを生成
result = Counter(rndlist)
print(result)

for key, count in result.items():
    print(f"{key}: {count}回")
Counter({2: 1699, 6: 1691, 3: 1671, 1: 1667, 4: 1645, 5: 1627})
4: 1645回
3: 1671回
2: 1699回
1: 1667回
6: 1691回
5: 1627回

関数など作らなくてもできちゃうんですね。


関数

リストを配列とみなし合計値を求める関数を書くとすれば、標準的で適切な解答。ただし引数名が不適切。これでは、関数の引数を想定しづらい。

def listgoukei(a):                    # 合計を求める関数 listgoukei を作成
    goukei = 0
    for i in range(0,len(a),1):       # 単純にrange(len(a))と書く方が好ましい。
       goukei = goukei+a[i]
    return goukei

a = [56,3,62,17,87,22,36,83,21,12]
goukei = listgoukei(a)                # 作った関数 listgoukei を呼び出し
print(goukei)
399

for文でリストから要素を取り出して処理を行うPythonらしい処理。共通テスト対策では教えない方が混乱を生じず良いかも。

def listgoukei(list):                    # 合計を求める関数 listgoukei を作成
    goukei = 0
    for v in list:                       # リストから要素を取り出して処理
       goukei = goukei+v
    return goukei

a = [56,3,62,17,87,22,36,83,21,12]
goukei = listgoukei(a)                # 作った関数 listgoukei を呼び出し
print(goukei)
399

WebAPI

import requests
import pyodide_http                              # PyTerm, PyScriptでの実行時のみに必要
import json

pyodide_http.patch_all()                         # requestsを修正する:PyTerm, PyScriptのみ

url = "https://zipcloud.ibsnet.co.jp/api/search"  # 使用する WebAPI の URL
# param = {"zipcode": "100-0013"}                  # WebAPI の引数
param = {"zipcode": "542-0061"}                  # WebAPI の引数
# param = {"zipcode": "100-8959"}                  # WebAPI の引数:文部科学省
# param = {"zipcode": "163-8001"}                  # WebAPI の引数:東京都庁
# param = {"zipcode": "540-8570"}                  # WebAPI の引数:大阪府庁

res = requests.get(url,params=param)             # WebAPI の戻り値が res へ
response = json.loads(res.text)
if (response["results"] is not None):
    address = response["results"][0]
    print(address["address1"] + address["address2"] + address["address3"])
else:
    print('関連する住所が記録されていません')
大阪府大阪市中央区安堂寺町

郵便番号の下4桁が8000番台の郵便番号は住所を取得できない。