ThinkStats (1)

現実トウヒで最初らへんに着手してみます。とりあえず週末もがっつりアレできそうなので、嬉しい。とりあえず 1 章に目を通しつつ演習問題から。

演習問題 1-*

ファイル取得して実行してみました。

$ ls
2002FemPreg.dat.gz  2002FemResp.dat.gz  survey.py
$ python survey.py 
Number of respondents 7643
Number of pregnancies 13593

オンラインドキュメントを確認。何故か w3m では確認できなんだ。書き写してみようかな、と思ったんですがここは別途確認ってことで。某所の対応もあるので survey.py の中身確認から。
とりあえず class として定義されてるのは以下な模様。

  • class Pregnancies(Table)
  • class Respondents(Table)
  • class Table(object)
  • class Pregnancy(Record)
  • class Respondent(Record)
  • class Record(object)

あと、main な手続きでは Respondents および Pregnancies なオブジェクトを生成して ReatRecords なメソド呼び出して records な属性の len を print してるのか。
ええと、確かに record な属性はありますね。 Table なクラスのコンストラクタが以下のはず。

    def __init__(self):
        self.records = []

配列の要素数、ということなのか。あるいは ReadRecords も両方同じカンジですね。

  • GetFilename 手続き呼び出してファイル名を取得
  • ReadFile 手続き呼び出し
  • Record 手続き呼び出し

ReadFile はスーパークラスのメソドな模様。中身で以下なナニ。

        for i, line in enumerate(fp):
            if i == n:
                break
            record = self.MakeRecord(line, fields, constructor)
            self.AddRecord(record)

ええと ReadFile の定義が以下になってて

    def ReadFile(self, data_dir, filename, fields, constructor, n=None):

あるいは i に添字、line に行 (?) が、って理解なんスけど、break な if の条件分岐は n が引数で指定されてるときだけ有効で、基本的には enumerate が戻す iterator (?) が終端に来たら繰り返しは終わるのだろうな。
あと、MakeRecord の中で construcor な引数が

        obj = constructor()

みたいなカンジで呼び出されてます。Pregnancies クラスから ReadFile が呼び出される時には以下な形で呼び出されてます。

        self.ReadFile(data_dir, filename, self.GetFields(), Pregnancy, n)

この時、引数に指定されている self.GetFields() という記述がどう評価されるのか。て、これは fields じゃん。その次の Pregnancy がソレにあたるのか。
ええと、Python はクラスを関数と同じ形式で呼び出すのはオブジェクト生成なソレになるので、ということなのか成程。Python 弄ってたのって随分昔だからなぁ。某所で Django/Python などとゆー話があったはずだけど、色々な意味で微妙。
基本的にはオブジェクトを作って引数の fields な配列を元に line な 1 レコードから切り出すための情報を取得して動的に属性を追加している模様。Ruby も凄いけど Python もなかなか凄い。
そういった意味では survey.py はデータを取り出してオブジェクトの配列にして件数を出力しているのみ、ということになるのかどうか。ただ、Record とかってメソドは未使用に見えるのでこのあたりが、とか superclass 方面にも色々あるように思えます。

これは

現実トウヒなネタとしては非常に良質なんですが、今の稼動ではアレかも。

ちょっとだけ現実トウヒ

演習問題 1-3-2 は以下で良いのかな。

# -*- coding: utf-8 -*-

import survey

table = survey.Pregnancies()
table.ReadRecords()
print u' 妊娠レコードの総数 : ', len(table.records)

outcome = 0
for i in table.records:
    if i.outcome == 1:
        outcome += i.outcome

print u' 生児出生数:', outcome

一応出力てきには以下。

$ python first.py 
 妊娠レコードの総数 :  13593
 生児出生数: 9148

OUTCOME ( 277-277 ) の LIVE BIRTH の数と一応合ってる、てか合わせた (?) カンジなんですが。