KuriKumaChan’s diary

Kuri ちゃんと Kuma ちゃんの飼い主の独り言

Head First Python を久しぶりに開いで最後まで読み通した - 写経プログラミングからの脱却へ

プログラミングの本を手に取ってみることは昔からたまにはあったのですが、「最初から最後まで読み通した」経験はほとんどありませんでした。しかしこの歳になっても結構楽しく読み通すことができた本でしたので頭の整理を兼ねて紹介したいと思います。
本の雰囲気だけは「読み進める上でのヒント」まで読んでいただければ分かると思います。
さらに章ごとの内容(「各章の概要」)については自分がもう一度読むことを前提に将来の自分へのヒントを書き出しましたが、部分的に細かく長くなってしまったりバランスが悪いので最後に持っていきました。

最初に結論

私なりにこの本の特徴と感想をまとめてみたいと思います。

特徴

(「序章」に「この本の読み方」が数ページ書かれています。ここに書いた内容はそれと一部重複しますが、一度書店で目を通してから購入することをお勧めします。)

  • 「親しみやすい文章をじっくり読む」ことと「手を動かす」ことで頭への定着を図りながら、一つの Web アプリケーションを徐々に強化していきます。(冗長性の排除、エラーハンドリングの強化、さらにパフォーマンス向上も)

  • 少しであっても何かしらのプログラミングの経験のある人向けの構成です。そもそも「プログラミングとはなに?」レベルのことは全く書いていません。Python のプログラムも写経プログラミングでも構わないので一度経験があることが望ましいと思います。

  • Python 学習の道筋としては、まず一通りの Python に関する基礎知識の再整理、再確認を行います (1章 - 4章:リスト/タプル/集合/辞書、関数/モジュール)。その上で Web アプリケーションの仕組み、DB (RDB) における入出力の基本的な仕組みを学び、その Web アプリの機能・品質強化のためにクラスやコンテキストマネジャー、関数デコレータ、例外処理を学び取り入れていきます。そして最後に内包表記、ジェネレータと仲良くなれるようになります (5章 - 12章)。

  • この本はリファレンスではないので、特定のテーマだけ参照するために途中の章だけいきなり読み始めると前の章との繋がりが理解できません (12章だけは単体で学習できます)。基本は最初から1章ずつ読み進めると共に自分で手を動かしながら動作を確認しながら進めます。まずは最低限度の機能を持った Web/DB アプリケーションを一旦動かし、その後各種強化をしていくイメージ。

感想

後で書きますが、この本を(再度)読み始めたモチベーションとして、写経プログラマーからの脱却として、一つの言語を一通り理解しておきたかったことがあります。苦手意識のあったデコレータや内包表記などに関しても実際に手を動かしてその動作を最低限は理解できた気持ちになれたので苦手意識は払拭できたのではないかと思います。もちろん読み通しただけで全てを一回で消化&定着できるわけでもないのですが、一度読み終えた現時点で「忘れた時はもう一度読もう!」と思える内容でした。

なぜこの本を選んだのか?

実は以前にチャレンジして挫折していた

会社員時代の終盤 2018年に書店で Python の読み物として面白そうな本があったので買ってみました。ただ仕事も忙しかったので(勉強を始めようとするにあたって不適切な言い訳ですが)あまり手を動かすことなく読み進めました。5章以降はいったん「Web アプリケーション」を動かし、その後はそれを改善していく構成なのだけれど、「 Web アプリケーションを前提にされてもそもそも Web アプリケーション書く予定無いしなぁ」と気持ちは後ろ向きのままパラパラと。さらに 10章「関数デコレータ」ではそれまでに手を動かしてコードを積み上げて来ていないのデコレータの必要性自体を体感できておらず、この本はとうとう完全積読状態となっていました。

写経プログラミングからの脱却を考えているとき書店の店頭で再開した

今年の春から Raspberry Pi で遊ぶことを始めて色々なセンサー類の使い方を調べていたのですが、やっぱり自分の Python のレベルを「写経プログラミング」からレベルアップしておきたい!と思ったことが一つ。あとちょっと凝ったプログラムを見ると『内包表記』というものが使われているのを目にし、そこで挫折することがあったので、「少しはちゃんと Python を勉強しないと」というモチベーションになっていました。
どうしたものかと思い大きめの書店で Python 関連の書籍を漁っていると、家で積読状態の "Head First Python" に再開したのです。店頭であらためて手に取ってみるとやっぱり挫折したデコレータと内包表記が目に入り、今なら時間も十分あるので最初からちゃんと手を動かして読み通そう!ということになりました(もちろん家の積読状態の本を再度開いて!)。

私のこれまでのプログラミング言語経験 - 写経の積み上げ

どのくらいのレベルの人が書いている文章か分からないと正しく受け止められないと思いますので、自分のバックグラウンドを少し書いておきます。 もともと IT 系の会社で新卒で働いていましたので、プログラマーではなかったのですがざっくり研修や OJT で色々な言語には触れていましたが、業務で使い続けるレベルのコーディングではないので、写経プログラミングの域を出ていません

  • プログラムというものがコンピュータの H/W, S/W のレイヤーの中で何をしているのかは分かっている。

  • 簡単なロジックであれば自分でも作れるが、大抵は写経と力技のコーディングで後から読みたくはないものが出来てしまう。

  • プログラミング自体、アウトプットがハッキリしているから基本的には嫌いではないですが、一度アウトプットが出てしまうとそれは目標がひとまず達成されたことになるので萎えてしまいます。「プログラミング言語を学ぼう!」という姿勢よりは「何はともあれアウトプットが出れば満足してしまう」感じ。

読み進める上でのヒント

もし「初めて読み始める」自分にアドバイスできるとしたらどんなことがあるかな、と思って書き出しました。

最初からわかっていた方が良いと思うわれること

基本的なリファレンスなどは手元にあった方が良い

Python なのでいくつかのライブラリが出てきますが最低限の説明しかありません。またコレクションのメソッドなどは説明なしで使われていることもあります。序章では「読み終えるまでに他の本を読まないように」とありますが、基本的なライブラリやメソッドの利用に不慣れな場合は優しめのリファレンスを手元に置いておくと良いかもしれません。私はだいぶ前に買った「逆引きPython標準ライブラリ 目的別の基本レシピ180+!」をチラチラ見ながら Head First Python を読み進めました。ちなみにこの本は特に評判が高いわけでもないですし、知りたい内容が記載されていないことも無くは無いのですが、とりあえずは「この本に書いてあることくらいは何回繰り返してでも知っておこう」と考えているので使い続けています。

補助的な道具立て - Web フレームワークと DBMS

Head First Python は純粋 Python の解説本なのですが、現実の世界で Python だけでアプリとして機能できることは少なく UI としての Web アプリケーションやデータベースを併せて用いることができないと極めて不便だと思います。(Web アプリに興味はあまりなかったのですが...) この本で用いられる Web フレームワークと DBMS は Flask/jinja2 と MySQL (MariaDB) です。Flask/junja 2 は私は初めて使いましたが、本書にはさほど詳しい解説はなく最低限ブラウザからの入出力ができたらそれ以上の応用には踏み込んでいないので、特に Flask の解説書がなくてもなんとかなるかな、と思います。 jinja2 テンプレートの書き方などは軽い説明に留まり「自分で作成する必要はない」と書いてあるでこの部分は写経で進めます。まぁ Flask/jinja2 を使いこなしたいと思ったら、本書を読み終えたあとに関連書籍を勉強するのが良いと思います。

データベースエンジンは MySQL でMac は MariaDB を推奨していたので私は Mac で MariaDB を使いました。Python 用の MySQL データベースドライバー(ライブラリ)は MySQL-Connector/Python を利用します。

読破までの壁

決して毎日読み進めていたわけではありませんが、2回ほど挫折しかけたことがありました。

壁 - その1:関数デコレータ(10章)

最初の壁は Python の関数デコレータ。私にとっては全くの未知の概念なので、なかなか今までの経験や知識からその機能を思い描くこと自体が難しかったです。最初の目的として「ログインチェック」のための関数を各ページ表示用の関数ごとに呼び出すのは煩雑なので、関数デコレータで効率的にコーディングする方法が紹介されます。落ち着いてデコレートする側、される側を意識しながら読み解きテストプログラムで確認していけば「なるほど、これで便利だ!」と腹落ちできました。
10章で学んだ後、11 3/4章のスレッド利用における呼び出し側関数が先に終了するケースで flask の @copy_current_request_context デコレータがさりげなく使われている頃はすでにデコレータの仕組みを忘れかかっていましたが、10章を軽く見直すには良い機会だったかも。

壁 - その2:複数作成するモジュールの位置付け

5章で Flask アプリ("vsearch4web.py")を作成してからこのコードを拡張しながら次の章に進んでいきます。(6章でファイル処理、7章でデータベース処理、8章でクラス、9章でコンテキストマネジメント)
またこの本体のプログラムファイル(vsearch4web.py)以外にもいくつかのテストプログラムや、本体アプリから呼び出される (import される) モジュールも追加作成していくので、一体自分が手を動かしているプログラムが単なる確認テストプログラムなのか?import されるモジュールなのか?それとも本体アプリなのかをしっかり認識して作業する必要があります。
具体的にはデータベース関連のコンテキストマネジメントを処理する DB アクセスプログラムファイルを 9章から別途作成して import して使うようになります(”DBcm.py")。さらに 10章でデコレータのモジュール ("checker.py") を新たに作成し、本体アプリをデコレートします。
この辺りの章は難易度も高かく私は一日に多く読み進めることができず、かつ短時間で細切れに読み進めていったことにより、モジュールの関係がよくわからなくなってしまいました。9章あたりから 11章までは集中力を持って読む必要があると痛感しました。

各章の概要 (読み返す自分へのヒント)

実際にはこのような区分にはなっていませんが、3部構成になっていると考えて読むと本で解説されている範囲の全貌がわかりやすいかもしれません。

  • 【第一部 - Python の基本】:1章 〜 4章
    Python 利用者が頻繁に使うだろうリストや辞書、タプル、集合といったデータ構造の扱いと関数/モジュールがテーマ。
    ひとまずこの第一部だけ読み通すと中途半端にならならず、一通りの再確認ができて一息つける。

  • 【第二部 - Web & データベースアプリの強化】:5章 〜 11 章
    まず最初の 5章でサクッと Flask / Jinja2 のアプリを作成。当然アプリには色々な考慮が必要なので、残りの 章で色々と機能強化していく。Flask / Jinja 2 自体の話はこの本のメインテーマでは無いのであまり深入りせず、とりあえず動くようになった Web アプリをこの本に従って機能強化していくことに集中した方が良い。
    強いて言えば 8章 クラス入門 は一旦 Web アプリから離れて単体のテストプログラムを作って確認するので、8章単独で学習することができる

  • 【第三部 - さらに Python の特徴】:12章、付録
    最後の 12章は 11章までとは独立して構成されているので、この内包表記とかジェネレータの勉強をするにあたってはこの章だけ読めば良い。その他付録ではこの本であまり取り上げなかったテーマが説明されている。

以下の記述で「(課題)」としているのは、章の構成として次の章で解決される課題と私なりに再度読み直しが必要かなと思われるものを取り上げています。

1章 - 基本

IDLE を使いながら簡単な Python プログラムを動かす。

2章- リストデータ(リスト)

Python のデータ構造の概要とその中でリストの扱いを確認する。

3章 - 構造化データ(辞書、タプルと集合)

残りのデータ構造の中で辞書を中心に、そして集合とタプルを確認する。

4章 - コードの再利用(関数とモジュール)

関数の基本とモジュール、そして PEP8 に関して確認する。

5章 - Web アプリケーションの構築 (Flask)

このあと 11章まで色々と手を加えていくベースとなる Web アプリ "vsearch4web.py" を作成する。
Web アプリケーションの仕組みや Web アプリケーションをサーバーにデプロイする話までサラリ言及されているが、Web アプリの仕組みをちゃんと知りたければ別の書籍を読んだ方が良い。。でもこの本を読み通すだけであれば深入りは不要。PythonAnyware へのデプロイの話も出てくるが、詳しい手順などは付録 B に解説がある。

(課題 1) 関数デコレータ @app.route('/')

Flask では @app.route('/') というおまじないが登場し、精神的難易度が一気に高まる。関数デコレータに関しては 10章を丸々使って説明があるので、ここでは単に「関数を URL パスにマッピングする」つまり 「"https://xx.xxx.xx.xx" で関数を呼び出すことができる」 とだけ理解していれば十分。

(課題 2)入出力データのファイルへの記録

この章のアプリでは入力された情報やその結果は Web ページに表示するだけで残らない。それをファイルに残そう、というのが次の 6章。

6章 - データの格納と操作 (ファイル i/o)

アプリの入出力データをログファイルに保存するために基本的なファイルの open / 処理 / close を確認するが、その後で "with" 文でコンテキストマネジメントできるのでこれを基本とする。
そのほかにログファイルのデータのフォーマットや jinja で出力のフォーマットを整えることを確認する。

(課題1) jinja2 による出力

この本では jinja 2 に関してほとんど使い方の説明は無い。しかし今後他の Flask/Jimja2 の本を読むにあたって最低限の経験をした、というレベルで納得しておく。

(課題2)ログの内容を検索する機能がまだない

ファイルの読み書きで色々工夫はできなくは無いが、この本ではあっさりと次の章でデータベースの利用につなげる。

7章 - データベースの利用 (MySQL、データベースドラーバー)

最初に一旦 Web アプリから離れてパソコンに MySQL を導入し単体でログ格納テーブルの作成をするところから始める。Mac の場合は MariaDB が推奨されているので私もそれに従って MariaDB を使う。
次に Python プログラムから MySQL データベースにアクセスする仕組み(ドライバー、API)と手順(サーバーへの接続、カーソルのオープン、SQL 実行、カーソル/接続のクローズ)の概要を確認する。

(課題) データベースアクセスの手順にはファイルの open/close と同様の「前処理」「後処理」がある

6章で確認した "with" 分を用いたファイルの open / close のコンテキストマネジメントを適用すれば、データベースアクセスのコードがよりシンプルになるという考え。これは 9章でコンテキストマネジャを作成して解決するが、コンテキストマネジャの作成にあたってはクラスを作成して初期化のメソッドを用いることが必要なので、コンテキストマネジャの作成に先立って 8章でクラスの考え方を整理する。

8章 - クラス入門

一旦 Web アプリから離れて単独のテストアプリ "CountFromBy.py" を作成してクラスやメソッドに関して確認する。 最低限のオブジェクト指向の話を経て、クラスの振る舞い(メソッド -> 関数)と状態(属性 -> 変数)を確認。その上で特殊メソッド __init__, __repr__、 独自メソッドの作成方法、属性のデフォルト設定方法などをテストアプリを通じて各院する。

9章 - コンテキストマネジメントプロトコル

コンテキストマネージャの内容としてはさほど複雑ではない。前処理__enter__後処理の __exit__初期化__init__ メソッドの役割とそこで実際に処理する内容を整理する。コンテキストマネージャを作成した後、それを使うように Web アプリを修正します。
章の最後にアプリケーションとしての機能拡張のための SQL 文の例を紹介しているが、作成するアプリにはその機能は取り込んでいない。

(課題 1) 先に完成仕様のコードを提示された上でコンテキストマネジャ "DBcm.py" を新たに作成し、さらにそれをもとに Web アプリ "vsearch4web.py" を修正する。

私の場合、この前の章あたりから経験の少ない分野に突入していたので頭がミクロ的な思考になっており、今自分がコンテキストマネジャーのコードを扱っているのか?コンテキストマネジャーを用いたアプリのコードを扱っているのかよく分からなくなり混乱した。
この章では新しく加わったコンテキストマネジャのコード "DBcm.py" と、本来のアプリのコード "vsearch4web.py" の位置付けをしっかり意識することが必要。

(課題 2) contextlib

この本では標準ライブラリの contextlib を使わないでコンテキストマネジャを作成しており、 contextlib   についてはその名称を紹介する程度。この辺りは後で自分で勉強した方が良さそう。

(課題 3) 追加のアプリ拡張

せっかく追加の SQL 文の紹介もあるのですが、アプリにはその機能は取り込まれていませんので、自力で Flask / jinja 2 の練習がてら機能拡張しようと思うが今後の宿題。

10章 - 関数デコレータ

5章で一度簡単な説明だけで済まされていた関数デコレータの解説。ここでは新たに「各ページの処理の際にログイン状態をチェックする」という機能を追加する。単に各ページでログインチェック関数を呼び出すのではなく既存の関数コードを変更せずに既存の関数に機能を追加する方法を学ぶ。
但し、この章の構成としては前半 20ページは Flask の session の解説とテスト、後半 30ページがようやく関数デコレータの解説とテストなので今自分が何を学んでいるのか意識した方が良い。
具体的には以下のようにいくつかのテストアプリを書きながら新しい機能を確認し、最終的に今まで機能強化してきた Web アプリ "vsearch4web.py" に反映する。本を読む際に今どのコードを扱っているかを意識しないと訳がわからなくなる。

"quick_session.py" - session に状態を格納する単機能テストアプリ

最初は「Web アプリにおける(ログイン)状態」の確認方法としてセッションを確認し、テストコードとして "quick_session.py" を作成。ここでは Flask の "session" と共に関数デコレータで url に指定したユーザー名を関数で受け取る方法も確認する。

"simple_webapp.py" (1) - 複数ページからなる Flask テストアプリ。

後でデコレートされるプログラム。

デコレータを書く準備テストプログラムを作成する

さらに一旦デコレータを書くために必要なコーデディング方法を確認する。 1「関数の作成」、2「関数に引数として関数を渡す方法」、3「関数から関数を返す方法」4「任意の数のあらゆる型の関数引数を処理する方法 *arg, *kwarg, **」。

"checker.py" 関数デコレータ checked_logged_in をもつモージュールを作成する 
  • デコレータは関数

  • デコレータは引数としてデコレートされる関数をとる

  • デコレータは新たな関数を返す

  • デコレータはデコレートされる関数のシグネチャをもつ

上記の対応をしたデコレータ checked_logged_in 用のモジュール "checker.py" を作成する。

"simple_webapp.py" (2) - デコレータ checked_logged_in を使うように修正する

作成したデコレータのテストを行う。

汎用的なデコレータのコードテンプレート

今後デコレータを自分で作成するために必要なコードテンプレートが示されている。

Web アプリ "vsearch4web.py" をデコレートする

ようやくここでメインのアプリにデコレータを適用してログイン状態の確認をできるようにする。

11章 - 例外処理

いくつかのケースを想定するが、この章の対応範囲(例外処理)で対応できるものとそうでは無いものも洗い出している。下記の中で (1), (3) に対して try/except を設定する。

  • (1) データベース接続上の問題
  • (2) Web アプリ(SQLインジェクション、クロスサイトスクリプティング)に関しては Flask / Jinja2、DB-API まかせでそれ以上の言及はなし。
  • (3) 関数呼び出し失敗

モジュールとしては Web アプリ本体 "vsearch4web.py" 内の try/catch だけではなく、"DBcm.py" 内でカスタム例外を投げるようにし、"vsearch4web.py" 内の vie_the_log 関数側にカスタム例外を処理する except ブロックと追加する。

try/except も蜜結合となるコードを避ける
(課題) 長時間処理の対応

これは次章 (11 3/4章) でスレッドで対応

11 3/4章 - スレッド入門

本来なら「11章」の次は「12章」だが、丸々 1章分の分量がないので「11 3/4章」としているの?
最初に Python 標準ライブラリの並列処理の一つのスレッド処理を確認する。しかし、呼び出し側関数がスレッドより先に終了するケースはリソースが回収され残されたスレッド側で例外が発生してしまう。
対応として、Flask の copy_current_resuest_context デコレータを利用する。

12章 - 高度なイテレーション (内包表記、ジェネレータ)

この章は Web アプリとは関係のない単体で動くアプリを作ります。基本的には for ループのアプリを作成し、それを内包表記に変更していく、という進行。


ということで、もう一度ポイントポイントで読み直す価値はありそうです。