『退屈なことはPythonにやらせよう』学習メモ(前半のみ)

まえがき

  • プログラミングは創造的な活動
    • レゴブロック
    • どんな外観の城を作りたいか基本構想を抱き、手持ちのブロックを確認する
    • 作業
    • 最後におめかしすることもある
    • プログラミングがほかと異なるのは、必要な材料がすべてコンピュータの中にあること

Ch01 Python入門

  • snake case
  • input()
  • print()
  • len()
  • str()
  • int()
  • float()
  • 式は値と演算子で構成され、ひとつの値になるまで評価する。
  • 式は評価してひとつの値となる。文は値にならない。

Ch02 フロー制御

  • Boolean
    • True, False
  • 比較演算子
    • ==, !=, <, >, <=, >=
  • ブール演算子
    • and, or, not
  • フロー制御の構成要素
    • 条件式
    • コードのブロック
  • プログラム実行
  • フロー制御文
    • すべてコロン(:)で終わり、次のブロックが続く
      • ブロックが続かなければコロンはない
    • if
    • else
    • elif
    • while
    • break
    • Ctrl+Cで無限ループを抜ける
    • True, Falseとみなされる値
      • 0, 0.0, ''は条件式として用いるとFalseとみなされ、ほかの値ならTrueになる
    • for, range()
      • range(5)
      • range(0, 10, 2)
      • range(5, -1, -1)
  • モジュールのインポート
    • import random, sys, os, math
    • from random import randint
  • sys.exit()

Ch03 関数

  • def hello():
  • return value
  • None
    • Pythonはreturn文のない関数定義には末尾にreturn Noneを追加する
    • NoneType
  • print('Hello', end='')
    • 文字列の末尾をendで指定
  • print('cats', 'dogs', sep=',')
  • global eggs
  • ローカル関数にローカル変数への代入分があれば、その変数はローカル変数として扱われる
    • グローバル変数が同じ名前であったとしても、同じスコープで参照するよりあとにローカル変数を定義している場合は、エラーになる
  • try:
  • except ZeroDivisionError:
  • 関数は、コードを論理的なグループに分割する基本的な手段

Ch04 リスト

  • リスト
    • list = [1,2,3,4]
    • list[-1]は4
    • list[0:3]は[1,2,3]
    • len(list)は4
    • [1,2,3]+['A','B','C']もできる
    • ['X','Y']*2は['X','Y','X','Y']
    • del list[2]
    • list = で初期化して、list = list + [value]でリストに追加していける
    • 2 in [1,2,3]
    • 累積代入演算子
    • bacon = ['A']
    • bacon *= 3は['A','A','A']
  • メソッド
    • index()
    • spam.append('A')
    • spam.insert(1,'A')
    • spam.remove('A')
      • 最初の値だけ消す
    • spam.sort(reverse=True)
      • ASCIIコード順。大文字の後に小文字。
    • spam.sort(key=str.lower)
      • 通常のアルファベット順ですべて小文字としてソート
  • 字下げルールの例外
    • リストの閉じ角括弧
    • \
  • リスト風のデータ型: 文字列とタプル
    • リストはミュータブルだが文字列はイミュータブル
      • 文字列の変更は、スライスと連結を使って元の文字列の一部から新しい文字列の生成が必要
    • タプルもイミュータブル
      • eggs = ('hello', 42, 0.5)
      • 順序づけられた値の並びを変更不可にしたいとき
      • コードが若干高速になる
    • list(), tuple()
  • 参照
    • リスト、辞書型は参照をコピーする
    • copy.copy()
      • 異なるリストを作る
      • cheese = list(spam)でも同じ
    • copy.deepcopy()
      • リストを含むリストをコピーする
  • 問題
    • int('3'*2)は33
    • 要素1つのタプル: (42,)のようにカンマが必要
  • 演習
    • カンマ付け
      • ', '.join(lst[:-1])
        • 文字列でリストを結合できる
    • グリッド
      • for y in range(len(grid[0]))

Ch05 辞書とデータ構造

  • 辞書型
    • my_cat = {'size': 'fat', 'color': 'gray', 'disposition', 'loud'}
    • 順序が不定
      • K-Vが同じなら別の順序で辞書を作っていても同じものになる
    • keys()→dict_keys
    • values()→dict_values
    • items()→dict_items
      • K-Vのタプルを返す
      • for k, v in spam.items()
    • get()
      • キーと、キーがないときに使う値も引数に取る
    • setdefault(key, defaultvalue)
      • キーがないときだけ登録する
      • キーが確実に存在するようにするための便利な方法
      • count.setdefault(character, 0)
      • count[character] = count[character] + 1
  • 整形表示
    • pprintモジュール
    • pprint.pprint(list)
      • リストや辞書が入れ子になっているときに特に便利
      • print(pprint.pformat(list))も同じ
  • データ構造で実世界の物体をモデル化する
    • 代数的記法
    • リストや辞書が有用
    • 三目並べ
      • 各マスにキーを振る
      • データ構造を作り、それを解釈して表示するコードを書くことで、モデル化したプログラムを書くことができる
  • 問題
    • 'cat' in spamと'cat in spam.keys()は同じ
      • in演算子はkeyに含まれるか調べる

Ch06 文字列操作

  • 文字列の操作
    • 文字列リテラル
      • ダブルクォート
        • 文字列にシングルクォートを含められる
      • エスケープ
        • \
        • ', ", t(タブ), n(改行), \
      • raw文字列
        • r''
        • エスケープを無視
      • 3連クォートによる複数行文字列
      • 複数行コメント
        • """ """
    • 文字列のインデックスとスライス
    • 文字列に対するinとnot in演算子
      • 大文字と小文字を区別して正確に調べる
  • 便利な文字列メソッド
    • upper(), lower(), isupper(), islower()
      • 新しい文字列を返す
    • isX
      • isalpha(), isalnum(), isdecimal(), isspace()(スペース、タブ、改行のみ), istitle()(大文字から始まって残りすべて小文字の英単語のみ)
      • validationに使える
    • startswith(), endswith()
    • join(), split()
      • ', '..join(['a', 'b', 'c'])
      • 'My name is Simon'.split(' ')
        • デフォルトではスペースやタブ改行などの空白文字で分割
        • 複数行の文字列の分割に使われる
    • rjust(), ljust(), center()
      • 'Hello'.rjust(10, '*')
        • 10文字の中で'Hello'を右揃え
        • 第2引数は埋める文字
      • 表形式のデータを正しくスペースを空けて表示するときに特に便利
    • strip(), rstrip(), lstrip()で空白文字を除去
    • pyperclip moduleで文字列をコピペ
  • プロジェクト: パスワードロッカー
    • プログラムの設計とデータ構造
      • 辞書でアカウント名とパスワードを関連付け
    • コマンドライン引数を扱う
      • sys.argv
    • 正しいパスワードをコピーする
  • プロジェクト: Wikiで箇条書きのマークアップ

Part 2 処理の自動化

Ch07 正規表現によるパターンマッチング

  • 正規表現を用いないテキストパターン検索
  • 正規表現を用いてテキストパターンを検索
    • Regex objectを生成
      • import re
      • re.compile()に正規表現パターンを表す文字列を渡すと、Regexパターンオブジェクトが返ってくる
    • Regex objectとマッチ
      • mo = obj.search('abc')
      • Match objectかNoneを返す
      • group()でマッチしたテキストを返す
  • 正規表現によるパターンマッチの続き
    • 丸括弧を使ったグルーピング
      • group(1)など整数を渡すとマッチした文字列の異なる部分を取得できる
        • 何も渡さないか0を渡せばマッチした文字列全体を返す
      • groups()で、すべてのグループを一度に取得する(タプルを返す)
    • 縦線を使って複数のグループとマッチ
      • グループを分けることで部分的にORでマッチできるようになる
    • 疑問符を用いた任意のマッチ
      • 0回または1回
    • アスタリスクを用いた0回以上のマッチ
    • プラスを用いた1回以上のマッチ
    • 波括弧を用いて繰り返し回数を指定
      • (Ha){3,5}
        • HaHaHa, HaHaHaHa, HaHaHaHaHa
      • {3,}, {,5}もあり
  • 貪欲マッチと非貪欲マッチ
    • ?をつけないと最も長いもの(貪欲)、つけると最も短いもの(非貪欲)にマッチする
  • findall()
    • 見つかったすべての文字列を(グループに対応したタプルの)リストで返す
  • 文字集合
    • \d: 0~9の数字
    • \w: 文字、数字、下線
    • \s: スペース、タブ、改行
    • それぞれ大文字はそれら以外を表す
  • 独自に文字集合を定義
    • [0-5], [aeiouAEIOU], [a-zA-Z0-9]など
    • 角括弧の中は正規表現の記号は解釈されない→エスケープ不要
    • ^をつけると補集合になる
  • キャレット(^)とドル記号
    • 先頭、末尾にマッチ
    • 全体の指定にも使える
  • ワイルドカード文字
    • ドット
    • ドットとアスタリスクであらゆる文字列をマッチ
      • 非貪欲なら/*?
    • ドット文字を改行とマッチさせる
      • re.DOTALLをre.compile()の第2引数として渡す
  • 大文字・小文字を無視したマッチ
    • re.IGNORECASE, re.Iを渡す
  • sub()で文字列を置換
    • 置き換える文字列と検索置換対象の文字列を渡す
    • マッチ部分を使うときは\1, \2のようにグループの番号を使う
      • ()を使うことで使いたい部分のグループを作る
  • 複雑な正規表現の管理
    • re.VERBOSEを渡すことで、正規表現中の空白やコメントを無視 → 複雑な表現にコメントをつけられる
  • re.IGNORECASEとre.DOTALLとre.VERBOSEを組み合わせる
    • |を使う
  • プロジェクト
    • 新しいプロジェクトに取り組むときは、まずは全体像から
      • 入力、処理、出力
    • テキスト検索でできること
      • 電話番号、アドレス、URL、日付フォーマットの置換、センシティブ情報の削除、誤記の発見
  • 問題
    • 3桁ごとにカンマがある数字にマッチ: ^\d{1,3}(,\d{3})*$など
    • 大文字で始まり小文字が続く1単語、スペース、特定の文字列: [A-Z][a-z]*\sNakamoto
  • 演習
    • 強いパスワードの検出
      • 複数の正規表現でチェックして、すべて通ればOKとすればよい
    • 正規表現を使ったstrip()

Ch08 ファイルの読み書き

  • ファイルとファイルパス
    • os.path.join()で文字列をパスのフォーマットで結合する
    • os.getcwd(), os.chdir()
    • os.makedirs()
  • os.pathモジュール
    • import os
    • 絶対パス相対パスの操作
      • os.path.abspath(path)
      • os.path.isabs(path)
      • os.path.relpath(path, start)
      • os.path.dirname(path)
        • 最後のパス区切り記号より前を返す
      • os.path.basename(path)
        • 最後のパス区切り記号より後ろを返す
      • os.path.split(path)は上の2つをタプルで返す
      • '/usr/bin'.sprit(os.sep)でパスを個々の要素に分割したリストになる
    • ファイルサイズとフォルダ内容を調べる
      • os.path.getsize(path)
        • バイト単位
      • os.listdir(path)
        • ファイル名とフォルダ名のリスト
    • パスを検査する
      • os.path.exists(path)
      • os.path.isfile(path)
      • os.path.isdir(path)
  • ファイルの読み書きの方法
    • open()でファイルを開く
      • 読み込みモードで開く
        • 'r'で明示
      • Fileオブジェクトを返す
    • ファイルの内容を読み込む
      • read()
      • readlines()
        • 行ごとのリスト
    • ファイルを書き込む
      • 'w'
        • 上書きして最初から書き直す
      • 'a'
        • 追記
      • open()の第1引数に渡したファイルがなければ、新しい空のファイルを作る
      • close()
      • write()
        • 改行も自分で追加する必要がある
  • shelveモジュールで変数を保存する
    • シェルフの値を辞書のように変更できる
    • open(), close()
    • keys(), values()
      • リスト風オブジェクトを返す
      • リストが必要ならlist()に渡す必要
  • pprint.pformat()を使って変数を保存する
    • データ構造の文字列化
    • 基本はshelveモジュールの方が便利
    • .pyファイルに保存すれば、テキストエディタで読んだり修正できるというメリットはある
  • プロジェクト: ランダムな問題集ファイルを作成
  • プロジェクト: マルチクリップボード