先日Go言語版をだしたので、Pythonはじめたときにどんなものをつくったのか気になって見てみたら、プログラミング言語が異なると結構違うというのを改めて実感したので、こちらも公開しようと思います。
HelloWord!の次に作るプログラム、Python版です。
つくるとわかるプログラミング言語(Python)の特徴
実際のプログラムは、50行にも満たない短いプログラムですが、いろいろな要素を含むプログラムをつくることで、小さくてもみえてくるものがあります。
Pythonの特徴
- 開発者にやさしい
- インデントブロックなので書き方が似てくる
- 開発環境が充実している
- 周辺ドキュメントが充実している
4つほど列挙したものの、一番最初の開発者にやさしい、という一言が最大の特徴です。
Pythonは、何かをやろうと思った時に、ごくごく自然に書くとそれが想定されているものに合致しました。
今回でいえば、乱数、時間差、ループの使い方など。
この方が使いやすいと考える通りに、言語仕様がなっていたり、部品が作られていたりします。
もっとも、Pythonだけではなく、インタプリタ型の最近の言語は、開発者よりになってはいます。
例えば、乱数です。
乱数も特定のアルゴリズムで生成しているため、通常はSEED(シード)といわれる乱数を生成ときに使う値を指定しないと、毎回同じ結果になってしまいます。
そのため、シードにつまりそのタイミングのシステムクロックを設定して、異なる乱数を発生させるということをよくやります。
というか、乱数を利用する場面を考えるとシードを与えずに利用するケースの方が数少ないと思われます。
乱数って、毎回毎回バラバラな値が欲しいから使うケースが多いと思うし、実際自分が過去利用したケースでは、ほぼ100%シードにシステムクロックを設定していました。
ほぼと書いたのも、どちらでもいいケースでやらなかっただけのものです。
それが、Pythonでは、最初からシステムクロックをシードに与えてありました。他言語に比べて、数行書くことが減ります。
数行とはいえ、乱数は特定の人を除けばそうそう使うものではないので、いつも乱数の使い方を調べてプログラムを書いています。
そのあたりも短縮されるので、開発者としては楽になりますね。
実際に、そんなことが重なったこともあり、Go言語では80行を超えていたプログラムが、Pythonでは、50行に満たない行数で実現できています。
もちろん、偶然使える部品がGo言語になかったか、知らなかっただけの理由だし、GoにはGoのよさがありますので、これだけで単純比較はできません。
ただ、開発者にはやさしい言語だというのは、いたるところで感じました。
ネクストHello,Worldプログラム
さて、Hello,Worldの次につくるべきプログラムは、次のものになります。
「タイピングの練習プログラム」
理由は、プログラムの各種要素が短いプログラムに凝縮されてつまっているから、です。
条件分岐、繰り返し、関数、文字列操作、ファイル操作、時間、演算、乱数、エラー処理まで、ここぞとばかりに詰め込まれています。
Go言語で書いたときにもう少し詳しくも書いていますので、よろしければ下記もご参考に。
プログラムの勉強でHelloWorldの次には何をつくったら良いか?【Go言語版】
タイピング練習プログラムの内容は、簡単には次の通りになります。
- ファイルから文字列を読込み、以下を繰り返す
- その中から一行をランダムに表示
- ユーザから一行入力
- 表示文字列と入力文字列の一致率を表示
- 入力にかかった時間を表示
- 入力がなければ終了
実際にPythonで作ったものを動かしてみました。
*** タイピング練習プログラム(Python版) *** 表示された文字を入力してください abcdefghij > abcdefghi 正解率: 90 パーセント 時間 6.03 秒: 表示された文字を入力してください qwert yuiop > qwert yuiop 正解率: 100 パーセント 時間 6.88 秒: 表示された文字を入力してください asdf jkl; > おつかれさまでした!
表示される文字列は、テキストファイルに書かれたものです。
そのファイルは、単純に文字を並べたものなので、書き変えればいろいろな文字列での練習ができます。
例えば、Pythonのキーワードなどをいれて練習すれば、Pythonプログラムをタイプする時間は短縮されるかもです。
abcdefghij asdf jkl; qwert yuiop
Pythonのタイピング練習プログラムの実例
Pythnで書いた、タイピング練習プログラムになります。
冒頭で、時間と乱数関連を取り込みます。
標準入出力やファイル操作関連は、特殊な使い方をしない場合は特にimport不要です。
import time import random
Python関数定義の順番
次に関数定義です。
Pythonはインタプリタ型ということで、上からソースコードが読み込まれて実行されていきますので、関数定義は先に実施します。
先に定義しておかないと実行時にそんな名前のものはないと、Pythonに叱られるからです。
もっとも、順番に実行する内容も、main関数として関数として定義していますので、実際には順番が逆転していても大丈夫です。
実行されるタイミングは最後になるので、そのタイミングで定義済みであれば問題はないからです。
つまり、下記のような流れなら問題はないということです。
- 関数1の定義(内部的には関数2を呼び出し)
- 関数2の定義
- 関数1を実行
上記ケースでは、実行時には関数1も関数2も定義済みです。
今回は主要な流れは、main()という関数にすべて定義して、プログラムの最後の行でmain関数を呼び出してますので、好きな順番で書くこともできます。
# 表示文字列と入力文字列の一致度合いを返す def calc_hit_rate(prtbuf, inpbuf): lprt = len(prtbuf) linp = len(inpbuf) ihit = 0 for i in range(lprt): if i >= linp: break if prtbuf[i] == inpbuf[i]: ihit = ihit + 1 return int((ihit / lprt) * 100.0)
この関数は先頭から一文字ずつ比較して一致していたら一致数を数えています。
最後に、表示文字長さでわり100をかければ、一致割合が算出されます。
Python:ソースコードはスネークケース(タイピング練習メインプログラム)
メイン処理部分は下記になります。今回ここに出すにあたって、関数名や変数名などを多少変更しました。
理由は、Pythonは関数名や変数名はスネークケースで書くのが一般的だからです。
スネークケースとは、小文字をアンダーバーでつないで記述することを言います。
Pythonも蛇だから、しゃれでこうしているのかはわかりませんが、確かに世の中にでているソースコードは、小文字+アンダーバーが多いですね。
クラス名は大文字はじまり、定数は全部大文字など、いくつか暗黙のルールはあるようで、最初のころわからずにインストールして最初の頃は、先頭文字や単語先頭を大文字で残りを小文字(キャメルケース)でかいていたものを、今回スネークケースに修正して載せています。
def main(): print('*** タイピング練習プログラム(Python版) ***') try: filename = 'typetext.txt' # 空行は読み飛ばし with open(filename,'r', encoding='utf-8') as f: readlist = [] for row in f.readlines(): if row.rstrip() != '': readlist.append(row.rstrip()) except: print('ファイル[{0}]オープンに失敗しました'.format(filename)) return False while True: print('\n表示された文字を入力してください') # 表示文字列を読み込んだ行からランダムに選択して表示 prtstr = readlist[random.randint(0, len(readlist) - 1)] print(' ' + prtstr) ts = time.time() inpstr = input('> ') te = time.time() # 入力がなかった場合は終了 if len(inpstr) == 0: print('おつかれさまでした!') break print('正解率: {0} パーセント 時間 {1:6.3} 秒: '.format( calc_hit_rate(prtstr, inpstr), float(te - ts)))
メイン処理では、表示するテキストを読み込んで、乱数をつかって一行表示、ユーザの入力文字列と表示文字列を比較して一致度を計算、最後に表示という順番をそのままプログラムしています。
ファイル読み込み処理が、with文を利用することでファイルクローズを気にしなくてよくなったり、一気に読込ながらも、空行の読み飛ばしなども簡単にできてしまうところは、開発する立場としてはうれしい限りです。
ファイルオープンのときには、encodeing='utf-8'をつけています。
今回のテキストファイルは、2バイト文字を含んでいないため特にはいらないのですが、Pythonは日本語表示で結構苦労しましたので、あえて付け加えました。(最初に書いたときには、はいってませんでした。今は、ファイルIOの際には文字コードを意識するようにしています。
Python実行部分のおまじない(if __name__ == "__main__")
if __name__ == "__main__": main()
最後に、main関数を呼び出します。
別にmainという名前の関数でなくともいいのですが、関数を呼び出して実行する部分、関数ではなくても実行部は、この条件ブロックに入れるのは、Pythonのおまじないになっています。
こうしないと、他のソースコードからインポート(import)で再利用しようとしたときも、実行されてしまうという理由からです。
pythonは、実行しようとしているソースコードに対しては、__name__というこのファイル内だけのプライベートな変数に、"__main__"という定義が与えられます。
インポートで利用される場合には、import touchtype であれば、touchtypeという定義があたえられるという仕組みになっています。
ということは、この条件文があれば、単にimportでは実行されないから、ここに定義した関数(例えば、calc_hit_rate)は他からインポートしても利用可能ということになります。
これを利用することで、テスト実行部分をこのif文以下のブロックに書いておくなどの使い方ができます。
以上、今回は、PythonでHello、Wolrdの次につくるべきプログラムということで、タイピング練習プログラムを紹介しました。
タイピング練習プログラムはさまざまな言語仕様を学ぶのに適した題材です。
これからPythonという方は、是非つくってみて、Pythonの学習に役立ててもらえると幸いです。
最後までお読みいただき、ありがとうございました。