LoginSignup
556

More than 1 year has passed since last update.

文科省のPythonはPythonじゃねぇ

Last updated at Posted at 2019-05-20

TL;DR

文科省によるプログラミングの教材はダメダメ。PEP8読め。

追記

もちろん、この指摘が普通のコードに対するものだとすれば 「重箱の隅をつつきすぎ」 だというのは全くその通りだと思います。こんな指摘をするつもりはさらさらありません。
しかし、これが文科省という権威ある機関が発表するものならば話は全く違います。
全ての日本の教育を一身に背負うくらいの気持ちと成果を伴わなければならないとも思います。

そういう理由での、厳しい(というか細かい)指摘です。

追記2

自分の説明が足りませんでした(すみません)。ちなみにこの教材は「教員研修用」です。
この教材で研修を受けた教師にプログラミングを教えられると思って考えてみてほしいと思います。

追記3 (2019/9/25 文科省の改訂を受けて)

この度文科省がPythonに関する資料の改訂版を発表しました。
文科省に対して改善を求める当初を行ったように、この記事自体、資料が教材としてより良くなることを願ってのものでした。ですから、等幅フォント・シャドーイングの消去などの改良があったことに関して、両手を上げて喜んでいます。これも皆様との議論の末に起きた事象だと思います。ありがとうございます。

追記4 (2022/10/16 再バズのため記事見直し)
この記事を最初に書いたのが2019/05なので、高3の初めごろでしたでしょうか... 今の自分から見ると、非常に拙いコードを改善例として挙げているものが一部ありました。そういったものをよりPythonicに編集すると共に、文言に関して修正を加えました。

なにがあったか

ネットを見ていると、こんな記事を見つけました

高校生全員が「Python」を履修するかも。「情報科」における学習内容、Pythonやmicro:bitが例示に挙がりましたが致命的なミスが!

おっ!Pythonなのか!!

と思いましたが、よくよく見てみるとコードがひどい。

MicroPythonでの実行を想定しているそうなので、Python3での実行として添削します。
特に、基礎的で大切な部分のみ添削したいと思います。

以下が実際のコードの載っている資料です。

添削開始

基本的に全て添削対象ですが、特にヤバいもののみ取り上げます。
また、一度言ったことはその後には書きません。

早速

全角スペース使うな

まず初めに、8ページ目のコードから

import sys                 # 変数や関数のライブラリを呼び出し
x=sys.float_info.max             #float 型で表せる最大値を x に代入
print(x)                   # 画面に x の値を表示
x=1.797693134862315799999e+308     #float 型の小数点以下に 5 桁「9」の追加した値を代入
print(x)                   # 画面に x の値を表示
x=1.8e+308                 #float 型の最大値より大きな値を代入
print(x)     

はい。赤線だらけですね。これを綺麗にしてみましょう。

import sys  # 変数や関数のライブラリを呼び出し
x = sys.float_info.max  # float 型で表せる最大値を x に代入
print(x)  # 画面に x の値を表示
x = 1.797693134862315799999e+308  # float 型の小数点以下に 5 桁「9」の追加した値を代入
print(x)  # 画面に x の値を表示
x = 1.8e+308  # float 型の最大値より大きな値を代入
print(x)

言いたいことは以下の点です。

  • コメントアウトの#の前には半角スペース2つ以上(今回では守られてますが)、あとには1つ
  • 「=」 などの計算記号の前後には半角スペース
  • てかまず全角スペース使うな(コメントアウトのためのスペースが全角になっている)(PDF化の時に全角になった説も十分あり得るというか多分そう、そうじゃなきゃ困るが、それでもそうならないよう気遣うぐらいして♡)

変なコードなんてレベルじゃないですね。これを教育に使わないでと。

組み込みをシャドウするな

28ページのコードです。

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

これは極刑ですよね

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

つまり、こういうことです

  • 組み込み関数を上書きするな
  • カンマ「,」の後にはスペース
  • 変数名は意味を持たせろ

sumという関数はデフォルトで用意されています。それをたった一度の宣言で上書きするなんて、正直考えられません。
計算させたいのは分かります。コード書いて理解してねっていう気持ち。

でも、実行時環境を汚すのは別問題です!

また、同じページ

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

なんのためにPythonを選んだんですか?

こうしましょう。

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

こうしないまでも

values = [56, 3, 62, 17, 87, 22, 36, 83, 21, 12]
sum_val = 0
for i in range(10):
    sum_val += values[i]
print(sum_val)

あるいは

values = [56, 3, 62, 17, 87, 22, 36, 83, 21, 12]
sum_val = 0
for v in values:
    sum_val += v
print(sum_val)

こうかく努力はすべきです。

注意すべき点は

  • インデントはスペース四個
  • 「a = a + b」 は 「a += b」と等価、こういうことはrangeより先に教えるべき
  • range(0, 10, 1)よりrange(10)を教えよう
  • てか、シャドウするようならそれを使ってあげてよ

言いたいことがちょっとぶれてますが、要するに、それって学ぶ順番間違ってるでしょってことです。

さっきとやってることちゃうやんけ

29ページ、乱数に関する項から

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

さっき、思いっきりrange(0, 10, 1)とかやっとったやん……

import random
r = random.randrange(1, 11)
print(r)

なんでrange(0, 10, 1)ができてrandom.randrange(1, 11)ができないんですか!

さっき(二行目前)とやってることちゃうやんけ

29ページのコードです

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 の方が小さい ")

なんでインデント揃ってないんですかーーーー!!!???

import random

a = 5
r = random.randrange(10)
if a == r:
    print(" 当たり ")
elif a > r:
    print("a の方が大きい")
elif a < r:
    print("a の方が小さい")

はぁ……

言葉は慎重に選ぼう

31ページより

 Python で WebAPI を扱う場合は OS のコマンドプロンプトを起動し,pip install requests と入力して requestsモジュールをインストールし,requests モジュールと json モジュールを import 文で取り込む必要がある。

おいちょっと待て!
それはライブラリだ!モジュールではない

@amuyikam様の指摘が無ければ見逃していました

Python で WebAPI を扱う場合は(略)requests モジュールと json モジュールを import 文で取り込む必要がある。

...

なんでrequestsjsonを用いる必要があるんですか。厳密には、requestsライブラリを使えばAPIへのリクエストやレスポンスの扱いが簡単になるだけです。さらには、requestsを使うなら、別にjsonモジュール使うところはない気がしますが...

@toritoritorina様からの指摘を受けて追記。厳密に言えば、モジュールを間違いとするのは正しくないかもしれません。というのも、パッケージはモジュールの仲間だという言い方もできるからです。
とはいえ、例えばイヌ科の動物であるタヌキだと言い張るのはおかしいですよね。
いやまぁ、この例がおかしいのは分かりますが、なんとなくそういう気持ちっていうことです。
また、Whats the difference between a module and a library in Python?に分かるように、Pythonを書いている人間からは明らかに違ったものとして扱われているという事実もあります。
こういったことを無視してモジュールでくくってしまうのは、誤りに思えてなりません。

Python3...だよね?

36ページより、二分探索をする項です。

def binsearch(a,p):
    i = 0
    j = len(a)-1
    while i<=j:
        m = int((i+j)/2)
        if a[m]==p:
            print(" 見つかりました ")
            break
        else:
            if a[m]>p:
                j=m-1
            else:
                i=m+1
a = [25,33,43,51,66,71,88]
p = 43
binsearch(a,p)

int((i+j)/2)ってマジ?こうすべきです。

def binary_search(values: list[int], target: int) -> bool:  # アノテーションは大事! `list`はPython3.9から使えます。以前は`typing.List`を使います。
    bottom = 0
    top = len(values) - 1
    while bottom <= top:
        mid = (bottom + top) // 2
        if values[mid] == target:
            return True
        else:
            if values[mid] > target:
                top = mid - 1
            else:
                bottom = mid + 1
    return False


value_list = [25, 33, 43, 51, 66, 71, 88]
value = 43
if binary_search(value_list, value):
    print("見つかりました")
else:
    print("見つかりませんでした")

Python3にはa // bという数学記号があります。それを使ってください。intの挙動を理解するために使用した~という意図は伝わってこなくもないですが、そういうのは二分探索とは別の文脈で解説するべきものであって、初学者である教材利用者のためにも分けたほうが良いかな...
また、変数などには意味のある単語を使いましょう。apでは、あとあとよくわからなくなります
これはちょっと本来学びたいことから外れそうですが、判定用関数である以上、boolなどの値を返すようにした方が再利用性は高いですし、綺麗です。アノテーションもあるといいですね。

もう疲れた

もうこれ以上は疲れました。ちょっと長すぎます。

皆さんも良ければ探してみてください。

編集履歴

  • @takuyakubo様から誤字の修正をいただきました。僕も敗北者でした。
  • @saturday06様からまたもや誤字修正。土下座じゃ済まねぇ……。
  • コメントアウト前のホワイトスペースに関して、記述を直しました。指摘していただいた方ありがとうございます。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
556