読者です 読者をやめる 読者になる 読者になる

StatsBeginner: 初学者の統計学習ノート

初学者が統計学、機械学習、R、Pythonの勉強の過程をメモっていくノート。

『Pythonスタートブック』第5章をやりました

Python 『Pythonスタートブック』

教科書第5章をやる

 昨日は、『Pythonスタートブック』第5章をやりました。進みが遅いですが、まぁ、何かの合間にやってる程度なので…。


Pythonスタートブック

Pythonスタートブック


 単なる基本操作なので、以下、やったことを単に羅列しておきます。

  • 第5章では、繰り返しのfor及びwhile、エラー処理のtry及びexcept、そして条件分岐のifとかを学ぶ。
  • forは何かリストになったものを1個目から順番に実行していくという繰り返し。whileはある条件を満たす限り定義された処理を実行していくという繰り返し。
  • この章で使われる条件分岐や繰り返しの文は、複数行のまとまったコードを塊(ブロック)として実行するのだが、この塊の定義においてPythonは「タブかスペースで字下げ(インデント)されている範囲を塊とみなす」方式になっている。タブでもスペースでもいいが、個数は揃えること。
  • ほかの言語では(Rもだが)、{}で囲む範囲がブロックになるとかがふつうなので、ここはPythonの独特なところ。
  • ifのあとにelseがあるときはelseの行は字下げせずに最初から書く。逆にelse配下の処理はelseより字下げして書く。
  • 教科書によると、この字下げルールによって、逆にみんなのコードの書き方が揃う(字下げしたりしなかったりということがない)ので、Pythonのコードが他人にも読みやすくなるという面があるらしい。
  • forでの繰り返しの考え方は、Rでやる場合と同じ。↓のようにすると、numbersというリストに入っている要素が1個目から順番にprintされる。varのところは、Rでfor (i in 1:100)とか書くときのiと同じで、べつにどういう文字列でもよい。
for val in numbers:
     print(val)
  • 上記のように、インデントしている範囲がforの実行対象となる。
  • 1行で書くべきコードを途中で改行したくなったときは、末尾に「\」を入れて改行する。
  • forで辞書型のオブジェクトの要素を呼び出す時は、順番が分からない。辞書の要素には順番という情報がないので。
  • 「while True:」と書いてこの配下のコードに含まれるif文の結果がTrueである限り処理を続けるという記述法がこの教科書では何度かされている。そういう記述法を一般的によくやるのかどうかは知らない。以下の2つのコードは同じ処理になる。
import random  # モジュールをインポート
rand_num = 0
while rand_num != 4:  # !=はノットイコール
     rand_num = random.randint(0, 9)  # 0~9の整数からランダムに1つを選んで格納
     print(rand_num)
while True:
     rand_num = random.randint(0, 9)
     print(rand_num)
     if rand_num != 4:
          continue  # Trueならもう1回同じことをやれということ
     else:
          break  # Trueじゃなくなったので処理をストップ
  • 論理的には、continueは「以降の行を無視してブロックの先頭に戻る」という意味であり、breakは「以降の行を無視して処理を中止する」という意味になる。
  • まとまったコードを実行させて、もしエラーが出た場合はメッセージを出すなりなんなりするという処理は、「try」と「except」の組み合わせで書く。
  • スクリプトのファイル中で日本語を扱いたい場合は、スクリプトの冒頭で以下のようにコメントを使って宣言しておく。なお、コメント中でしか日本語を扱わないときでも、同じように宣言しておく。
#coding:utf-8
  • Pythonで複数行をまとめてコメントアウトするときは、引用符を3つ重ねたもので挟む。引用符は「"」でも「'」でもいいので、「"""」か「'''」になる。
  • 文字列フォーマット操作というのがあって少しややこしい。以下のような感じになるのだが(Out[68]:というのはCanopyのシェルから操作するときについてくる記号)、これは「%0.2f」が、「%のところに入る数字に関して、少数第2位までを表示する」ということを意味しており、「% x」で%の箇所にxを代入している。
x = 1.0/3.0
'answer = %0.2f' % x
Out[68]: 'answer = 0.33’
  • この章の最後で、「身長と体重を入力したらBMIを計算した上で、太ってるか痩せてるかを教えてくれるプログラム」を書く。
  • 以下のようなコードで、「コマンドライン上で身長の入力を求める→数字が入力される→体重の入力を求める→BMIを計算する→BMIによって痩せてるか太ってるかというメッセージを表示する→もう1度身長の入力を求める→何も入力されずにenter(return)が押された場合は処理を終了する」という処理を行う。
#coding:utf-8

while True:
    height = raw_input('身長(m)?:')  # コマンドライン上で入力を求め、heightというオブジェクトに格納
    if len(height) == 0:
        break  # heightが未入力だった場合は処理をストップ
    height = float(height)  # 少数型に変換
    weight = float(raw_input('体重(kg)?:'))  # こっちは最初から少数型にして格納
    bmi = weight / pow(height, 2)  # BMIを計算。powは累乗を計算する関数
    print('BMIは%0.1fです。' % bmi)  # 少数第1位までしか表示しないように設定
    if bmi < 18.5:
        print('少しやせすぎです。')
    elif 18.5 <= bmi < 25.0:
        print('標準的な体型です。')
    elif 25.0 <= bmi < 30.0:
        print('少し太っています。')
    else:
        print('高度の肥満です。')  # ここまできたら最初の処理に戻る
  • raw_input('hogehoge')は、コマンドラインからの数字や文字の入力を受け付けるという関数で、('hogehoge')の部分に書いた文字は入力受付のメッセージとしてコマンドラインに表示される。あるPython入門サイトでの例だと、以下のようなことをやっているが、これはコマンドラインに「May I your your name, please?」と表示して入力を待ち、入力された文字列をnameというオブジェクトに格納するという処理である。その後のprintの行は、単に組み合わせで文字列を表示しているだけ。
name = raw_input('May I your your name, please? ')
print 'Hi! ' + name + '. Nice to meet you.'
  • ところで、raw_inputで入力を求める際のメッセージ部分が、Canopyのシェル上では文字化けしてしまって表示されない。処理結果はきちんと日本語で表示されるんだけど……。
run bmi.py  # Canopyのシェルから実行している
���������m���?:1.70
���������kg���?:69.0
BMIは23.9です。
標準的な体型です。
  • OSのターミナルから実行してみると、日本語のところがちゃんと表示された。なので、Canopyが日本語をきちんと表示できないか、なにか設定が足りないんだろう。
MBA2012:Startbook yk$ Python bmi.py  # Mac OSのターミナルから実行している
身長(m)?:1.71
体重(kg)?:66.0
BMIは22.6です。
標準的な体型です。
身長(m)?:1.65
体重(kg)?:55
BMIは20.2です。
標準的な体型です。
身長(m)?:1.83
体重(kg)?:89.0
BMIは26.6です。
少し太っています。
身長(m)?:
MBA2012:Startbook yk$ 

 
 

メモなど

  • Pythonの字下げルールについては解説しているサイトがけっこうある。たとえば

Pythonとインデント - KnowledgeBase

従来の言語では、ブロックの終わりが"end"や"}"で明示されるが、Pythonの場合それに相当するものがないので、ブロックの範囲がわかりにくい場合がある。特に、ブロックが非常に長かったり、多重ブロック(forの中にifがあり、その中にforがある場合など)の場合にはわかりにくい。これを回避する方法として、ブロックが閉じる位置にコメントを入れるという手がある。


#end for i

インデントには、タブもしくは空白を使うことができる。空白を使う場合は、個数をきちっとそろえる。タブを使うなら、空白を混在させないように注意する。見かけ上は同じだけインデントされているように見えても、タブや空白が混在していて、しかもその個数が行ごとに異なっていると、同じ字数だけ字下げされているかどうかが判別できないのでエラーになる
入力するにはタブの方が楽なのだが、タブとスペースが混在した時に気付きにくい。一般には空白4つでインデントすることが推奨されている

  • Rでは、決まったパターンの処理を部品化するには、①関数を自分で作る、②スクリプトを書いたテキストファイル(hoge.Rとか)をsource(“hoge.R”)で呼び出す、③パッケージを使うといったやりかたになるが、今やっているpythonの教科書は②のやり方でいろいろな部品を作っていって、必要なときに呼び出すというのに近い。
  • Python全般、プログラミング全般で、そういう部品化した処理をどういうふうにやってるのかは知らん。Javaのクラスファイルとかも似たようなもの?
  • Canopyを終了せずにMacをスリープさせると、異常終了になる。Rはべつに大丈夫なので、Rの処理の途中でMacBookをパタンと閉じて移動したりするのだが、Canopyでそれをやると不正な終了になるので注意。
  • テキストエディタ、Canopyのシェル、Evernoteなどアプリをまたいでコードを書いてコピペしたりしてるときに、引用符("や')が、入力補助なのか知らんけど勝手に全角(”や’)に変換されていて気づかないことがある。これはコードが動かなくなるし、Rでもたまにやってしまうミスなので、気をつける。

 
 

課題など(前回から解決していないものを含む)

  • 「変数」「モジュール」「オブジェクト」「メソッド」「インスタンス」「データ型」など基本用語さ指す範囲や包含関係にまだ曖昧なところがあるので頭を整理する
  • 日本語のリストを変数に代入して、print(変数)したとき、日本語の出力が文字化けするのをどうしたらいいのか
  • CanopyつかうのにX codeってほんとに必要なの?なくても大丈夫?
  • Canopyのシェルから操作することと、OSのシェル(ターミナル)から操作することの違いがよくわかってない。Canopyを起動するとPythonも起動してると思うんだけど、それとは無関係に同時にターミナルでPythonを起動したり終了したりできるのもよくわからない
  • raw_inputという関数を使ったときに、コマンドラインに表示されるメッセージが、Canopyで文字化けする。処理の結果とかはきちんと日本語で表示されるのに。OSのターミナルからスクリプトファイルを呼び出して実行すると、文字化けしなかった。
  • Rのエディタのように、スクリプトを書いてマウスで選択した部分だけその都度実行するというツールがあると、とてもやりやすいんだけど、そういうのはないのかな?(探したけどよくわからない)