「エキスパートPythonプログラミング 改訂4版」を読んだ
 tenkei
tenkei第一章
Python の歴史や取り巻く環境の説明。
Slackコミュニティとニュースレターの紹介が良かった。Slackコミュニティに参加し、PythonWeeklyのニュースレターを購読してみた。
また、Python にも Awesome レポジトリ(https://github.com/vinta/awesome-python )があることを知った。
 tenkei
tenkei第二章
Python の開発環境について。
多くのOSでは標準コンポーネントとして Python がインストールされている。が、バージョンが少し古い。
また、パッケージについては PyPI のものを使うべきで、pip コマンドを利用してインストールする。
$ python3 -m ensurepip
pip コマンドでインストールしたものは site-packages ディレクトリに保存される。
# 確認
$ python3 -m site
しかし、 pip でインストールを行うと、グローバルな site-packages に保存されてしまう。これは避けるべき。
そこで利用できるのが環境分離。そのための機能として、 Python には venv というものがある。
また、依存パッケージの管理には Poetry が利用できる。Poetry の設定ファイルは pyproject.toml を作成する。
それ以外には、Docker や Vagrant を使った仮想環境の作成方法や、IPythonの利用方法など。
 tenkei
tenkei第三章
Python3での新機能について。
辞書のマージと更新の演算子
演算子によってリストやタプル同士を結合したり、要素を追加できる。
[1,2,3] + [4,5,6]
value = (1,2,3)
value += (4,5,6)
セット同士の積、和、差、対称差を求めることもできる。
{1,2,3} & {4,5} # {1}
{1,2,3} | {1,4} # {1,2,3,4}
{1,2,3} - {1,4} # {2,3}
{1,2,3} ^ {1,4} #{2,3,4}
辞書同士の結合とインプレース更新も可能。
{‘a’:1} | {‘a‘:3, ‘b’: 2} # {‘a’: 3, ‘b’: 2}
my_dict = {‘a’: 1}
my_dict |= {‘a’: 3, ‘b’: 2} # {‘a’: 3, ‘b’: 2}
以下のようなアンパックによる結合をする必要はもうない。
a = {‘a’: 1}; b = {‘a’:3, ‘b’: 2}
{**a, **b} 
代入式(セイウチ演算子)とは式だけど変数に値を割り当てることができる。
isOk = True
if isOk:
  return
を
```py
if isOk = True:
  return
のようにスッキリと書ける。以下のような場合にも有効。
first_name = “foo”; last_name = “bar”
user = {
  “first_name”: first_name,
  “last_name”: last_name,
  “display_name”: f”{first_name} {last_name}”
}
代入式を使うと以下の通り。
user = {
  “first_name”: (first_name := “foo”),
  “last_name”: (last_name := “bar”),
  “display_name”: f”{first_name} {last_name}”
}
構造的パターンマッチ
構造的パターンマッチとは match-case 構文。
ちなみに match はソフトキーワード、つまり予約語ではないので普通に変数名としても使える。
以下は、FizzBuzz問題を構造的パターンマッチで実装した例。
for i in range(100):
    match (i % 3, i % 5):
        case (0, 0): print(“FizzBuzz”)
        case (0, _): print(“Fizz”)
        case (_, 0): print(“Buzz”)
        case _: print(i)
最後のアンダースコアはワイルドカードパターン。
型ヒントのジェネリクス型
typing の Dict, List, Tuple, Set, FrozenSet は非推奨となっており、将来削除される。Python3.9以降では、組み込みのジェネリック型を使って型ヒントを指定するべき。
Union型と|演算子
Union型を表現する場合に、def foo(key: string | bytes): のように書ける。ジェネリクス型と異なり、typingのUnionが非推奨になっているわけではない。
位置専用引数
Pythonで関数に引数を渡すには、2つの方法がある。位置引数とキーワード引数。
以下のように書くと、引数の渡し方をより限定できる。
def concatenate(first: str, second: str, /, *, delim: str):
    return delim.join([first, second])
/ より前は位置引数、* より後はキーワード引数。
zoneinfo モジュール
以下、ZoneInfoモジュールを利用して、タイムゾーン対応の datetime オブジェクトを作成する例。
from datetime import datetime
from zoneinfo import ZoneInfo
dt = datetime(2020, 11, 28, tzinfo=ZoneInfo(“Asia/Tokyo”))
その他
以前からPythonにあるけど、特筆すべき機能。
- f-stringは便利
- 数値リテラルにはアンダースコアが使える(例: 1_000_000)
- randomモジュールの生成する乱数は条件によっては予測可能なので、パスワードやトークンなどのセキュリティ目的に使うべきではない。セキュリティ目的なら、secrets モジュールがピッタリ。
 tenkei
tenkei第四章
Pythonとほかの言語の比較。
オブジェクト指向プログラミング
PythonはKotkinと似ている。
Pythonでは多重継承が可能だが、良いプラクティスかは疑問。また、private/publicといったアクセス制御キーワードを提供しない。
クラスインスタンスの初期化
Pythonではクラスプロパティとして定義せずとも、 __init__ メソッドから初期化できる。
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
演算子のオーバーロード
Pythonの数多くの演算子は、dunderメソッドとしてエクスポーズされている。
例えば、+ 演算子は __add__ としてアクセス可能。そしてこれらは上書きすることができる。
class DoubleAdder:
    def __add__(a: int, b: int):
        return (a+b)*2
double_adder = DoubleAdder()
double_adder.add(1,2)  # 6 
map, filter, reduce
map, filter は import せずに利用可能だが、reduce は functools から import する。
ジェネレーター
試行回数が無限のような処理では、ジェネレータが有効。
def fibonacci():
    a, b = 0, 1
    while True:
        yield b
        a, b = b, a + b
>>> fib = fibonacci()
>>> next(fib)
1
>>> next(fib)
2
デコレータ
関数に加えて、あらゆる callable なものに付与可能。
デコレータは単なるシンタックスシュガー。
@decorate_this
def decorated_function():
    pass
def decoreted_functions():
decoreted_functions = decorate_this(decoreted_functions)
列挙型
Enum や Flag など。値が固定で、グローバルに1度だけ定義されるような場合に有効。
もし値自体に意味がない場合は、auto を利用するとよい。
from enum import Enum, auto
class OrderStatus(Enum):
    PENDING = auto()
    PROCESSING = auto()
    PROCESSED = auto()
辞書型や named tuple は単なるデータ構造なので、何度でもインスタンスを作れる。
 tenkei
tenkei第5章 インターフェイス、パターン、モジュール化
zope.interface
昔に人気だったが今では使われなくなってきているライブラリ。インターフェイスの定義や検証が可能となる。
関数アノテーションや抽象基底クラス
抽象基底クラス(ABC)について。
from abc import ABC, abstractmethod
class DummyInterface(ABC):
    @abstractmethod
    def dummy_method(self): ...
    @property
    @abstractmethod
    def dummy_property(self): ...
型アノテーション
typing を利用して型アノテーションを作成可能。mypyなどを利用すれば、静的型解析が可能。
制御の反転と依存性注入
伝統的なアーキテクチャでは、上位のレイヤーが下位のレイヤーを呼び出す。
制御の反転(Inverse of Control)はその逆。ポリモーフィズム、関数を引数で渡す、デコレータ、クロージャなど。デザインパターンではなく、設計の特性。
制御の反転の中でも最も重要なものが、依存性注入(Dependency Injection)。これによって、疎結合が実現できる。インターフェースは共有するが、実装同士は独立することができる。
 tenkei
tenkei