python 技術書 読書感想

【技術書感想】きれいなPythonプログラミング ~クリーンなコードを書くための最適な方法

スポンサーリンク

概要

「きれいなPythonプログラミング ~クリーンなコードを書くための最適な方法」を読んだので感想を書こうと思います。

Beyond the Basic Stuff with Python:Pythonプログラミングの入門・基本をマスターしたら次のステージへと踏み出そう! パイソニック(Pythonic)なコードを書くことを学び、より優れたプログラマーになる手法を伝授します。

 

スポンサーリンク

書籍概要

どんな本?

誰にでも読みやすく。Clean Code を実践しよう

自分の書いたコードに自信を持てるプログラマーになろう

[誰にでも読みやすい 広く公開できるコードを書こう]
本書ではきれいなコード(Clean Code)を書くために、コマンドライン、コード整形、型チェッカー、リンター、バージョン管理 などのその道のプロが利用しているツールを詳解し、Pythonプログラミングスキルを向上させる方法を学びます。

[Clean Codeを実践するツールを活用できるようになろう]
開発環境のセットアップ、変数の命名方法、読みやすさ向上のための最適な方法 を紹介します。

[オブジェクト指向設計を理解し アルゴリズムを活用しよう]
コードの公開に必要となるドキュメントの作成や書式の統一、またパフォーマンスの測定、オブジェクト指向プログラミング、コーディングインタビューで一般的に使用されるオーダー記法(Big O)について説明します。

本書の後半では2つのコマンドラインのゲーム「ハノイの塔(ロジックパズル)」と「四目並べ(タイル落としゲーム)」を作りますが、書いたゲームのコードが本書の「最適な方法」でプログラミングされているかを確認してみましょう。

  • Al Sweigart (著), 岡田佑一 (翻訳)
  • 2022年02月 発行
  • 384ページ
  • 定価3,608円(税込)

 

スポンサーリンク

内容のまとめと感想

タイトルの通り、きれいなPythonコードを書くためのノウハウや手法を説明する書籍です。

コード自体に関する説明だけではなく、クリーンなコードを書くために必要になる、各種ツールや考え方もカバーした幅広い内容を取り扱っているのが特徴です。

とりあえずコードを書ける状態から卒業して、綺麗なでクリーンなコードを書くためにどういったことが必要なのかを総合的に学べるようになっています。

 

特徴

Pythonの基本文法は理解している前提

基本的にPythonをある程度書けるエンジニアを想定して書かれているので、基本的な文法や構文に関する説明はありません。

Python自体を学びたいという人は、別途入門書等を読むことをオススメします。

 

インタラクティブシェルでの実行

コードの実行方法に関しては、基本的にインタラクティブシェルによる対話的な実行になっています。

ですのでIDEや環境に依存せずに極力汎用的な形での紹介になっています。

 

幅広いテーマ

コードの書き方だけではなく、エラー(トレースバック)の読み方やエラー内容に関しての、インターネット上のコミュニティでの質問方法など、プログラマーとして知っておきたい基本的なノウハウに関しても書かれていて面白いです。

その他にも、リンター、Docstring(ドキュメント)などなど、クリーンで他者が理解できるコードを書くためのツールに関してもカバーしています。

その他にもGitによるバージョン管理に関しても1つの章を割いていたりします。(個人的にはちょっといらない気が・・・。)

 

初級者〜中級者向け

本書でも書かれていますが、より深い内容を学びたい場合は「Effective Python」や「Fluent Python」といった評判の高い書籍を挙げています。

さらなるステップアップを目指したい場合にはこういった書籍に取り組むのが良いと思います。

GoogleでPythonを使ったさまざまなサービスを立ち上げ、Pythonを知り尽くした著者による、Pythonエキスパート必携書の改訂版です。第2版ではPython 3.8に対応、データ構造、内包表記とジェネレータ、性能、デバッグについての章を新たに追加するなど、第1版の59項目を大幅に改訂し、90項目にわたってベストプラクティス、ヒント、落とし穴の避け方だけでなく、新機能の使い方などのノウハウを解説します。
一歩先行くパイソニスタを目指す人のためのPython解説書。Pythonはシンプルです。使い方を覚えるのも簡単で生産性を短期間で高めることができます。しかしこれは、Pythonに備わっている豊富な機能のほんの一部しか使っていないということでもあります。本書では、とても有用なのにあまり使われていないPythonの特徴的な機能を活用し効果的で慣用的なPythonコードを書く方法について解説します。

 

オブジェクト指向関係の話題は後半に集約

クラスを使用したオブジェクト指向プログラミングに関しての話題は、後半の数章に集約されています。

それまでは基本的に関数ベースのシンプルなサンプルになっているので、クラスベースのPythonに慣れていないという人でも読むのに困らないようになっています。

 

具体的なコードを使用したリファクタリング

「ハノイの塔」と「四目並べ」という具体的なゲームを用いて、本書で学んだノウハウを適応してどうコードを綺麗にしたら良いかを学ぶことができます。

挙げているゲームのコード自体もシンプルでコード量も多くないので、理解するのには良い教材だと思いました。

 

まとめ

最初はPython版クリーンコード的なものをイメージしていましたが、コードの書き方だけでなく各種関連ツールやパフォーマンス向上、オブジェクト指向など、非常に幅広いテーマを取り扱っていて面白かったです。

取り扱う内容自体が幅広くなりすぎて、個々の説明が少し薄くなってしまっている感もありますが、Pythonというテーマでエンジニアとして知るべき各種ノウハウが凝縮されていて良い本だと思いました。

 

個人的なメモ

怪しいコード集

関数やモジュールにすべきクラス

Pythonでもクラスによる実装が可能なため、単純な実装でもわざわざクラスによる実装になりがちであるが、簡単に関数で実装できるなら関数で実装すべき。

下記はサイコロによるランダムな数値を返すクラスによる実装。

 

実際に必要なのは1~6のランダムな数値を返すということなので、関数で実装すれば下記の1行で済む。

 

内包表記の中に内包表記がある

配列をループ処理する際に、pythonでは内包記法を用いることで、1行でシンプルに書くことができる。

5の倍数の数値以外を文字列として格納する例:

 

ただし、ネストした配列にたいして書くと、逆に読みにくくなってしまうのでやめるべき。

片側はいったんforループで回した上で、内包記法を用いるのがわかりやすい

パイソニックなコードを書こう

range()ではなくenumerate()を使う

forループ内でindexへのアクセスが必要となる際には、rangeによる記法の代わりに、enumerate()を用いることですっきりとしたコードになる。

 

バックスラッシュが多い文字列の場合にはraw文字列を使う

パスを文字列で扱う場合などに、通常の文字列だとエスケープのために¥¥といった形で表現しなければいけないが、rを先頭に付与してraw文字列として扱うとそのまま記載できてすっきりとする。

 

switchの代わりに辞書を使う

pythonにはswitch文がないため、複数の条件をifを用いて書くと冗長になる。

代わりに辞書を使って書くとシンプルなコードになる。

 

代入演算子と比較演算子の連結

範囲条件を指定したい際に、andで2つの条件を記載するのではなく、比較演算子の連鎖させる書き方を用いることでシンプルになる。

下記のような複数の値が同一かのチェック処理も連鎖を用いることでシンプルに書ける

 

Pythonのよくある落とし穴

copy.copy(),copy.deepcopy()を使用せずに可変型の値をコピーしない

他のプログラム言語でも同じだが、値型でない変数を=で代入すると、アドレスのコピーとなる。

そのため、そのまま値変更すると代入元となる値も変化してしまう。

copy.copy()で参照ではなく、値自体をコピーすることができる。

 

ただし、リスト内に値型以外のものが格納されていると、そちらはアドレスのコピーが入ってしまう。

そのようない場合には、copy.deepcopy()を使用することで、中の要素も含めて完全にコピーが作成される。

パフォーマンスは落ちるが、わざわざ要素が値型以外もあるのかを判断するのは大変なのでdeepcoyを常に使用するのが楽。

 

文字列連結で文字列を作らない

他のプログラム言語でもよく上がる話題だが、文字列の連結を大量に繰り返す場合には文字列は連結しないほうが良い。

文字列自体は実は代入の度に新しい文字列オブジェクトが生成されるため、大量に繰り返すと文字列オブジェクトを大量に作ることになってしまい、パフォーマンス上よろしくない。

リストに格納しておいて、最後にまとめて結合する方法が良い。

 

良い関数の書き方

可変長関数を作成するために*を使う

関数の引数に*を付与することで、可変長の引数を定義できる。

*args自体はタプルとして扱われる。

可変長引数を使わなくても、arrayを引数として渡せば同様なことを実現はできるので、どのような使い分けをすべきか?

使う側が自然に使えるように意識して使い分ける。

例1:sum関数はarrayの方が望ましい。sum(2, 3, 6)と書くよりも、sum(array)といった形で配列を渡す方が使い方として多いと推測される。

例2:print関数は可変長の方が望ましい。print("ABC", "AAA")と書く方が一般的で、表示するのにわざわざarrayの文字列を生成するのは不自然。

 

どちらにも対応させる方法も可能。

 

**を使って可変長の関数を作る

*がタプルなのに対して、**とすることで辞書(dict)と同じ可変長の引数として扱われる。

呼び出し側はdict形式で渡さなくても良いので、便利である。

 

コメント、docstring、型ヒント

リストや辞書型に型ヒントを設定する

Listなどに対して型ヒントを使用するにはtypingモジュールを利用する。

 

パフォーマンスの測定とオーダー記法

cProfileプロファイラー

関数の処理時間を簡単に計測することができる。

実行結果っとして、各関数の実行時間などが表示される。

 

オブジェクト指向プログラミングと継承

多重継承

多くのプログラミング言語は多重継承ができないが、Pythonでは多重継承(ミックスイン)が可能になっている。

 

継承元でメソッドが重複した場合には左側に書かれた継承クラスの処理が実行される。

 

パイソニックなオブジェクト指向

プロパティ

Pythonにはアクセススコープが無いため、クラス内の属性に関しても自由にアクセスできる。

そのため、一般的に_から始まる属性やメソッドを作ることでスコープを示すことになる。

ただしプロパティを使用することで、属性の直接的なアクセスによって想定外の動作を防ぐことができる。

Setterを使用することで、エラーチェック処理を実装することができる。

 

-python, 技術書, 読書感想

© 2022 nobu blog Powered by AFFINGER5