[
  {
    "path": ".github/workflows/mkdocs.yml",
    "content": "name: MkDocs\n\non:\n  push:\n    branches:\n      - master\n    paths:\n      - mkdocs.yml\n      - docs/**\n\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Checkout the repository\n        uses: actions/checkout@v2\n\n      - name: Configure Git\n        run: |\n          git config user.name github-actions\n          git config user.email github-actions@github.com\n          git fetch origin gh-pages\n\n      - name: Install MkDocs\n        run: |\n          python3 -m pip install setuptools\n          python3 -m pip install -r requirements.txt\n\n      - name: Deploy HTML files\n        run: python3 -m mkdocs gh-deploy\n"
  },
  {
    "path": ".gitignore",
    "content": "site/\n\n# Created by https://www.gitignore.io/api/macOS\n# Edit at https://www.gitignore.io/?templates=macOS\n\n### macOS ###\n# General\n.DS_Store\n.AppleDouble\n.LSOverride\n\n# Icon must end with two \\r\nIcon\n\n# Thumbnails\n._*\n\n# Files that might appear in the root of a volume\n.DocumentRevisions-V100\n.fseventsd\n.Spotlight-V100\n.TemporaryItems\n.Trashes\n.VolumeIcon.icns\n.com.apple.timemachine.donotpresent\n\n# Directories potentially created on remote AFP share\n.AppleDB\n.AppleDesktop\nNetwork Trash Folder\nTemporary Items\n.apdisk\n\n# End of https://www.gitignore.io/api/macOS\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2025 Ida Kenichiro\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# ゼロから学ぶ Python\n\nこのリポジトリはオンライン学習サイト[ゼロから学ぶ Python]のソースコードリポジトリです。\n\n## 必要なもの\n\nソースコードから HTML ページを生成するには下記のものが必要です。\n\n- Python3\n\n## ビルド\n\nHTML を生成するには下記のコマンドを実行してください。\n\n```shell\n$ pip install -r requirements.txt\n$ mkdocs build\n```\n\nビルド結果をブラウザ上で確認するには次のコマンドを実行します。\n\n```shell\n$ mkdocs serve\n```\n\nhttp://localhost:8000 にアクセスすると Web ページが表示されます。\n\n[ゼロから学ぶ Python]: https://rinatz.github.io/python-book\n"
  },
  {
    "path": "docs/ch01-01-installation.md",
    "content": "# インストール\n\nPython 開発に必要な下記のツールをインストールします。\n\n- Python\n- Visual Studio Code\n\n## Python\n\n各プラットフォームに合わせて Python のインストール手順が下記サイトにまとまっていますのでインストールをしてください。\n\n- [macOS](https://www.python.jp/install/macos/install_python.html)\n- [Windows](https://www.python.jp/install/windows/install.html)\n\nコマンドを打って Python が正しくインストールされたかどうかを確認します。\n\n=== \"macOS\"\n\n    ターミナル上で下記コマンドを実行します。\n\n    ```shell\n    $ python3 --version\n    ```\n\n    バージョンが表示されれば成功です。\n\n=== \"Windows\"\n\n    コマンドプロンプト上で下記コマンドを実行します。\n\n    ```shell\n    $ py -3 --version\n    ```\n\n    バージョンが表示されれば成功です。\n\n## Visual Studio Code のインストール\n\nVisual Studio Code (VS Code) はエンジニアの間で人気のエディタです。\n拡張機能を取り入れることで見た目の変更や機能追加などを自由にカスタマイズできるのが特徴です。\n\n下記のサイトで VS Code をダウンロードし、インストールをしてください。\n\n!!! Info \"VS Code\"\n    [https://code.visualstudio.com/](https://code.visualstudio.com/)\n\n次に Python の開発環境を整えるための VS Code 拡張機能をインストールします。\n\n| 拡張機能                                  | 概要                        |\n|-------------------------------------------|-----------------------------|\n| [Python extension for Visual Studio Code] | Python 開発のための基本機能 |\n| [Pylance]                                 | コード補完                  |\n| [Visual Studio IntelliCode]               | オートコンプリート          |\n\n[Python extension for Visual Studio Code]: https://marketplace.visualstudio.com/items?itemName=ms-python.python\n[Pylance]: https://marketplace.visualstudio.com/items?itemName=ms-python.vscode-pylance\n[Visual Studio IntelliCode]: https://marketplace.visualstudio.com/items?itemName=VisualStudioExptTeam.vscodeintellicode\n\nインストールは VS Code を起動した後、左側にあるペインから拡張機能のタブを選択し、\nインストールする拡張機能を検索してインストールします。\n\n[![](img/vscode-01.png)](img/vscode-01.png)\n"
  },
  {
    "path": "docs/ch01-02-hello-world.md",
    "content": "# Hello, World!\n\n標準出力に `Hello, World!` と出力する簡単な Python プログラムを書いてみます。\n\n---\n\nまずターミナル上で `hello` というディレクトリを作成し、それを VSCode で開きます。\n\n```shell\n$ mkdir hello\n$ cd hello\n$ code .\n```\n\n[![](img/vscode-02.png)](img/vscode-02.png)\n\n---\n\n次にファイルの新規作成のアイコンを押して `hello.py` という名前のファイルを作成します。\n\n[![](img/vscode-03.png)](img/vscode-03.png)\n\n---\n\nファイルを作成してそのファイルを開くとウィンドウの左下に使用する Python のバージョンが表示されます。\nこのバージョンがインストールした Python のバージョンと異なる場合は Python のバージョンをクリックすると\n使用する Python を変更することができます。\n\n[![](img/vscode-04.png)](img/vscode-04.png)\n\n複数の Python をインストールしている場合にはこのようにして使用する Python を変更してください。\n\n---\n\nここまでできたら `hello.py` にコードを書いてみます。\n\n**hello.py**\n\n```python\n#!/usr/bin/env python\n\n\ndef main():\n    print('Hello, World!')\n\n\nif __name__ == '__main__':\n    main()\n```\n\nできたらファイルを保存してプログラムを実行してみます。\n\nウィンドウの右上にある再生ボタンをクリックするとプログラムが実行されます。\n\n[![](img/vscode-05.png)](img/vscode-05.png)\n\n## 構文の説明\n\n### シバン\n\n```python hl_lines=\"1\"\n#!/usr/bin/env python\n\n\ndef main():\n    print('Hello, World!')\n\n\nif __name__ == '__main__':\n    main()\n```\n\n`#` から始まる 1 行目は [シバン] といいます。シバンはこのソースコードを実行する際に使用するコマンドを記述します。`/usr/bin/env python` は `python` コマンドを呼び出しているという意味になります。\n\n[シバン]: https://ja.wikipedia.org/wiki/%E3%82%B7%E3%83%90%E3%83%B3_(Unix)\n\n!!! warning\n    Windows では `python` コマンドの代わりに `py` コマンドを使用するように説明しましたが、シバンは\n\n    ```\n    #!/usr/bin/env python\n    ```\n\n    と書いて下さい。\n\n### `main()`\n\n```python hl_lines=\"4 5\"\n#!/usr/bin/env python\n\n\ndef main():\n    print('Hello, World!')\n\n\nif __name__ == '__main__':\n    main()\n```\n\nこれは関数の定義をしています。関数の詳細な説明は [関数] の章で説明します。\n\n`print()` がインデントされていることはとても重要です。なぜなら\n\n```python\ndef main():\nprint('Hello, World!')\n```\n\nと書くと構文エラーになるからです。関数の実装は必ずインデントしてから記述するルールになっています。\n\n### `__name__`\n\n```python hl_lines=\"8 9\"\n#!/usr/bin/env python\n\n\ndef main():\n    print('Hello, World!')\n\n\nif __name__ == '__main__':\n    main()\n```\n\n`main()` は関数を呼び出しています。`if __name__ == '__main__':` については [モジュール] の章で説明しますので、今はおまじないだと思って下さい。`main()` の呼び出しは必ずインデントをして下さい。さもないと構文エラーになります。\n\n### シンプルな書き方\n\nPython の処理はソースコードの上の行から逐次実行されます。そのため、処理を関数内に収めなくても正しく実行することができます。\n\n```python\n#!/usr/bin/env python\n\n\nprint('Hello, World!')\n```\n\nしかし特別な理由がある場合を除いて、関数内に定義する方が望ましいです。その理由は [モジュール] の章で明らかになります。\n\n[関数]: ch02-02-functions.md\n[モジュール]: ch04-01-modules.md\n"
  },
  {
    "path": "docs/ch02-01-variables.md",
    "content": "# 変数\n\n次のようなコードを書いて色々な変数を出力してみましょう。\n\n```python hl_lines=\"6\"\n#!/usr/bin/env python\n\n\ndef main():\n    x = 10      # 変数の定義\n    print(x)\n\n\nif __name__ == '__main__':\n    main()\n```\n\n## 数値型\n\n### 整数 `int`\n\n```python\nx = 10\n```\n\n### 浮動小数点 `float`\n\n```python\nx = 3.14\n```\n\n### 数値演算\n\n数値に対しては四則演算ができます。\n\n```python\n# 加算\ntotal = 5 + 10\n\n# 減算\ndifference = 95.5 - 4.3\n\n# 乗算\nproduct = 4 * 30\n\n# 除算\ndivision = 56.7 / 32.2\n\n# 商\nquotient = 62 // 12\n\n# 剰余\nremainder = 43 % 5\n```\n\n!!! warning \"整数 / 整数 の結果\"\n    整数に対する `/` は Python 2 系と 3 系では意味が変わります。\n\n    | バージョン | 挙動 | 5 / 2 = ? |\n    |------------|------|-----------|\n    | 2.x.x      | 商   | 2         |\n    | 3.x.x      | 除算 | 2.5       |\n\n## 真偽値 `bool`\n\n真偽値を扱うための型です。\n\n```python\nx = True\ny = False\n```\n\n## 文字列 `str`\n\n```python\nx = 'Hello, World!'\ny = '日本語'\n```\n\n### f-string\n\n文字列の先頭に `f` を付けると文字列内に変数や式の埋め込みができるようになります。\n\n```python\nx = 10\ns1 = f'The value of x is {x}'           # 'The value of x is 10'\ns2 = f'The value of x * x is {x * x}'   # 'The value of x * x is 100'\n```\n\nf-string を使わなくても次のようにも書けます。\n\n```python\ns1 = 'The value of x is {}'.format(x)\ns2 = 'The value of x * x is {}'.format(x * x)\n```\n\nf-string は `'...'.format()` のシンプルな書き方を提供する機能です。\n\n## バイト `byte`\n\nバイト列を扱う型です。\n\n```python\nx = b'0xDEADBEEF'\n```\n\n## コレクション型\n\nコレクション型は複数の値をまとめて扱える型の総称です。\n\n### リスト `list`\n\n配列を扱うための型です。リストの各要素は必ずしも同じ型である必要はありません。\n\n```python\nx = [0, 1, 2, 3, 4]\ny = [10, 3.14, 'Hello, World!']\n```\n\n要素の末尾に `,` が入っていても構文として正しいです。\n\n```python\n x = [\n    10,\n    3.14,\n    'Hello, World!',    # OK\n]\n```\n\n要素の追加は次のようにします。\n\n```python\nx.append(100)\n```\n\nまた要素参照は次のようにします。\n\n```python\nx = [10, 3.14, 'Hello, World!']\n\nx[0]    # 10\nx[1]    # 3.14\nx[2]    # 'Hello, World!'\n```\n\n添字には負の数も指定できます。負の数を指定した場合は末尾の要素から参照されます。\n\n```python\nx = [10, 3.14, 'Hello, World!']\n\nx[-1]    # 'Hello, World!'\nx[-2]    # 3.14\nx[-3]    # 10\n```\n\n要素が空のリストを作る場合は `x = []` とします。\n\n### タプル `tuple`\n\nリストとよく似た扱いができる型ですが、タプルは要素の変更も追加もできません。\n\n```python\nx = (0, 1, 2, 3, 4)\ny = (10, 3.14, 'Hello, World!')\n```\n\n要素参照はリストと同じようにしてできます。`()` はただの飾りであり、必須ではありません。タプルになるかどうかは `,` が含まれているかどうかで決まります。\n\n```python\nx = 10, 3.14, 'Hello, World!'   # 3 要素のタプル\ny = 20,                         # 1 要素のタプル\n```\n\nただし空のタプルを作りたいときは `()` を使います。\n\n```python\nx = ()\n```\n\n!!! note\n    要素の変更が必要ない場合はリストよりタプルを使う方が安全です。\n\n### アンパック代入\n\nリストやタプルの要素を複数の変数に同時に代入する構文を **アンパック代入** といいます。\n\n```python\nx = (10, 3.14, 'Hello, World!')\na, b, c = x     # a: 10, b: 3.14, c: 'Hello, World!'\n```\n\n代入元と代入先の要素数は一致している必要があります。\n\n```python\nx = [0, 1, 2, 3, 4]\na, b, c = x     # エラー\n```\n\nしかし代入先の変数に `*` を付けておくと、その変数はリスト型になるため、要素数が一致しなくてもアンパック代入ができるようになります。\n\n```python\nx = [0, 1, 2, 3, 4]\na, b, *c = x     # a: 0, b: 1, c: [2, 3, 4]\n```\n\n### 辞書 `dict`\n\nキーに対する値を管理するための型です。\n\n```python\nx = {'name': 'John Doe', 'age': 30}\n\nx['name']   # 'John Doe'\nx['age']    # 30\n```\n\n要素が空の辞書を作る場合は `x = {}` とします。\n\n### 集合 `set`\n\n重複を取り除いて複数の要素を扱うための型です。\n\n```python\nx = {0, 1, 2, 2, 3, 4, 4}   # {0, 1, 2, 3, 4}\n```\n\n`set()` を使うとリストやタプルから集合を作ることができます。\n\n```python\nx = set([1, 1, 2, 3, 4, 4])                 # {1, 2, 3, 4}\ny = set(('x', 'x', 3.14, [1, 2], [1, 2]))   # {'x', 3.14, [1, 2]}\n```\n\n空の集合を作る場合は `x = set()` とします。`x = {}` としても空の辞書となるので注意してください。\n\n## `None`\n\n変数に `None` というキーワードを代入すると、その変数はどの型にも属さない変数になります。\n\n```python\nx = None\n```\n\n変数は用意したいけど、どのような値を入れるかは後で決めたいといったケースでは `None` が使用されます。\n\n## 定数\n\nPython には定数の概念がありません。しかし、書き換えを想定しない変数は大文字で書いて定数であることを示すというルールがあります。\n\n```python\nPI = 3.14\n```\n"
  },
  {
    "path": "docs/ch02-02-functions.md",
    "content": "# 関数\n\n関数を定義するには `def` キーワードを使います。\n\n```python\n#!/usr/bin/env python\n\n\ndef another_function():\n    print('Another function')\n\n\ndef main():\n    print('Hello, World!')\n\n    another_function()\n\n\nif __name__ == '__main__':\n    main()\n```\n\n関数名は自由に与えることができますが、慣習的に英数字かつ *snake_case* （小文字を `_` でつなぐ記法）で表記します。\n\n!!! note\n    関数定義の間は慣習的に 2 行開けるルールになっています。\n\n## 引数\n\n関数には引数を渡すことができます。\n\n```python\ndef another_function(x, y):\n    print(f'The value of x is {x}')\n    print(f'The value of y is {y}')\n\n\ndef main():\n    another_function(5, 6)\n```\n\n## デフォルト引数\n\n関数には引数を明示的に渡さなかった場合にデフォルト値を暗黙的に渡す機能があります。\n\n```python\ndef another_function(x, y=10):\n    print(f'The value of x is {x}')\n    print(f'The value of y is {y}')\n\n\ndef main():\n    another_function(5, 3)   # x: 5, y: 3\n    another_function(7)      # x: 7, y: 10\n```\n\nデフォルト引数は引数内で一番最後に渡す必要があります。\n\n```python\n# OK\ndef f1(x, y=10):\n    print(f'The value of x is {x}')\n    print(f'The value of y is {y}')\n\n\n# OK\ndef f2(x, y=10, z=20):\n    print(f'The value of x is {x}')\n    print(f'The value of y is {y}')\n    print(f'The value of z is {z}')\n\n\n# NG\ndef f3(y=10, x, z=20):\n    print(f'The value of x is {x}')\n    print(f'The value of y is {y}')\n    print(f'The value of z is {z}')\n```\n\n!!! note\n    デフォルト引数の定義は慣習的に `=` の両端にはスペースを入れずに書きます。\n\n## キーワード引数\n\n関数を呼び出すときに引数名を指定すれば引数を順不同で渡すこともできます。\n\n```python hl_lines=\"7\"\ndef another_function(x, y):\n    print(f'The value of x is {x}')\n    print(f'The value of y is {y}')\n\n\ndef main():\n    another_function(y=10, x=20)\n```\n\n## `*args, **kwargs`\n\n関数の引数名に `*` が付いたものがあると、その変数は複数の引数を 1 つのタプルとして受け取るようになります。\n\n```python\ndef another_function(x, *args):\n    print(f'The value of x is {x}')         # x: 0\n    print(f'The value of args is {args}')   # args: (1, 2, 3)\n\n\ndef main():\n    another_function(0, 1, 2, 3)\n```\n\nまた引数名に `**` を付けると複数のキーワード引数を 1 つの辞書として受け取るようになります。\n\n```python\ndef another_function(x, **kwargs):\n    print(f'The value of x is {x}')             # x: 0\n    print(f'The value of kwargs is {kwargs}')   # kwargs: {'y': 10, 'z': 20}\n\n\ndef main():\n    another_function(0, y=10, z=20)\n```\n\n`*args, **kwargs` は併用することも可能です。\n\n```python\ndef another_function(x, *args, **kwargs):\n    print(f'The value of x is {x}')             # x: 0\n    print(f'The value of args is {args}')       # args: (1, 2)\n    print(f'The value of kwargs is {kwargs}')   # kwargs: {'y': 10, 'z': 20}\n\n\ndef main():\n    another_function(0, 1, 2, y=10, z=20)\n```\n\n!!! note\n    `*` 引数と `**` 引数はどのような名前にしても構いませんが、慣習的に `*args, **kwargs` が使われます。\n\n## 引数のアンパック\n\n関数に引数を渡すときにタプルに `*` を付けて渡すとタプルの各要素を個別の引数として渡せるようになります。\n\n```python\ndef another_function(x, y, z):\n    print(f'The value of x is {x}')     # x: 0\n    print(f'The value of y is {y}')     # y: 1\n    print(f'The value of z is {z}')     # z: 2\n\n\ndef main():\n    args = (0, 1, 2)\n    another_function(*args)             # another_function(0, 1, 2)\n```\n\nまた辞書に `**` を付けて渡すと辞書の各要素をキーワード引数として渡せるようになります。\n\n```python\ndef another_function(x, y, z):\n    print(f'The value of x is {x}')     # x: 0\n    print(f'The value of y is {y}')     # y: 1\n    print(f'The value of z is {z}')     # z: 2\n\n\ndef main():\n    kwargs = {'x': 0, 'y': 1, 'z': 2}\n    another_function(**kwargs)          # another_function(x=0, y=1, z=2)\n```\n\n## 型ヒント\n\n引数に特定の型だけを渡せるようにしたければ **型ヒント** を使用します。\n\n```python\ndef another_function(x: int, y: int):\n    print(f'The value of x * y is {x * y}')\n```\n\n型ヒントを使用しなければどんな型の変数も渡せます。これはしばしば混乱の元となるので、なるべく型ヒントを使うようにしましょう。\n\n## 戻り値\n\n関数の呼び出し側に値を返却する場合は `return` を使用します。\n\n```python\ndef plus_one(x):\n    return x + 1\n\n\ndef main():\n    x = plus_one(5)     # x: 6\n\n    print(f'The value of x is {x}')\n```\n\n戻り値として返す型は複数あっても構いません。\n\n```python\ndef another_function(x):\n    if x == 0:\n        return x + 3.14\n    else:\n        return x + 1\n```\n\nこの関数は `x` が `0` のときは `float` 型を返し、そうでないときは `int` 型を返します。複数の型を返すことを想定してなければ、型ヒントを使うことで誤って意図しない型を返却してしまうことを防ぐことができます。\n\n```python\ndef plus_one(x: int) -> int:\n    return x + 1\n```\n\nPython の関数は必ず戻り値を持っており、`return` を明示的に使わなかった場合は `None` が返ります。\n\n```python\ndef f(x):\n    print(f'The value of x is {x}')\n```\n\nこの関数は下記と同じ意味になります。\n\n```python\ndef f(x):\n    print(f'The value of x is {x}')\n    return None\n```\n\n## 空実装\n\n関数の実装を空にしたい場合は `pass` と書いておきます。\n\n```python\n# 何もしない関数\ndef empty_function():\n    pass\n```\n"
  },
  {
    "path": "docs/ch02-03-comments.md",
    "content": "# コメント\n\n`#` から始まる行はコメントと見なされます。コメントはプログラム上は無視されるため、自由にメッセージを書くことができます。\n\n```python\n# この行はコメントです。\n```\n\nコードの末尾に置くことも可能です。\n\n```python\ndef main():\n    lucky_number = 7    # I’m feeling lucky today.\n```\n"
  },
  {
    "path": "docs/ch02-04-conditions.md",
    "content": "# 条件文\n\nある条件を満たしている時だけ行いたい処理がある場合は条件文を使って処理を書きます。\n\n## `if`\n\n```python\n#!/usr/bin/env python\n\n\ndef main():\n    check(3)\n    check(7)\n\n\ndef check(x):\n    if x < 5:\n        print('condition was true')\n    else:\n        print('condition was false')\n\n\nif __name__ == '__main__':\n    main()\n```\n\n`x` の値が `5` 未満かどうかで出力されるメッセージが変化します。`if` に渡す値は必ずしも評価式である必要はありません。次のように値そのものを渡すこともできます。\n\n```python\nx = 10\n\nif x:\n    print('x is not 0')\n```\n\nこの条件は `x` を `bool` に変換した値が評価されます。値を `bool` に変換した場合の結果は次のように評価されます。\n\n- `0, 0.0, '', b'', [], (), {}, set(), None` のとき `False`\n- それ以外のとき `True`\n\n## `elif`\n\n複数の条件を見たい場合は `if, elif, else` を使います。\n\n```python\ndef check(number):\n    if number % 4 == 0:\n        print('number is divisible by 4')\n    elif number % 3 == 0:\n        print('number is divisible by 3')\n    elif number % 2 == 0:\n        print('number is divisible by 2')\n    else:\n        print('number is not divisible by 4, 3, or 2')\n\n\ndef main():\n    check(10)\n```\n\n`else if` ではなく `elif` であることに注意してください。\n\n!!! note \"switch 文\"\n    Python には switch 文がありませんので `if, elif, else` を使用して下さい。\n\n## 空の条件文\n\n条件文内の処理を空にしたい場合は `pass` と書いておきます。\n\n```python\nif x == 0:\n    pass\n```\n\n## 演算子\n\n条件文で使用できる演算子には次のようなものがあります。\n\n### `and`\n\n複数の条件が成立するかどうかを調べるときに使用します。\n\n```python\ndef check(x):\n    if x >= 0 and x < 10:\n        print('x is in [0, 10)')\n\n\ndef main():\n    check(10)\n```\n\nただし変数の範囲チェックをする場合は `and` を使わなくてもシンプルな書き方ができます。\n\n```python\n\ndef check(x):\n    if 0 <= x < 10:     # x >= 0 and x < 10 と同じ\n        print('x is in [0, 10)')\n\n\ndef main():\n    check(10)\n```\n\n### `or`\n\n複数の条件のうちどれか 1 つが成立するかどうかを調べるときに使用します。\n\n```python\ndef check(x, y):\n    if x > 0 or y > 0:\n        print('Either x or y is a positive value')\n\n\ndef main():\n    check(10, -3)\n```\n\n### `in`\n\nリスト・タプル・集合内に特定の要素が含まれているかどうかを調べます。\n\n```python\ndef check(data, x):\n    if x in data:\n        print(f'{data} contains {x}')\n\n\ndef main():\n    check([0, 1, 2, 3, 4], 3)\n```\n\n辞書に対して使用するとキーの存在を調べることができます。\n\n```python\ndef check(data, key):\n    if key in data:\n        print(f'{data} contains the value of key {key}')\n\n\ndef main():\n    check({'x': 0, 'y': 1, 'z': 2}, 'x')\n```\n\n### `is`\n\n`is` は 2 つの変数が同じインスタンスを参照しているかどうかを調べるときに使用します。\n\n```python\ndef check(x, y):\n    if x is y:\n        print('x is y == True')\n\n\ndef main():\n    x = [0, 1, 2]\n    y = x\n    z = x\n    check(y, z)\n```\n\nここでいう「同じ」とは保持している値が等価という意味ではありません。参照しているインスタンスが同じかどうかを意味しています。言い換えれば変数 `x, y` に対して、これらの代入元の変数をたどっていって同じ変数にたどり着くなら `x is y` は `True` になります。\n\n```python\nx = [0, 1, 2]\ny = x\nz = y\n\nx is y  # True\ny is z  # True\nz is x  # True\n\na = [0, 1, 2]\nb = a\n\nx is a  # False\nx is b  # False\n```\n\n変数に `None` が代入されているかどうかを調べるときは `==` ではなく `is` を使用します。\n\n```python\nx is None\n```\n"
  },
  {
    "path": "docs/ch02-05-loops.md",
    "content": "# ループ文\n\nリストの要素に対して繰り返し同様の処理を実行する場合は `for` や `while` を使います。\n\n## `for`\n\nリストに対して `for` を使う場合は次のように書きます。\n\n```python\nvalues = [0, 1, 2, 3, 4]\n\nfor value in values:\n    print(f'The value is {value}')\n```\n\nタプルの場合も同様にして `for` に渡すことができます。辞書も渡すことができますが、この場合キーが各ループで参照されます。\n\n```python\nitems = {'a': 1, 'b': 2, 'c': 3}\n\nfor key in items:\n    print(f'The key is {key}')\n```\n\n値のループあるいはキーと値の両方をループで参照したい場合はそれぞれ `values(), items()` メソッドを使用します。\n\n```python\nitems = {'a': 1, 'b': 2, 'c': 3}\n\nfor value in items.values():\n    print(f'The value is {value}')\n\nfor key, value in items.items():\n    print(f'The pair of key and value is ({key}, {value})')\n```\n\n### `range()`\n\n整数を順にループさせたい場合は `range()` という関数を使って実現できます。\n\n```python\nfor i in range(10):\n    print(f'The value is {i}')\n```\n\n`range(10)` で 0 以上 10 未満（すなわち 0 ～ 9） の整数をループします。`range()` は終了値だけでなく、開始値と刻み幅を指定することもできます。\n\n```python\nrange(stop, start=0, step=1)\n```\n\n!!! note \"例\"\n    - `range(2, 10)`: 2, 3, 4, 5, 6, 7, 8, 9\n    - `range(2, 10, 2)`: 2, 4, 6, 8\n    - `range(10, 0, -1)`: 10, 9, 8, 7, 6, 5, 4, 3, 2, 1\n\n## `while`\n\n`while` は特定の条件が `True` である間ループ処理を続けるというものです。\n\n```python\nx = [10, 20, 30, 40, 50]\nindex = 0\n\nwhile index < 5:\n    print(f'The value is {x[index]}')\n    index += 1\n```\n"
  },
  {
    "path": "docs/ch02-06-list-comprehensions.md",
    "content": "# リスト内包表記\n\nリスト内包表記とはリストを簡単に作成するための構文のことです。今 `[0, 2, 4, 6, ..., 98]` というリストを作ろうとした場合、\n\n```python\nx = []\n\nfor i in range(50):\n    x.append(i * 2)\n```\n\nのようにループ処理をして要素を詰めて作ることができますが、リスト内包表記を使うと下記のようにもっとシンプルに書くことができます。\n\n```python\nx = [i * 2 for i in range(50)]\n```\n\nリスト内包表記は別のコレクション型から変換を行う際によく使われます。例えば下記は辞書からタプルを要素とするリストを作成する例です。\n\n```python\nx = {'a': 10, 'b': 20, 'c': 30}\ny = [(key, val) for key, val in x.items()]  # [('a', 10), ('b', 20), ('c', 30)]\n```\n\nループ処理を短く書くことができますので活用するとコードがシンプルになります。\n"
  },
  {
    "path": "docs/ch02-07-lambdas.md",
    "content": "# ラムダ式\n\nラムダ式とは関数を変数に代入して扱えるようにするものです。ラムダ式が必要になってくるシーンは関数を別の関数の引数として渡す必要があるときです。\n\n!!! Tips\n    引数として渡される関数のことをコールバックといいます。\n\n例として `map()` という組み込み関数について考えてみます。`map()` はリストなどのコレクションの各要素に何らかの変換を加えたコレクションを新たに作成する関数です。\n\n```python\na = [1, 2, 3, 4, 5]\n```\n\n上記のリストの各要素を 2 乗して `[1, 4, 9, 16, 25]` というリストを `map()` で作成するには次のようにします。\n\n```python\nlist(map(lambda x: x * x, a))\n```\n\n`map()` の第 1 引数にはラムダ式が渡されています。ラムダ式は機能的には通常の関数と同様の機能を提供しており\n\n```python\nlambda x: x * x\n```\n\nというラムダ式は下記の関数と等価なものになっています。\n\n```python\ndef power(x):\n    return x * x\n```\n\n`map()` は第 2 引数に渡されたコレクションの各要素をラムダ式に渡し、その戻り値を逐次返却していくという振る舞いをします。ちなみに `map()` には上記の `power()` のような通常の関数を渡すこともできます。\n\n```python\nlist(map(power, a))\n```\n\nラムダ式が通常の関数と異なる点は\n\n- 名前を持たない（無名関数）\n- 必要なときに即時に定義できる\n\nという点です。`map()` に渡すためのちょっとした処理に対して、わざわざ関数定義をするのも面倒だといったケースではラムダ式が使われます。その他の例もいくつか挙げておきます。\n\n```python\nlist(map(lambda x: 2 * x, a))           # [2, 4, 6, 8, 10]\nlist(map(lambda x: (x, 2 * x + 1), a))  # [(1, 3), (2, 5), (3, 7), (4, 9), (5, 11)]\n```\n\n`map()` の戻り値は [ジェネレータ](./ch07-01-generators.md) というオブジェクトが返ります。ジェネレータ自体はリストではないですが、ループ文に渡すことでリストと同じように変換結果の要素を取り出すことができます。\n\n```python\nfor item in map(lambda x: x * x, a):\n    print(item)     # 1, 4, 9, 16, 25\n```\n\nジェネレータを `list()` に渡すとリストに変換してくれますが、ループ文で要素を参照するだけであればリストに変換する必要はありません。インデックス参照などがしたい場合にリストに変換すると良いでしょう。`map()` のようにコレクションとコールバックを受け取りジェネレータを返す関数は他にもいくつか用意されています。代表的なものには [itertools] があります。\n\n[itertools]: https://docs.python.org/ja/3/library/itertools.html\n"
  },
  {
    "path": "docs/ch03-01-classes.md",
    "content": "# クラス\n\nクラスとは新しい型を定義するための仕組みです。クラスを使うことで複数の変数と関数を集約した変数を作ることができるようになります。\n\n## 定義\n\nクラスを定義するには `class` キーワードにクラス名を付けて定義します。下記の `Rectangle` クラスは長方形に関する情報を扱うクラスで、長方形の幅と高さをメンバ変数として持ったクラスになります。\n\n```python hl_lines=\"5 6 7 8\"\n#!/usr/bin/env python\n\n\nclass Rectangle:\n    def __init__(self, width, height):\n        self.width = width\n        self.height = height\n\n\ndef main():\n    rectangle = Rectangle(10, 20)\n\n    print(f'The value of width is {rectangle.width}')\n    print(f'The value of height is {rectangle.height}')\n\n\nif __name__ == '__main__':\n    main()\n```\n\n## `__init__()`\n\n`__init__()` はいわゆるコンストラクタです。コンストラクタには 2 つの役割があります。\n\n1. インスタンス化をするときに最初に呼び出される\n1. クラスのメンバ変数を定義し、それを初期化する\n\nクラスにどのようなメンバ変数を用意したいかということも含めてコンストラクタで定義することに注意して下さい。\n\n引数には初期化に必要な値を渡すことができます。ただし第 1 引数は必ず `self` という引数にして下さい。`self` については後述します。\n\nクラスで扱うメンバ変数を定義したいときは次のようにします。\n\n```python hl_lines=\"3 4\"\nclass Rectangle:\n    def __init__(self, width, height):\n        self.width = width\n        self.height = height\n```\n\nこれはクラスのメンバ変数として `width, height` を用意するという意味になります。これで `Rectangle` という型が作成され、その型は `width, height` をメンバ変数として持っていることになります。\n\n`width` に `10` 、`height` に `20` を渡して `Rectangle` の変数を作るには次のようにします。\n\n```python\ndef main():\n    rectangle = Rectangle(10, 20)\n\n    print(f'The value of width is {rectangle.width}')\n    print(f'The value of height is {rectangle.height}')\n```\n\n## `self`\n\n`Rectangle` をインスタンス化する際は `10, 20` という 2 つの値しか渡してないのに `__init__()` の第 1 引数には `self` という変数が含まれており、合計 3 つの引数が用意されています。これは一体どういうことでしょうか。この謎はクラスのインスタンス化の仕組みを理解すれば分かってきます。\n\n`rectangle = Rectangle(10, 20)` という処理をイメージで説明すると、だいたいこんな感じになります。\n\n```python\nrectangle = (Rectangle クラスの変数を用意)  # この時点では rectangle.width, rectangle.height は存在しない\nRectangle.__init__(rectangle, 10, 20)       # rectangle.width = width, rectangle.height = height という処理が実行される\n```\n\nすなわち `self` というのはクラスインスタンスを表す変数です。\n\n## 関数\n\nクラスには関数を定義することもできます。クラスのメンバとして定義された関数はメソッドとも呼ばれます。\n\n```python hl_lines=\"10 11 16\"\n#!/usr/bin/env python\n\n\nclass Rectangle:\n    def __init__(self, width, height):\n        self.width = width\n        self.height = height\n\n    def area(self):\n        return self.width * self.height\n\n\ndef main():\n    rectangle = Rectangle(10, 20)\n    area = rectangle.area()\n\n    print(f'The area is {area}')\n\n\nif __name__ == '__main__':\n    main()\n```\n\nクラスに関数を定義するときは第 1 引数が `self` である必要があります。これは `rectangle.area()` という呼び出しは実際には `Rectangle.area(rectangle)` のように呼び出されるためです。\n\n## 継承\n\n定義済みのクラスのメンバを持つ新たなクラスを作成することもできます。\n\n```python\n#!/usr/bin/env python\n\n\nclass Square(Rectangle):\n    def __init__(self, size):\n        super().__init__(size, size)\n\n\ndef main():\n    square = Square(10)\n    area = square.area()\n\n    print(f'The area is {area}')\n\n\nif __name__ == '__main__':\n    main()\n```\n\n`Square` クラスは `Rectangle` クラスのメンバを全て引き継いだクラスになっており、これをクラスの継承といいます。`Rectangle` が長方形を扱うクラスなのに対し、`Square` は正方形を扱うクラスになっており、`Rectangle` が持つ全てのメンバ `square.width, square.height, square.area()` が参照できます。\n\n## インターフェース\n\nPython にはインターフェースが存在しません。また多態性を実現するのにクラスに継承関係を作る必要もありません。それを確認するために継承関係にない 2 つのクラス `A, B` を作ってみます。またメソッドとして `greet()` という関数をそれぞれのクラスで定義しておきます。\n\n```python hl_lines=\"5 6 13 14\"\nclass A:\n    def __init__(self):\n        pass\n\n    def greet(self):\n        print('This is class A')\n\n\nclass B:\n    def __init__(self):\n        pass\n\n    def greet(self):\n        print('This is class B')\n```\n\n次に `greet()` 関数をメンバに持った変数を受け取るような関数 `call()` を次のように作成します。\n\n```python\ndef call(x):\n    x.greet()\n```\n\nこの関数に `A, B` の変数をそれぞれ渡してみます。\n\n```python\ndef main():\n    call(A())\n    call(B())\n```\n\nソースコードの全体は次のようになります。\n\n```python\n#!/usr/bin/env python\n\n\nclass A:\n    def __init__(self):\n        pass\n\n    def greet(self):\n        print('This is class A')\n\n\nclass B:\n    def __init__(self):\n        pass\n\n    def greet(self):\n        print('This is class B')\n\n\ndef call(x):\n    x.greet()\n\n\ndef main():\n    call(A())\n    call(B())\n\n\nif __name__ == '__main__':\n    main()\n```\n\nこのコードは問題なく実行することができます。Python は例え継承関係を持っていなくてもクラスの構造（メンバ変数や関数の名前・引数）が一致していれば同種の型として扱えるようになります。このような多態性の実現方法のことを **ダックタイピング** といいます。\n"
  },
  {
    "path": "docs/ch03-02-scopes.md",
    "content": "# スコープ\n\n他の言語ではクラスメンバに対して `public, protected, private` といったアクセス指定子を指定することができますが Python ではそのような指定はできず、すべてのメンバが `public` として扱われます。ですが習慣的に下記のような命名規則でメンバのスコープを区別するようになっています。\n\n| スコープ  | 命名規則     |\n|-----------|--------------|\n| public    | `method()`   |\n| protected | `_method()`  |\n| private   | `__method()` |\n\nPython では `__method()` のような private メソッドを作ることはそれほど多くはありません。隠蔽したいメンバを定義するときは `_method()` のような protected メソッドを定義することのほうが多いです。\n"
  },
  {
    "path": "docs/ch03-03-special-attributes.md",
    "content": "# 特殊属性\n\nクラスには特殊属性と呼ばれるメソッドが存在しており、クラスを使う際に使用される構文はどれも特殊属性の呼び出しに変換されて実行されます。代表的な特殊属性をいくつか紹介します。\n\n下記のようなクラスを定義したときの特殊属性には次のようなものがあります。\n\n```python\nimport math\n\n\nclass Point:\n    \"\"\"Point クラスです。\"\"\"\n\n    def __init__(self, x, y):\n        self.x = x\n        self.y = y\n\n    def distance(self):\n        return math.sqrt(self.x * self.x + self.y * self.y)\n```\n\n## `__doc__`\n\n`Point.__doc__` という変数には `\"\"\"Point クラスです。\"\"\"` という文字列が入ります。`\"\"\" ... \"\"\"` というトリプルクオテーションでくくられた文字列は改行を含む複数行の文字列を定義できる文字列です。\n\n```python\n\"\"\"この文字列は\n一つの文字列として\n扱われます。\"\"\"\n```\n\n`__doc__` は docstring と呼ばれ、ドキュメンテーションをする際に使用される文字列として扱われます。\n\n## `__init__`\n\nクラスインスタンスを作成するときは `__init__()` が呼び出されます。\n\n```python\npoint = Point(10, 20)   # point.__init__(10, 20)\n```\n\n## `__getattribute__`\n\nクラスのメンバやメソッドを参照したときは `__getattribute__()` が呼び出されます。\n\n```python\npoint = Point(10, 20)\npoint.x             # point.__getattribute__('x')\npoint.distance()    # point.__getattribute__('distance')()\n```\n\n## `__getattr__`\n\n`__getattribute__()` でのメンバ参照に失敗した場合は `__getattr__()` が呼び出されます。このような事が起こるのはクラスのメンバとして定義されていないものにアクセスしようとしたときに起こります。\n\n```python\npoint.x2   # point.__getattr__('x2')\n```\n\n`__getattr__()` は明示的には定義されません。使用するには自分で定義する必要があります。\n\n```python\nclass Point:\n    ...\n\n    def __getattr__(self, item):\n        if item == 'x2':\n            return self.x * self.x\n        elif item == 'y2':\n            return self.y * self.y\n```\n\n## `__getitem__`\n\nクラスインスタンスに対して `[]` を使用した際には `__getitem__()` が呼び出されます。\n\n```python\npoint = Point(10, 20)\npoint['x']      # point.__getitem__('x')\n```\n\n`__getitem__()` を使用するには自分で定義する必要があります。\n\n```python\nclass Point:\n    ...\n\n    def __getitem__(self, item):\n        if item == 'x':\n            return self.x\n        elif item == 'y':\n            return self.y\n```\n\n## `__setattr__`\n\nメンバへの代入が行われた場合は `__setattr__()` が呼び出されます。\n\n```python\npoint = Point(10, 20)\npoint.x = 30    # point.__setattr__('x', 30)\n```\n\n## `__eq__`\n\nインスタンスに対して `==` が使用された場合は `__eq__()` が呼ばれます。\n\n```python\npoint1 = Point(10, 20)\npoint2 = Point(30, 40)\npoint1 == point2    # point1.__eq__(point2)\n```\n\nその他類似の特殊属性が下記の通り用意されています。\n\n| 特殊属性 | 意味               |\n|----------|--------------------|\n| `__ne__` | `point1 != point2` |\n| `__le__` | `point1 <= point2` |\n| `__lt__` | `point1 < point2`  |\n| `__ge__` | `point1 >= point2` |\n| `__gt__` | `point1 > point2`  |\n\n## `__str__`\n\nクラスインスタンスに対して文字列型へのキャストを行うと `__str__()` が呼び出されます。明示的なキャストでなくても文字列への変換が必要とされるケースでも同様の振る舞いをします。\n\n```python\npoint = Point(10, 20)\nprint(point)    # print(point.__str__())\n```\n\n`__str__()` はデフォルトで定義されていますが、大抵の場合は有益な文字列にはなっていないので自分で定義したほうが良いです。\n\n```python\nclass Point:\n    ...\n\n    def __str__(self):\n        return f'<Point(x={self.x}, y={self.y})>'\n```\n"
  },
  {
    "path": "docs/ch03-04-properties.md",
    "content": "# プロパティ\n\nクラスのメンバで変数のように参照することのできる関数のことをプロパティといいます。\n\n```python\nimport math\n\n\nclass Point:\n    def __init__(self, x, y):\n        self.x = x\n        self.y = y\n\n    @property\n    def distance(self):\n        return math.sqrt(self.x * self.x + self.y * self.y)\n```\n\n`@property` のように `@` ではじまるキーワードは **デコレータ** といって関数やクラスに特殊な振る舞いを注入することのできる機能になっています。`distance()` は関数として定義されていますが `@property` デコレータがついていると変数のように参照することができるようになります。\n\n```python\npoint = Point(10, 20)\npoint.distance  # 22.360679775\n```\n\nプロパティは `point.distance()` のように呼ぶことはできません。\n\nメンバ変数 `x, y` を隠蔽して、代わりにプロパティを提供すると代入ができなくなるので安全です。\n\n```python\nimport math\n\n\nclass Point:\n    def __init__(self, x, y):\n        # _ をつけて隠蔽していることを示す\n        self._x = x\n        self._y = y\n\n    @property\n    def x(self):\n        return self._x\n\n    @property\n    def y(self):\n        return self._y\n\n    @property\n    def distance(self):\n        return math.sqrt(self.x * self.x + self.y * self.y)\n```\n\n```python\npoint = Point(10, 20)\nprint(point.x, point.y)     # _x, _y の参照は可能\npoint.x = 30                # _x, _y への代入はできない\n```\n\nプロパティに対して代入を行いたい場合は `setter` プロパティを定義します。\n\n```python\n@property\ndef x(self):\n    return self._x      # getter\n\n@x.setter\ndef x(self, value):\n    self._x = value     # setter\n```\n\n\n```python\npoint.x = 30    # OK\n```\n\nプロパティの利点は `get_x()` のような関数を定義しなくても、まるで変数を直接参照しているようなコードが書ける点にあります。これはクラスを利用する人からするとシンプルなコードが書けるので便利です。ただしプロパティは変数と同じくらいに気軽に参照するメンバになるので、パフォーマンスが遅い関数をむやみにプロパティとして定義するのは避けたほうが良いです。"
  },
  {
    "path": "docs/ch04-01-modules.md",
    "content": "# モジュール\n\nモジュールとは関数やクラスなどを別ファイルで利用できる状態で整理した Python のソースコードのことです。これまでのソースコードは実行することを念頭に実装しましたが、モジュールは別のファイルから取り込まれることを念頭に実装を行います。\n\n## モジュールの書き方\n\n拡張子 `.py` を持った通常の Python ファイルとして作成すれば問題ありません。ただしシバンはモジュールを実装するときには不要です。たとえ書いても悪さをすることはありませんが、実行するスクリプトとしては使用しないので書く意味はあまりありません。\n\nフィボナッチ数列 `0, 1, 1, 2, 3, 5, 8, ...` を出力するような関数 `fib(n)` をモジュールとして書いてみましょう。\n\n**fib.py**\n\n```python\n\n\ndef fib(n):\n    a, b = 0, 1\n\n    while a < n:\n        print(a, end=' ')\n        a, b = b, a + b\n\n    print()\n```\n\n`fib.py` を別のファイル `main.py` に取り込んでこの関数を実行するには次のように書きます。\n\n**main.py**\n\n```python\n#!/usr/bin/env python\n\n\nimport fib          # fib.py を取り込む\n\n\ndef main():\n    fib.fib(10)     # fib.py 内の fib() を呼び出す\n\n\nif __name__ == '__main__':\n    main()\n```\n\n## モジュール作成の注意点\n\nPython のコードは必ずしも関数内に含める必要はなく、ファイル内に直接処理を書くこともできます。\n\n**fib.py**\n\n```python\n\n\na, b = 0, 1\n\nwhile a < n:\n    print(a, end=' ')\n    a, b = b, a + b\n\nprint()\n```\n\nしかしこの状態で `main.py` から `import fib` をすると import した時点でフィボナッチ数列を出力する処理が突然実行されてしまいます。こういった問題が起こらないようにモジュールとして提供する機能は基本的に関数やクラスにまとめておく必要があります。\n\n## `from-import`\n\nモジュール内の関数やクラスにアクセスするときは `モジュール名.関数名` のように `.` を使ってアクセスしますが、モジュール名や関数名が長くなってくると少し書き方が面倒になります。こういうときは `from` 文を使って参照名を短くすることができます。\n\n```python\nfrom (モジュール名) import (関数名)\n```\n\nこのようにすると `モジュール名.関数名` としていたところが `関数名` だけで参照できるようになります。\n\n```python\n#!/usr/bin/env python\n\n\nfrom fib import fib     # fib.py 内の fib() をインポート\n\n\ndef main():\n    fib(10)             # fib() を呼び出す\n\n\nif __name__ == '__main__':\n    main()\n```\n\nただし `import fib` とインポートしたときは `fib.py` 内のすべての関数やクラスが参照できるのに対し、 `from fib import fib` は `fib()` のみが参照できます。複数の定義をインポートしたいときは次のようにします。\n\n```python\nfrom (モジュール名) import (関数名), (関数名), ...\n```\n\nモジュール内の全定義をまとめて `from` でインポートしたければ次のようにします。\n\n```python\nfrom (モジュール名) import *\n```\n\nただしこのインポート文は余計な定義をインポートしてしまう恐れがあるため推奨されません。モジュールのインポート方法は次の優先度で検討して下さい。\n\n| おすすめ     | インポート文                          |\n|--------------|---------------------------------------|\n| :heart_eyes: | `import (モジュール名)`               |\n| :smiley:     | `from (モジュール名) import (関数名)` |\n| :confounded: | `from (モジュール名) import *`        |\n\n## `__name__`\n\n`__name__` は Python で使用できる隠し変数の 1 つで、モジュール名を表す文字列が入っています。例えば `foo.py` というモジュールであれば `__name__` は `'foo'` になります。\n\n```python\nimport foo\n\nprint(foo.__name__)     # 'foo'\n```\n\nしかしこの変数がモジュール名になるのは別のモジュールからインポートされたときだけです。`foo.py` を直接実行した場合は `__name__` には `'__main__'` が入ります。\n\n**foo.py**\n\n```python\n#!/usr/bin/env python\n\nprint(__name__)\n```\n\n```shell\n$ python foo.py\n__main__\n```\n\nつまり `__name__` の値がモジュール名になるのか `'__main__'` になるのかを見ることでインポートされようとしているのかどうかを判断することができるようになります。\n\n[Hello, World!](./ch01-02-hello-world.md) のソースコードで出てきた\n\n```python\nif __name__ == '__main__':\n    main()\n```\n\nという構文は自分がインポートされてないときだけ `main()` を呼び出すという意味になります。 `__name__` の値を見ることで 1 つのファイルで実行スクリプトとモジュールの両方を実装することができるようになります。\n"
  },
  {
    "path": "docs/ch04-02-packages.md",
    "content": "# パッケージ\n\nモジュールを使うことで関数やクラスをまとめることができますが、1 つのモジュール内にたくさんの定義を含めてしまうとコードが長くなってしまい分かりづらくなってしまいます。そういうときはファイルを分割して複数のモジュールを作成し、それを 1 つのディレクトリに集約することで綺麗に整理することができます。このように複数のモジュールを集約したディレクトリのことをパッケージといいます。\n\nモジュールとパッケージの関係はファイルシステムでいうところのファイルとディレクトリの関係に一致します。\n\n| ファイルシステム | Python     |\n|------------------|------------|\n| ファイル         | モジュール |\n| ディレクトリ     | パッケージ |\n\nファイル・ディレクトリのことを Python の世界ではモジュール・パッケージと呼んでいると理解して概ね問題ありません。\n\n## パッケージの作り方\n\nパッケージはディレクトリのことだと説明しましたが、単に Python のソースコードをディレクトリに集約しただけではパッケージにはなりません。ディレクトリをパッケージとして扱うためには `__init__.py` というファイルをディレクトリ内に用意しておく必要があります。\n\n```\nexample\n├── __init__.py     # これがないとパッケージとは呼べない\n├── a.py\n└── b.py\n```\n\n`__init__.py` は空ファイルとして作成してもらって問題ありません。Python のソースコードをディレクトリに集約するときは必ず `__init__.py` を作るようにしましょう。\n\n## パッケージを使用する\n\nパッケージもモジュールと同様、他のファイルに取り込まれることを想定した機能なので `import` 構文を使って取り込む\nことができます。いま、パッケージの構成が次のようになっていたとしましょう。\n\n```\nexample\n├── __init__.py\n├── a.py\n│  └── def fib(n)\n└── b.py\n```\n\nこのとき、関数 `fib(n)` を呼び出したいときには次のようにします。\n\n```python\n#!/usr/bin/env python\n\n\nimport example.a\n\n\ndef main():\n    example.a.fib(10)\n\n\nif __name__ == '__main__':\n    main()\n```\n\n`パッケージ名.モジュール名.関数名` のように `.` で区切って関数にアクセスすることができます。ちなみにパッケージ内にパッケージが含まれていても問題ありません。\n\n!!! warning \"モジュール・パッケージ名の命名規則\"\n    モジュール名・パッケージ名に `-` を使用するのは避けましょう。なぜなら `xxx-yyy` というモジュール・パッケージを作ったとき\n\n    ```python\n    import xxx-yyy\n    ```\n\n    のように import することになりますが `-` が引き算だと解釈されてしまいます。一般的に命名規則は次のようなルールになっています。\n\n    - 全て小文字\n    - パッケージ名に区切り文字は禁止\n    - モジュール名の区切り文字は `_` を使用\n\n    モジュール名であっても区切り文字はできるだけ使用しない方が好まれます。パッケージ名は例え複数語であっても区切り文字は使用しません。\n\n## `__init__.py`\n\n`__init__.py` というファイルがどのような働きをするのか見ていきたいと思います。上記のサンプルにある\n\n```python\nimport example.a\n```\n\nというインポートを下記のように変更すると `example.a.fib()` の参照が正しくできなくなります。\n\n```python\nimport example\n```\n\n両者の違いはインポートにモジュール名 `example.a` を指定しているか、パッケージ名 `example` を指定しているかにあります。インポートでパッケージ名を指定したときは `example` 配下にある `__init__.py` を探してインポートを実行するという振る舞いをします。\n\n```python\nimport example  # example/__init__.py を参照する\n```\n\nもし `__init__.py` 内に何も記述がなければ `import example` では何も取り込まれないことになります。そのため `example.a.fib()` の参照はエラーになってしまいます。たとえ `example` ディレクトリ配下に `a.py` があったとしても Python からは `__init__.py` の定義に従ってパッケージの階層を参照しているということです。\n\nこれに対して `import example.a` の場合だとうまくいくのは、モジュール `example/a.py` を直接インポートしており `__init__.py` の参照が起こらないからです。\n\n`import example` として `example.a.fib()` を参照できるようにするためには `__init__.py` 内でモジュール `a` が参照できるようにしてあげる必要があります。これは下記のようにすることで実現できます。\n\n**`example/__init__.py`**\n\n```python\nfrom . import a\n```\n\nこれは `__init__.py` と同一のディレクトリ階層から `a` をインポートするという構文で **相対インポート** といいます。こうすることで `__init__.py` 内でモジュール `a` が参照できるようになるため `import example` としても `example.a.fib()` が参照できるようになります。\n\n## モジュール検索パス\n\n`__init__.py` 内の記述を\n\n```python\nimport a\n```\n\nと書いてもうまくいきません。 `import example` としてもモジュール `a` が見つからないというエラーが起こってしまいます。これは Python がモジュールを探しに行くときに、決まったルールで検索をしているからです。Python はモジュールを探しに行くときに次の順序でモジュールを検索します。\n\n1. ビルトインモジュール（Python に最初から組み込まれたモジュール）\n2. `python` コマンドに渡したファイルのあるディレクトリ直下\n\n例えばファイル構成が下記のようになっていた場合 `python main.py` と実行して Python がモジュールを探しに行くディレクトリは `root` 直下になります。\n\n```\nroot    # ここ\n├── example     # ここは探しに行かない\n│  ├── __init__.py\n│  └── a.py\n└── main.py\n```\n\nソースコードのどの場所で `import a` を書いても `root` 直下から `a.py` を探そうとします。相対インポートはこのルールに従わずにモジュールを検索してくれるため、うまくいくということです。\n"
  },
  {
    "path": "docs/ch04-03-pip.md",
    "content": "# pip\n\n`pip` はインターネットで公開されている Python パッケージを取得するためのパッケージ管理ツールです。\n\n## 使い方\n\n[requests] という HTTP に関する機能を取り扱う有名なライブラリがあります。これを `pip` で取得して使ってみましょう。\n\n[requests]: http://docs.python-requests.org/en/master/\n\nターミナル上で次のコマンドを実行して下さい。\n\n```shell\n$ pip3 install requests\n```\n\n成功したら次のようなソースコードを書いてみましょう。\n\n```python\n#!/usr/bin/env python\n\n\nimport requests\n\n\ndef main():\n    response = requests.get('http://example.com')\n    print(response.text)\n\n\nif __name__ == '__main__':\n    main()\n```\n\n実行すると [http://example.com](http://example.com) のページの HTML 文字列が出力されると思います。\n\n## PyPI\n\n`pip` によってインストールされるパッケージはどこから取得されているのでしょうか。 Python は [PyPI] というパッケージを登録しておける Web サイトがあり、 `pip` を実行すると PyPI からパッケージがインストールされます。上記の requests も下記の通り PyPI に登録されています。\n\n!!! info \"PyPI\"\n    [https://pypi.org/project/requests/](https://pypi.org/project/requests/)\n\n[PyPI]: https://pypi.org/\n\n## freeze\n\nインストール済みのパッケージ一覧を確認するには `freeze` というコマンドを実行します。\n\n```shell\n$ pip3 freeze\ncertifi==2019.3.9\nchardet==3.0.4\nidna==2.8\nrequests==2.21.0\nurllib3==1.24.1\n```\n\n`requests` とその依存パッケージがバージョン番号とともに表示されます。\n\n## requirements.txt\n\nインストールしたいパッケージをあらかじめファイルに列挙しておき、そのファイルを指定することでもインストールすることができます。インストールしたいパッケージを記述したファイルは通常 `requirements.txt` という名前で保存します。`requirements.txt` を指定してインストールをするには次のようにします。\n\n```shell\n$ pip3 install -r requirements.txt\n```\n\n`requirements.txt` は自分の環境にパッケージをインストールする目的で使用することはあまりありません。むしろ他の人の環境で自分が使っているパッケージをインストールして欲しいときに使用します。また `requirements.txt` は手で作成する必要はなく、`pip freeze` の結果を保存しておくだけで使用できます。`pip freeze` の結果にあるような `==version` という形式のものを `pip` でインストールすると指定されたバージョンをインストールしてくれるため、自分で入れたバージョンと全く同じものを他の人の環境でもインストールしてもらえるようになり、環境差分をなくすことができます。\n\nまとめるとパッケージ管理は次のような手順で行うことになります。\n\n**自分の環境**\n\n```shell\n$ pip3 install name1 name2 ...\n$ pip3 freeze > requirements.txt\n```\n\n`requirements.txt` は Git などでバージョン管理をしておきます。\n\n**他の人の環境**\n\n```shell\n$ pip3 install -r requirements.txt\n```\n"
  },
  {
    "path": "docs/ch04-04-venv.md",
    "content": "# venv\n\n`pip` を使ってサードパーティ製のパッケージをインストールすることができましたが、インストールしたいパッケージが稀に競合を起こすことがあります。\n\n| プログラム | `requests` の要求バージョン |\n|------------|-----------------------------|\n| program1   | 2.21.0                      |\n| program2   | 2.20.1                      |\n\nprogram1 では `requests` 2.21.0 を使おうとしているのに対し program2 では 2.20.1 を使いたかったとすると、システムの中に複数バージョンの `requests` をインストールしておく必要が出てきます。もし使用したいパッケージのバージョンが意図しないものになっているとプログラムが正しく動かない可能性が出てきます。\n\n## 仮想環境の作成\n\nこのような競合を解決するために Python には各プログラムで使用したいパッケージを互いに影響がない形で個別に管理するための仕組みが用意されており、仮想環境と呼ばれます。仮想環境を作成するためのツールは `venv` と呼ばれ、Python に標準で同梱されています。\n\n試しにこれから 2 つの仮想環境を作成し、それぞれに異なるバージョンの `requests` をインストールしてみます。まず下記のように 2 つのディレクトリを作成します。\n\n```shell\n$ mkdir program1 program2\n```\n\n次に program1 配下で仮想環境を作成します。\n\n=== \"macOS\"\n\n    ```shell\n    $ cd program1\n    $ python3 -m venv .venv\n    ```\n\n=== \"Windows\"\n\n    ```shell\n    $ cd program1\n    $ py -3 -m venv .venv\n    ```\n\nprogram1 配下に `.venv` というディレクトリが作成されます。仮想環境を有効にするために下記のコマンドを実行します。\n\n=== \"macOS\"\n\n    ```shell\n    $ . .venv/bin/activate\n    (.venv) $\n    ```\n\n=== \"Windows\"\n\n    ```shell\n    $ .venv\\Scripts\\activate.bat\n    (.venv) $\n    ```\n\nこの状態で `requests` 2.21.0 をインストールしてみます。パッケージをバージョン指定でインストールしたければ次のように実行します。\n\n```shell\n(.venv) $ pip install requests==2.21.0\n```\n\n!!! note\n\n    仮想環境が有効な場合であれば pip コマンドは `pip` が使用できます。\n    `pip3` コマンドも使用できますが、どちらを使用しても効果は同じです。\n\n    一方で仮想環境が無効な状態であれば `pip` は Python 2 系の古い pip を呼び出すことになり\n    `pip3` とは挙動が異なるので注意してください。\n\nこの `requests` は .venv ディレクトリ配下にインストールされ、仮想環境が有効でない限りは参照することができないようになっています。 `pip freeze` を使ってインストールされているパッケージ一覧を確認してみます。\n\n```shell\n(.venv) $ pip freeze\ncertifi==2019.3.9\nchardet==3.0.4\nidna==2.8\nrequests==2.21.0\nurllib3==1.24.1\n```\n\n仮想環境を無効にする場合は `deactivate` というコマンドを実行します。このコマンドは仮想環境が有効なときだけ使用することができます。\n\n=== \"macOS\"\n\n    ```shell\n    (.venv) $ deactivate\n    $\n    ```\n\n=== \"Windows\"\n\n    ```shell\n    (.venv) $ venv\\Scripts\\deactivate.bat\n    $\n    ```\n\nprogram2 配下でも同様に仮想環境を作成してみます。`requests` のバージョンは 2.20.1 を使用します。\n\n=== \"macOS\"\n\n    ```shell\n    $ cd program2\n    $ python3 -m venv .venv\n    $ . .venv/bin/activate\n    (.venv) $ pip install requests==2.20.1\n    (.venv) $ pip freeze\n    certifi==2019.3.9\n    chardet==3.0.4\n    idna==2.7\n    requests==2.20.1\n    urllib3==1.24.1\n    ```\n\n=== \"Windows\"\n\n    ```shell\n    $ cd program2\n    $ py -3 -m venv .venv\n    $ .venv\\bin\\activate.bat\n    (.venv) $ pip install requests==2.20.1\n    (.venv) $ pip freeze\n    certifi==2019.3.9\n    chardet==3.0.4\n    idna==2.7\n    requests==2.20.1\n    urllib3==1.24.1\n    ```\n\nprogram1, program2 配下いずれかの仮想環境を有効にすることで異なるバージョンの `requests` が使用できるようになっています。ちなみに仮想環境が有効でない状態でインストールされたパッケージは全プログラムから参照可能なので競合を起こす可能性があり、使用すべきではありません。そのため、前章の `pip` の章でインストールしたパッケージは下記のように削除しておくことをおすすめします。\n\n```shell\n$ pip3 freeze > requirements.txt\n$ pip3 uninstall -y -r requirements.txt\n```\n"
  },
  {
    "path": "docs/ch04-07-project-structures.md",
    "content": "# プロジェクト構成\n\nPython のソースコードを管理する際にディレクトリの構成をちゃんと考えておくことはとても重要なことです。なぜなら Python は適切な構成になっていないとプログラムを正しく動かすことができなくなるからです。そこで Python 開発ではどのような構成で管理すれば問題が起こりにくいのかについて説明します。\n\n## The Hitchhiker's Guide to Python\n\nPython の理想のプロジェクト構成は Kenneth Reitz 氏によって推奨されている構成に従うのがよいでしょう。どのような構成なのかは [The Hitchhiker’s Guide to Python] というサイトの [Structuring Your Project] の章で詳しく書かれていますのでそちらを参考にしてもらうことにして、ここでは特に注意すべきことについてまとめておきます。\n\nディレクトリの基本構成は次のとおりです。\n\n```\n(project)\n├── (project)  ............ プログラムのソースコードディレクトリ\n│  ├── __init__.py\n│  └── *.py\n└── tests  ................ 単体テストのソースコードディレクトリ\n   ├── __init__.py\n   └── *.py\n```\n\n`(project)` の部分は開発する Python プログラムの名前を付けます。`sample` というプログラムを開発するなら\n\n```\nsample\n├── sample\n│  ├── __init__.py\n│  └── *.py\n└── tests\n   ├── __init__.py\n   └── *.py\n```\n\nのようになります。大事なのはプログラムのソースコードは必ず `(project)` 配下の 1 つのディレクトリ内に集約させるということです（単体テストのソースコードは除く）。なぜならディレクトリは Python のパッケージを構成するものなので、複数のディレクトリでソースコードを管理すると複数の Python パッケージを開発していることになります。しかし通常 1 つのプロジェクト内に複数のパッケージを含めて開発することはありません。\n\nソースコードが 1 つで十分な場合はディレクトリを用意しなくても大丈夫です。\n\n```\n(project)\n├── (project).py  ........... プログラムのソースコードディレクトリ\n└── test_(project).py  ...... 単体テストのソースコードディレクトリ\n```\n\n下記は良くない構成の一例です。\n\n```\nsample\n├── sample\n│  ├── __init__.py\n│  └── *.py\n├── libs  ................. よくないディレクトリ\n│  ├── __init__.py\n│  └── *.py\n└── tests\n   ├── __init__.py\n   └── *.py\n```\n\n下記は `sample/__init__.py` が用意されていないため問題のある構成です。ディレクトリ内に Python ファイルを入れる場合は必ず `__init__.py` を用意してください。\n\n```\nsample\n├── sample\n│  └── *.py\n└── tests\n   └── *.py\n```\n\n下記のような構成もやってしまいがちですが適切ではありません。\n\n```\nsample\n├── sample\n│  ├── __init__.py\n│  └── *.py\n├── main.py\n└── tests\n   ├── __init__.py\n   └── *.py\n```\n\n**main.py**\n\n```python\n#!/usr/bin/env python\n\n\nimport sample\n\n\ndef main():\n    # sample パッケージを使った処理\n    ...\n\n\nif __name__ == '__main__':\n    main()\n```\n\nこの構成の問題点はライブラリとアプリケーションの区別ができていない構成になっているという点です。\n\n| 構成             | 説明                                           |\n|------------------|------------------------------------------------|\n| ライブラリ       | 他のプログラムから `import` して使うプログラム |\n| アプリケーション | 直接実行するプログラム                         |\n\nこの例だと `sample` はライブラリで `main.py` はアプリケーションという位置づけになります。もしライブラリとアプリケーションの両方の側面を持つプログラムを書きたいという場合は `main.py` を `sample/__main__.py` という名前で保存してください。\n\n```\nsample\n├── sample\n│  ├── __init__.py\n│  ├── __main__.py\n│  └── *.py\n└── tests\n   ├── __init__.py\n   └── *.py\n```\n\nそして `main()` を実行したい場合はターミナル上で次のようにします。\n\n=== \"macOS\"\n\n    ```shell\n    $ python3 -m sample\n    ```\n\n=== \"Windows\"\n\n    ```shell\n    $ py -3 -m sample\n    ```\n\nこうすると `sample/__main__.py` が実行されるようになります。決して\n\n=== \"macOS\"\n\n    ```shell\n    $ python3 sample/__main__.py\n    ```\n\n=== \"Windows\"\n\n    ```shell\n    $ py -3 sample/__main__.py\n    ```\n\nのように実行してはいけません。たとえ動いたとしてもいつもうまくいくと期待しないほうがいいでしょう。\n\n[The Hitchhiker’s Guide to Python]: https://docs.python-guide.org/\n[Structuring Your Project]: https://docs.python-guide.org/writing/structure/\n"
  },
  {
    "path": "docs/ch05-01-files.md",
    "content": "# ファイル操作\n\nファイルの読み書きをする方法について説明します。\n\n## 読み込み\n\n`file.txt` というファイルを読み込み、1 行ずつプリントするプログラムは次のように書きます。\n\n**main.py**\n\n```python\n#!/usr/bin/env python\n\n\ndef main():\n    f = open('file.txt')\n\n    for line in f:\n        print(line)\n\n    f.close()\n\n\nif __name__ == '__main__':\n    main()\n```\n\n`for` を使わずに 1 行読み込む場合は `readline()` メソッドを使います。\n\n```python\nprint(f.readline())\n```\n\n注意が必要なのは読み込んだ各行の文字列は末尾の改行も含んでいるということです。例えば `file.txt` が次のような内容だった場合\n\n**file.txt**\n\n```\naaa\nbbb\nccc\n```\n\n`for` や `readline()` で読み込んだ各行の文字列は次のようになります。\n\n```python\n'aaa\\n'\n'bbb\\n'\n'ccc\\n'\n```\n\n`print()` は文字列をプリントした後に自動で改行を 1 つ書き出すため、これらの文字列をプリントすると改行が 2 つ入った状態で出力されてしまいます。\n\n```shell\n$ python main.py\naaa\n\nbbb\n\nccc\n```\n\nこれを解決するには読み込んだ文字列に対して `strip()` というメソッドを呼び出します。 `strip()` は文字列の両端にある空白や改行を削除するメソッドです。\n\n```python\n#!/usr/bin/env python\n\n\ndef main():\n    f = open('file.txt')\n\n    for line in f:\n        print(line.strip())\n\n    f.close()\n\n\nif __name__ == '__main__':\n    main()\n```\n\nその他次のようなメソッドでも文字列を読み込むことができます。\n\n| メソッド      | 説明                              | 例                            |\n|---------------|-----------------------------------|-------------------------------|\n| `readlines()` | 各行をリストで読み込む            | `['aaa\\n', 'bbb\\n', 'ccc\\n']` |\n| `read()`      | 全行を 1 つの文字列として読み込む | `'aaa\\nbbb\\nccc\\n'`           |\n\n## 書き込み\n\nファイルを書き込む処理は次のように書きます。\n\n```python\n#!/usr/bin/env python\n\n\ndef main():\n    f = open('file.txt', 'w')\n    f.write('Hello, World!\\n')\n    f.close()\n\n\nif __name__ == '__main__':\n    main()\n```\n\n`open()` の第 2 引数に `'w'` を付けることで書き込みモードでファイルをオープンします。そして `write()` メソッドに書き出したい文字列を渡すことでファイルに書き出すことができます。 `write()` には文字列しか渡すことができませんので、数値などを書き出したいときは f-string を使って文字列に変換する必要があります。また `write()` は `print()` とは違って改行を自動で付与しないので、改行したいときは明示的に `'\\n'` を渡す必要があります。\n"
  },
  {
    "path": "docs/ch05-02-contexts.md",
    "content": "# コンテキスト\n\n`open()` を使ってファイルの読み書きをした後は必ず `close()` を使ってファイルを閉じる必要があります。しかしファイルの閉じ忘れがよくあるミスの 1 つです。このファイルの閉じ忘れをなくすために Python にはコンテキストマネージャという機能が用意されています。コンテキストマネージャを使えばファイルの読み書きが不要になったときに暗黙的にファイルを閉じてくれるようになります。\n\n## `with` 文\n\nコンテキストマネージャを使うには `with` 文という構文を使用します。\n\n```python\nf = open('file.txt')\n```\n\nのように記述していた部分を\n\n```python\nwith open('file.txt') as f:\n```\n\nという構文で書き直します。そうするとファイルインスタンス `f` は `with` のブロック内だけで使用できるようになり、ブロックを抜けると暗黙的に `f.close()` を読んでファイルをクローズしてくれるようになります。下記は `with` を使ってファイルを読み込む例です。\n\n**main.py**\n\n```python\n#!/usr/bin/env python\n\n\ndef main():\n    with open('file.txt') as f:\n        for line in f:\n            print(line)\n\n\nif __name__ == '__main__':\n    main()\n```\n\nファイルの閉じ忘れを防ぐためにもファイル操作を行う際はいつもコンテキストマネージャを用いたほうが良いでしょう。\n"
  },
  {
    "path": "docs/ch05-03-csv.md",
    "content": "# CSV\n\nPython で CSV の読み書きを行いたい場合は `csv` モジュールを使います。\n\n## 読み込み\n\n### reader\n\nCSV ファイルを読み込む場合は `open()` でファイルを開いた後、ファイルオブジェクトを `csv.reader()` に渡します。\n\n```python\n#!/usr/bin/env python\nimport csv\n\n\ndef main():\n    with open('example.csv', newline='') as f:\n        reader = csv.reader(f)\n\n        for row in reader:\n            print(row)  # row は CSV の各行になる\n\n\nif __name__ == '__main__':\n    main()\n```\n\n!!! warning \"注意\"\n    `newline=''` というのはファイルの改行コードをそのまま読み込むというオプションです。これを付けないと CRLF, LF, CR などの改行コードはすべて LF に変換されてファイルが読み込まれますが CSV を読むときはこの変換をすべきでないとされています。\n\n`row` にはカンマ区切りの要素がリストで保存されます。\n\n**example.csv**\n\n```\n0,A\n1,B\n2,C\n```\n\n上記のファイルに対しては `row` は下記のようになります。\n\n```python\n[0, 'A']\n[1, 'B']\n[2, 'C']\n```\n\n### DictReader\n\nCSV が下記のようなヘッダを持つ場合は `reader()` の代わりに `DictReader` を使うと各行を辞書で読むことができるようになります。\n\n**example.csv**\n\n```\nid,name\n0,A\n1,B\n2,C\n```\n\n```python\n#!/usr/bin/env python\nimport csv\n\n\ndef main():\n    with open('example.csv', newline='') as f:\n        reader = csv.DictReader(f)\n\n        for row in reader:\n            print(row)\n```\n\n実行結果は下記のようになります。\n\n```python\n{'id': 0, 'name': 'A'}\n{'id': 1, 'name': 'B'}\n{'id': 2, 'name': 'C'}\n```\n\n## 書き込み\n\n### writer\n\nCSV ファイルを作成するには `open()` でファイルを開いた後 `csv.writer()` にファイルオブジェクトを渡します。\n\n```python\n#!/usr/bin/env python\nimport csv\n\n\ndef main():\n    with open('example.csv', 'w', newline='') as f:\n        writer = csv.writer(f)\n\n        writer.writerow([0, 'A'])\n        writer.writerow([1, 'B'])\n        writer.writerow([2, 'C'])\n```\n\n!!! warning \"注意\"\n    書き込みの場合も `newline=''` は必ず付けるようにしてください。\n\n### DictWriter\n\nヘッダ付きの CSV を作成したい場合は `writer()` の代わりに `DictWriter` を使うと書き込む要素を辞書で指定できるようになります。\n\n```python\n#!/usr/bin/env python\nimport csv\n\n\ndef main():\n    with open('example.csv', 'w', newline='') as f:\n        writer = csv.DictWriter(f, fieldnames=['id', 'name'])\n\n        writer.writerow({'id': 0, 'name': 'A'})\n        writer.writerow({'id': 1, 'name': 'B'})\n        writer.writerow({'id': 2, 'name': 'C'})\n\n\nif __name__ == '__main__':\n    main()\n```\n"
  },
  {
    "path": "docs/ch05-04-json.md",
    "content": "# JSON\n\nPython で JSON の読み書きを行いたい場合は `json` モジュールを使います。\n\n## 読み込み\n\n### ファイルから読み込み\n\nJSON ファイルを読み込む場合は `open()` でファイルを開いた後、ファイルオブジェクトを `json.load()` に渡します。\n\n```python\n#!/usr/bin/env python\n\nimport json\n\n\ndef main():\n    with open('example.json') as f:\n        json_data = json.load(f)\n\n\nif __name__ == '__main__':\n    main()\n```\n\n`json_data` は読み込んだ JSON の構造に応じて Python の辞書やリストになります。\n\n**example.json**\n\n```json\n{\n    \"message\": \"Hello, World!\",\n    \"items\": [0, 1, 2],\n    \"ok\": true\n}\n```\n\n上記のファイルに対しては `json_data` は下記のようになります。\n\n```python\n{\n    \"message\": \"Hello, World!\",\n    \"items\": [0, 1, 2],\n    \"ok\": True\n}\n```\n\n### 文字列から読み込み\n\n`json.loads()` を使うと文字列で作成された JSON をパースすることができます。\n\n```python\njson_string = \"\"\"\n{\n    \"message\": \"Hello, World\",\n    \"items\": [\n        0,\n        1,\n        2\n    ],\n    \"ok\": true\n}\n\"\"\"\n\njson_data = json.loads(json_string)\n```\n\n!!! note\n    `json.loads()` の `s` は `string` の `s` です。\n\n## 書き込み\n\n### ファイルに書き込み\n\nJSON ファイルを作成するには `open()` でファイルを開いた後、`json.dump()` にファイルオブジェクトを渡します。\n\n```python\n#!/usr/bin/env python\nimport json\n\n\ndef main():\n    json_data = {\n        \"message\": \"Hello, World!\",\n        \"items\": [0, 1, 2],\n        \"ok\": True,\n    }\n\n    with open('example.json', 'w') as f:\n        json.dump(json_data, f)\n\n\nif __name__ == '__main__':\n    main()\n```\n\n**example.json**\n\n```json\n{\"items\": [0, 1, 2], \"message\": \"Hello, World!\", \"ok\": true}\n```\n\nJSON データは改行されずに出力されます。もし整形して出力させたい場合は `json.dump()` に `indent` オプションを渡します。`indent` にはインデント数を渡します。\n\n```python\njson.dump(json_data, f, indent=4)\n```\n\n```json\n{\n    \"items\": [\n        0,\n        1,\n        2\n    ],\n    \"message\": \"Hello, World!\",\n    \"ok\": true\n}\n```\n\n出力したいデータ内に日本語が含まれていると JSON に変換するときに `\\uXXXX` というエスケープされた形式で変換されてしまいます。\n\n```python\njson_data = {\n    \"message\": \"こんにちは\",\n    \"items\": [0, 1, 2],\n    \"ok\": True,\n}\n```\n\n**結果**\n\n```json\n{\n    \"message\": \"\\u3053\\u3093\\u306b\\u3061\\u306f\",\n    \"items\": [\n        0,\n        1,\n        2\n    ],\n    \"ok\": true\n}\n```\n\n日本語をエスケープさせたくない場合は `json.dump()` に `ensure_ascii=False` オプションを渡します。\n\n```python\njson.dump(json_data, f, indent=4, ensure_ascii=False)\n```\n\n**結果**\n\n```json\n{\n    \"message\": \"こんにちは\",\n    \"items\": [\n        0,\n        1,\n        2\n    ],\n    \"ok\": true\n}\n```\n\n### 文字列に出力\n\nJSON を文字列に出力したい場合は `json.dumps()` を使います。\n\n```python\njson_data = {\n    \"message\": \"Hello, World!\",\n    \"items\": [0, 1, 2],\n    \"ok\": True,\n}\n\njson_string = json.dumps(json_data, indent=4, ensure_ascii=False)\nprint(json_string)\n```\n\n**結果**\n\n```json\n{\n    \"message\": \"Hello, World!\",\n    \"items\": [0, 1, 2],\n    \"ok\": true\n}\n```\n"
  },
  {
    "path": "docs/ch06-01-exceptions.md",
    "content": "# 例外\n\nPython のプログラムで不正な処理を行ったときは例外と呼ばれる割り込み処理が通常の処理に変わって実行されます。例外が発生するタイミングにはいろいろなものがありますが、代表的なものには次のようなものがあります。\n\n## 不正な構文を実行\n\n```python\n#!/usr/bin/env python\n\n\ndef main():\n    print('Hello, World!'\n\n\nif __name__ == '__main__':\n    main()\n```\n\n```shell\n$ python main.py\n  File \"main.py\", line 8\n    if __name__ == '__main__':\n                             ^\nSyntaxError: invalid syntax\n```\n\n`SyntexError` という種類の例外が発生しています。\n\n## 配列のインデックスが不正\n\n```python\n#!/usr/bin/env python\n\n\ndef main():\n    x = [0, 1, 2]\n    print(x[3])\n\n\nif __name__ == '__main__':\n    main()\n```\n\n```shell\n$ python main.py\nTraceback (most recent call last):\n  File \"main.py\", line 10, in <module>\n    main()\n  File \"main.py\", line 6, in main\n    print(x[3])\nIndexError: list index out of range\n```\n\n`IndexError` という種類の例外が発生しています。\n\n## 存在しないファイルをオープン\n\n```python\n#!/usr/bin/env python\n\n\ndef main():\n    with open('file.txt') as f:\n        print(f.read())\n\n\nif __name__ == '__main__':\n    main()\n```\n\n```shell\n$ python main.py\nTraceback (most recent call last):\n  File \"main.py\", line 10, in <module>\n    main()\n  File \"main.py\", line 5, in main\n    with open('file.txt') as f:\nFileNotFoundError: [Errno 2] No such file or directory: 'file.txt'\n```\n\n`FileNotFoundError` という種類の例外が発生しています。このように不正な処理が検知された時点で例外が割り込み、プログラムは停止します。\n\n- `SyntexError`\n- `IndexError`\n- `FileNotFoundError`\n\nはすべて例外クラスを呼ばれるものです。\n\n## 例外を捕捉する\n\n例外が発生したときにプログラムを停止させる代わりに、例外が発生したときに実行する処理を書くこともできます。`try-except` 文を使ってそれが実現できます。\n\n```python\n#!/usr/bin/env python\n\n\ndef main():\n    try:\n        # 例外を監視する処理\n        with open('file.txt') as f:\n            print(f.read())\n    except FileNotFoundError:\n        # 例外発生時の処理\n        print('ファイルが存在しません。')\n\n\nif __name__ == '__main__':\n    main()\n```\n\n```shell\n$ python main.py\nファイルが存在しません。\n```\n\n`try` ブロックで例外が発生しうる処理を記述し、`except` ブロックで例外が発生したときに実行する処理を記述します。 `except` ブロックは複数書くこともでき、そうすることで複数の例外を捕捉することができます。\n\n```python\n#!/usr/bin/env python\n\n\ndef main():\n    try:\n        with open('file.txt') as f:   # file.txt が存在しなければ FileNotFoundError\n            contents = f.read()\n            print(contents[1000])     # ファイル内の文章が 1000 字以上なければ IndexError\n    except FileNotFoundError:\n        print('ファイルが存在しません。')\n    except IndexError:\n        print('文章は 1000 字以上必要です。')\n\n\nif __name__ == '__main__':\n    main()\n```\n\n例外を捕捉するメリットには次のようなものがあります。\n\n- `try-except` を `if-else` のような条件分岐の代わりとして使える\n- どのようなエラーが発生しうるかがコード上で明らかになる\n- エラー発生時の原因や解決策を `print()` などを使って伝えられる\n\n## 例外を送出する\n\n自分で例外を送出することもできます。例外を送出するには `raise` を使います。\n\n```python\ndef factorial(n):\n    if not n >= 0:\n        raise ValueError('n >= 0 である必要があります')\n\n    ...\n```\n\n自分で例外を送出する場合は独自の例外クラスを用意しておいたほうがエラーの起こった箇所が区別しやすくなります。例外クラスを作成するには `Exception` クラスを継承して作成する必要があります。\n\n```python\nclass MyException(Exception):\n    pass\n```\n\n例外クラスの実装は空で問題ありません。 `Exception` を継承している組み込みの例外クラスを継承しても良いです。\n\n!!! tips \"組み込み例外の一覧\"\n    下記ページに例外クラスの一覧が載っていますので参考にして下さい。\n    [https://docs.python.org/ja/3/library/exceptions.html](https://docs.python.org/ja/3/library/exceptions.html)\n"
  },
  {
    "path": "docs/ch07-01-generators.md",
    "content": "# ジェネレータ\n\nジェネレータとは処理を一時停止できる機能を持った関数のことです。処理を一時停止できるということがどういうことなのか、具体的なソースコードで説明していきます。\n\n## ジェネレータの例\n\nまず下記のような処理の挙動について確認しておきます。\n\n**main.py**\n\n```python\n#!/usr/bin/env python\n\n\ndef f():\n    print('開始')\n\n    return\n\n    print('終了')\n\n\ndef main():\n    f()\n    f()\n\n\nif __name__ == '__main__':\n    main()\n```\n\n```shell\n$ python main.py\n開始\n開始\n```\n\n関数 `f()` は通常の関数ですが `return` の後ろに `print()` の呼び出しが入っています。`return` があると関数の処理はそこで終わってしまうので `f()` を実行しても `終了` という文字列はプリントされません。\n\n次に `return` の箇所を `yield` というキーワードに変更して同様のプログラムを実行するとどうなるでしょうか。\n\n```python hl_lines=\"7\"\n#!/usr/bin/env python\n\n\ndef f():\n    print('開始')\n\n    yield\n\n    print('終了')\n\n\ndef main():\n    f()\n    f()\n\n\nif __name__ == '__main__':\n    main()\n```\n\n```shell\n$ python main.py\n開始\n終了\n```\n\n2 回目の `f()` の呼び出しで `終了` という文字列がプリントされるはずです。`yield` は `return` とよく似た挙動をしますが `return` が関数の処理を終了するのに対し `yield` はそこで一時停止をして関数を抜けます。再度 `f()` が呼ばれると `yield` の箇所から関数の処理が再開されます。このように `yield` を使った関数のことをジェネレータといいます。\n\n## ジェネレータを使ったループ\n\nジェネレータは `return` と同様 `yield` で任意の値を返すことができます。\n\n**main.py**\n\n```python\n#!/usr/bin/env python\n\n\ndef f():\n    yield 0\n    yield 1\n    yield 2\n\n\ndef main():\n    print(f())\n    print(f())\n    print(f())\n\n\nif __name__ == '__main__':\n    main()\n```\n\n```shell\n$ python main.py\n0\n1\n2\n```\n\nさらに `for` にジェネレータを渡して値を取り出すこともできます。\n\n```python\ndef main():\n    for x in f():\n        print(x)    # 0, 1, 2\n```\n\nジェネレータを `for` に渡すとジェネレータに書かれた `yield` の個数分だけループが回ります。つまりジェネレータはリストのようなデータ構造とよく似た振る舞いをします。\n\n## ループ処理のカスタマイズ\n\n複雑なループ処理はジェネレータを使うことでシンプルに書くことができるようになります。例えば下記のような 2 つのリストの要素の総当たりの組み合わせを得るような処理を考えます。\n\n```python\ndef main():\n    xs = [0, 1, 2]\n    ys = ['a', 'b', 'c']\n\n    for x in xs:\n        for y in ys:\n            print(x, y)\n```\n\nこのような処理は 2 つのリストを受け取って総当たりの組み合わせを返すジェネレータで書き換えることができます。\n\n```python\ndef product(xs, ys):\n    for x in xs:\n        for y in ys:\n            yield x, y\n\n\ndef main():\n    xs = [0, 1, 2]\n    ys = ['a', 'b', 'c']\n\n    for x, y in product(xs, ys):\n        print(x, y)\n```\n\n`product()` を使うと二重ループが単一ループで書き直せました。実は `product()` は標準ライブラリの [itertools] ですでに用意されているため、わざわざ自分で作らなくても使うことができます。\n\n[itertools]: https://docs.python.org/ja/3/library/itertools.html#itertools.product\n"
  },
  {
    "path": "docs/ch08-01-doctest.md",
    "content": "# doctest\n\nPython にはソースコードのドキュメンテーションをサポートするための docstring という文字列を使ってドキュメントを作成することができます。さらに docstring には関数の使用例を記述するための構文が用意されています。またその使用例を示すコードは関数が実際に記述したとおりに振る舞うかどうかをテストする機能も備わっており doctest と呼ばれます。\n\n**main.py**\n\n```python\n#!/usr/bin/env python\n\n\n\"\"\"\nサンプルモジュールです。\n\nこのモジュールは factorial() という関数を提供しており、次のように使用します。\n\n>>> factorial(5)\n120\n\"\"\"\n\n\nimport math\n\n\ndef factorial(n):\n    \"\"\"n >=0 であるような整数に対する階乗を計算します。\n\n    >>> [factorial(n) for n in range(6)]\n    [1, 1, 2, 6, 24, 120]\n\n    >>> factorial(30)\n    265252859812191058636308480000000\n    >>> factorial(-1)\n    Traceback (most recent call last):\n        ...\n    ValueError: n >= 0 である必要があります\n\n    浮動小数点型も渡せますが、その値は整数値である必要があります。\n    >>> factorial(30.1)\n    Traceback (most recent call last):\n        ...\n    ValueError: n は整数でなければいけません\n    >>> factorial(30.0)\n    265252859812191058636308480000000\n\n    極端に大きな整数値を渡しても階乗の計算はできません。\n    >>> factorial(1e100)\n    Traceback (most recent call last):\n        ...\n    OverflowError: n の値が大きすぎます\n    \"\"\"\n\n    if not n >= 0:\n        raise ValueError('n >= 0 である必要があります')\n    if math.floor(n) != n:\n        raise ValueError('n は整数でなければいけません')\n    if n + 1 == n:\n        raise OverflowError('n の値が大きすぎます')\n\n    result = 1\n    factor = 2\n\n    while factor <= n:\n        result *= factor\n        factor += 1\n\n    return result\n\n\nif __name__ == '__main__':\n    import doctest\n    doctest.testmod()\n```\n\n`\"\"\"...\"\"\"` のようにトリプルクオテーションで囲まれた文字列が docstring です。通常はソースコード・関数・クラスの先頭部分で記述します。`>>>` から始まる行\n\n```python\n>>> factorial(5)\n120\n```\n\nは Python のコードを記述するための行で、その処理を実行したらどのように振る舞うのかを `>>>` の下部に記述します。実行時に例外を送出する場合はその旨を記述することもできます。\n\n```python\n>>> factorial(-1)\nTraceback (most recent call last):\n    ...\nValueError: n >= 0 である必要があります\n```\n\ndocstring 内のコードが記述したとおりに動くかどうかを確認するためには doctest モジュールを使用します。\n\n```python\nimport doctest\ndoctest.testmod()\n```\n\nこのように記述しておき\n\n```shell\n$ python main.py\n```\n\nと実行すると doctest が走ります。`factorial()` の実装が期待通りになっている場合は何も表示されませんが、もしバグが混入していた場合はエラーメッセージが出力されます。下記は `result = 1` の部分を `result = 10` と書いてしまっていた場合の doctest の実行結果になります。\n\n```shell\n$ python main.py\n**********************************************************************\nFile \"main.py\", line 9, in __main__\nFailed example:\n    factorial(5)\nExpected:\n    120\nGot:\n    1200\n**********************************************************************\nFile \"main.py\", line 20, in __main__.factorial\nFailed example:\n    [factorial(n) for n in range(6)]\nExpected:\n    [1, 1, 2, 6, 24, 120]\nGot:\n    [10, 10, 20, 60, 240, 1200]\n**********************************************************************\nFile \"main.py\", line 23, in __main__.factorial\nFailed example:\n    factorial(30)\nExpected:\n    265252859812191058636308480000000\nGot:\n    2652528598121910586363084800000000\n**********************************************************************\nFile \"main.py\", line 35, in __main__.factorial\nFailed example:\n    factorial(30.0)\nExpected:\n    265252859812191058636308480000000\nGot:\n    2652528598121910586363084800000000\n**********************************************************************\n2 items had failures:\n   1 of   1 in __main__\n   3 of   6 in __main__.factorial\n***Test Failed*** 4 failures.\n```\n\n## なぜ doctest を使うのか\n\ndoctest を使うことで次のような機能を提供することができます。\n\n- プログラムの使用例をドキュメントに記述できる\n- その使用例が単体テストとして使用できる\n- プログラムの実装と使用例が同期しているかどうか用意に確認できる\n\nプログラムの使い方を記述しておくことはとても重要なことですが、ドキュメントというのは時間が経つと形骸化しやすいものです。しかし doctest を使ってドキュメントを管理しておくとプログラムの内容と同期が取れているかどうかを簡単に確認できるため、形骸化することがなくなります。\n"
  },
  {
    "path": "docs/ch08-02-pytest.md",
    "content": "# pytest\n\nPython には単体テストを書くためのフレームワークがいくつかあります。\n\n| フレームワーク | 説明               |\n|----------------|--------------------|\n| unittest       | 標準ライブラリ     |\n| nose           | かつては主流だった |\n| pytest         | 現在主流のもの     |\n\n上記の通り Python は標準ライブラリを使って単体テストを書くことができますが、サードパーティ製の pytest の使い勝手が良いため、pytest を使って書かれることが多いです。そこでここでは pytest の簡単な使い方について説明します。\n\n## 準備\n\n[プロジェクト構成](./ch04-07-project-structures.md) を参考に、単体テストのソースコードは `tests` 配下に作成するようにします。ソースコードが 1 つで十分な場合はディレクトリを作らなくても構いません。\n\n下記のような構成でファイルを作成し、素数判定のコードをテストしてみましょう。\n\n```shell\nprime\n├── prime.py\n└── test_prime.py\n```\n\n!!! warning \"注意\"\n    テストを複数ファイルに分割して書く場合は `tests` ディレクトリを作成し、その中に `__init__.py` を含めるようにしてください。`__init__.py` がないとテストが正しく実行できなくなります。詳しくは [ディレクトリ構成](./ch04-07-project-structures.md) を参考にしてください。\n\n## インストール\n\npipenv を使ってインストールします。\n\n```shell\n$ mkdir fibonacci\n$ cd fibonacci\n$ pipenv install -d pytest\n```\n\n`-d` というのは開発時にだけ必要となるパッケージをインストールするときに指定するフラグです。単体テストは通常開発時にしか必要ないため大抵のケースで pytest は `-d` を指定してインストールするのが良いでしょう。\n\n## テストの書き方\n\nまず素数判定を行う関数を書きます。\n\n**prime.py**\n\n```python\ndef is_prime(n: int) -> bool:\n    if n <= 1:\n        return False\n\n    if n == 2:\n        return True\n\n    if n % 2 == 0:\n        return False\n\n    i = 3\n\n    while i * i <= n:\n        if n % i == 0:\n            return False\n\n        i += 2\n\n    return True\n```\n\n今回はこのプログラムを直接実行するわけではないため、シバンや `main()` は不要です。次にこの関数に対するテストを下記のように記述します。\n\n**test_prime.py**\n\n```python\nfrom prime import is_prime\n\n\ndef test_is_prime():\n    assert not is_prime(1)\n    assert is_prime(2)\n    assert is_prime(3)\n    assert not is_prime(4)\n    assert is_prime(5)\n    assert not is_prime(6)\n    assert is_prime(7)\n    assert not is_prime(8)\n    assert not is_prime(9)\n    assert not is_prime(10)\n```\n\npytest は `test_` で始まるファイル・関数を単体テストのコードとみなします。テストしたい関数を `import` 文で取り込み、`assert` という文の後ろにテストしたい式を記述します。\n\n## テスト実行\n\nテストを実行するには `pytest` というコマンドを使います。\n\n```shell\n$ pipenv shell\n(prime) $ pytest test_prime.py\n============================================== test session starts ==============================================\nplatform darwin -- Python 3.7.3, pytest-4.5.0, py-1.8.0, pluggy-0.11.0\nrootdir: /Users/kenichiro-ida/Documents/github.com/rinatz/prime\ncollected 1 item\n\ntest_prime.py .                                                                                           [100%]\n\n=========================================== 1 passed in 0.02 seconds ============================================\n```\n\n素数判定が正しく実装されていなかった場合の挙動を確認するため、`is_prime()` から次の行を無効にして再度テストを実行してみます。\n\n**prime.py**\n\n```python hl_lines=\"8 9\"\ndef is_prime(n: int) -> bool:\n    if n <= 1:\n        return False\n\n    if n == 2:\n        return True\n\n    # if n % 2 == 0:\n    #     return False\n\n    i = 3\n\n    while i * i <= n:\n        if n % i == 0:\n            return False\n\n        i += 2\n\n    return True\n```\n\n```shell\n(prime) $ pytest test_prime.py\n============================================== test session starts ==============================================\nplatform darwin -- Python 3.7.3, pytest-4.5.0, py-1.8.0, pluggy-0.11.0\nrootdir: /Users/kenichiro-ida/Documents/github.com/rinatz/prime\ncollected 1 item\n\ntest_prime.py F                                                                                           [100%]\n\n=================================================== FAILURES ====================================================\n_________________________________________________ test_is_prime _________________________________________________\n\n    def test_is_prime():\n        assert not is_prime(0)\n        assert not is_prime(1)\n        assert is_prime(2)\n        assert is_prime(3)\n>       assert not is_prime(4)\nE       assert not True\nE        +  where True = is_prime(4)\n\ntest_prime.py:9: AssertionError\n=========================================== 1 failed in 0.09 seconds ============================================\n```\n\n`is_prime(4)` が `True` になっているというエラーメッセージが出力されています。\n\n## パラメータ化したテスト\n\n上記の例では `is_prime(4)` のテストに失敗すると、その時点でテストが終わってしまうため、`is_prime(5)` 以降のテストがどうなるかは分かりませんでした。このようなケースでは **パラメータ化したテスト** を作ることで `1～10` までのすべての値をテストできるようになります。\n\nパラメータ化したテストはテスト内で使用するパラメータを関数の引数として渡せるように書き直したテストのことです。パラメータ化したテストでテストを記述した場合は、すべてのパラメータのテストを実行するまでテストが続行されます。チュートリアルの `test_is_prime()` をパラメータ化したテストで書き直すと次のようになります。\n\n```python\nimport pytest\n\nfrom prime import is_prime\n\n\n@pytest.mark.parametrize(('number', 'expected'), [\n    (1, False),\n    (2, True),\n    (3, True),\n    (4, False),\n    (5, True),\n    (6, False),\n    (7, True),\n    (8, False),\n    (9, False),\n    (10, False),\n])\ndef test_is_prime(number, expected):\n    assert is_prime(number) == expected\n```\n\n`@pytest.mark.parametrize()` はデコレータと呼ばれるもので、これにテストで使用するパラメータを記述します。デコレータの最初の引数 `('number', 'expected')` はテスト関数に渡すパラメータの引数名になります。第 2 引数は実際に渡すパラメータの値をタプルのリストとして記述します。\n\n```python\n@pytest.mark.parametrize(('number', 'expected'), [\n    (1, False),\n])\n```\n\nのように記述すると `test_is_prime(1, False)` が実行されます。複数記述すればその分だけ `number, expected` に値が渡され `test_is_prime()` が実行されます。\n\n### 注意点\n\nデコレータの書き方には注意して下さい。次のいずれも正しい書き方ではありません。\n\n**スペルミス**\n\n!!! warning \"誤\"\n    `@pytest.mark.parameterized`\n\n!!! check \"正\"\n    `@pytest.mark.parametrized`\n\n**文字列をタプルにしていない**\n\n!!! warning \"誤\"\n    ```python\n    @pytest.mark.parametrized('number', 'expected', [\n        ...\n    ])\n    ```\n\n!!! check \"正\"\n    ```python\n    @pytest.mark.parametrized(('number', 'expected'), [\n        ...\n    ])\n    ```\n\n**タプルをリストの要素としない**\n\n!!! warning \"誤\"\n    ```python\n    @pytest.mark.parametrized(('number', 'expected'),\n        (1, False),\n        (2, True),\n        ...\n    )\n    ```\n\n!!! check \"正\"\n    ```python\n    @pytest.mark.parametrized(('number', 'expected'), [\n        (1, False),\n        (2, True),\n        ...\n    ])\n    ```\n\n## フィクスチャ\n\nフィクスチャはテストの実行前後で行いたい前処理・後処理を記述するために使用する関数のことです。各テストで同じ前処理・後処理を行う必要がある場合に暗黙的にそれが実行できるようになります。\n\n### ファイルを扱うテスト\n\nファイルを扱う関数はフィクスチャが有効です。今ファイルから整数を受け取り、それを昇順に読み込む関数を考えます。\n\n```python\nfrom typing import List\n\n\n# List[int] で要素が int のリスト型を表す型ヒントになる\ndef load_numbers_sorted(txt: str) -> List[int]:\n    numbers = []\n\n    with open(txt) as f:\n        numbers = sorted(map(lambda e: int(e), f))\n\n    return numbers\n```\n\nこの関数は入力値としてファイルのパスを受け取ります。そのため、事前にファイルを用意しなければいけません。このファイルを用意するためにフィクスチャが利用できます。\n\n!!! warning \"注意\"\n    関数がファイルを必要とするからと言ってテスト用のファイルをあらかじめリポジトリにコミットするようなことは避けるべきです。そのようなことをするとテストパターンが増えるたびにファイルも増えてしまい、管理が複雑になります。\n\n### 前処理の書き方\n\n下記のような整数を保存したファイルを用意して `load_numbers_sorted()` のためのテスト `test_load_numbers_sorted()` を作成してみます。\n\n**numbers.txt**\n\n```\n2\n5\n4\n3\n1\n```\n\n`test_load_numbers_sorted()` が実行される前にファイルを用意する必要があるため次のようにフィクスチャを使ってファイルを作成します。\n\n```python\nimport pytest\n\n\n@pytest.fixture\ndef txt() -> str:\n    with open('numbers.txt', 'w') as f:\n        for n in [2, 5, 4, 3, 1]:\n            f.write('{}\\n'.format(n))\n\n    yield 'numbers.txt'\n```\n\n`numbers.txt` というファイルを作り、そのファイル名を返却しています。このフィクスチャを使って `test_load_numbers_sorted()` を実行するには次のようにします。\n\n```python\ndef test_load_numbers_sorted(txt):\n    assert load_numbers_sorted(txt) == [1, 2, 3, 4, 5]\n```\n\nテスト関数にフィクスチャと同じ名前の引数 `txt` を渡します。すると `txt` にはフィクスチャ `txt()` の戻り値 `numbers.txt` が入ってきます。このコードを実行すると\n\n1. `txt()` が呼ばれる\n1. `numbers.txt` が作成される\n1. `test_load_numbers_sorted('numbers.txt')` が呼ばれる\n\nという振る舞いをします。\n\n### 後処理の書き方\n\n`numbers.txt` はテストが終われば不要なため、後処理としてファイルを削除してあげましょう。ファイルを削除するにはフィクスチャ `txt()` に次の行を追加します。\n\n```python\nimport os\n\n\n@pytest.fixture\ndef txt() -> str:\n    ...\n\n    yield 'numbers.txt'\n\n    os.remove('numbers.txt')\n```\n\nこうするとテストが終わると `os.remove('numbers.txt')` が呼び出され、ファイルが削除されます。つまりフィクスチャは\n\n```python\n@pytest.fixture\ndef txt():\n    # 前処理\n\n    yield ...   # テスト関数に何らかの値を渡す\n\n    # 後処理\n```\n\nという構造をしています。`test_load_numbers_sorted(txt)` の引数 `txt` はフィクスチャ `txt()` で\n何を返したかで型が決まります。\n\n### フィクスチャの連携\n\nフィクスチャから別のフィクスチャを呼び出すこともできます。\n\n```python\n@pytest.fixture\ndef txt_and_list(txt) -> Tuple[str, List[int]]:\n    yield txt, [1, 2, 3, 4, 5]\n\n\ndef test_load_numbers_sorted(txt_and_list):\n    assert load_numbers_sorted(txt_and_list[0]) == txt_and_list[1]\n```\n\nこの場合 `txt() -> txt_and_list()` の順にフィクスチャが実行され、その結果が `test_load_numbers_sorted()` に渡されます。\n\n### テンポラリの作成\n\npytest には安全にテンポラリを作成するための `tmpdir` というフィクスチャがあらかじめ用意されています。先に見た例ではファイルがローカルに作られるため、大量のファイルが作られるとディレクトリが汚れてしまいますが `tmpdir` を使うと `/tmp` 配下にファイルを作成するため、ファイル管理がスマートになります。\n\n`tmpdir` の使い方は次のとおりです。\n\n```python\n@pytest.fixture\ndef txt(tmpdir) -> str:\n    tmpfile = tmpdir.join('numbers.txt')\n\n    with tmpfile.open('w') as f:\n        for n in [2, 5, 4, 3, 1]:\n            f.write('{}\\n'.format(n))\n\n    yield str(tmpfile)\n\n    tmpfile.remove()\n```\n\n### フィクスチャのスコープ\n\n通常フィクスチャはテスト単位で呼び出されます。\n\n```python\ndef test_sample1(txt):\n    ...\n\n\ndef test_sample2(txt):\n    ...\n```\n\nこの場合、フィクスチャ `txt()` は各テスト関数を実行するたびに毎回呼び出されます。場合によってはこれが非効率で冗長になることもあります。このような場合はフィクスチャが呼び出されるタイミングを次のようにして変更することができます。\n\n```python\n@pytest.fixture(scope='module')\ndef txt(tmpdir) -> str:\n    ...\n```\n\n`scope` に指定できる値は次のとおりです。\n\n| scope    | 説明                                                        |\n| -------- | ----------------------------------------------------------- |\n| function | テスト関数ごとにフィクスチャを実行（デフォルト）            |\n| module   | 同一モジュール（ソースコード）内で1回だけフィクスチャを実行 |\n| class    | 同一クラス内で1回だけフィクスチャを実行                     |\n| session  | テスト実行時に1回だけフィクスチャを実行                     |\n\nただフィクスチャのスコープはむやみに広げないほうが良いです。フィクスチャの設定をテスト間で共有すると依存関係が生まれてしまい、不意にテストが成功してしまうケースがあるからです。テスト関数ごとにフィクスチャを実行しても問題ない場合はそのようにすべきです。\n\n### conftest.py\n\n複数のファイルをまたいで共通のフィクスチャを使用したいこともあると思います。そのような時はフィクスチャを `conftest.py` というファイルに定義しましょう。`conftest.py` 内のフィクスチャは pytest によって自動的にインポートされ、`conftest.py` があるディレクトリ配下で暗黙的に参照できるようになります。\n\n```\n.\n└─tests\n    ├─conftest.py .............. 全テストで参照可能\n    ├─test_sample1\n    │  ├─conftest.py .......... test_sample2.py, test_sample3.py で参照可能\n    │  ├─test_sample2.py\n    │  └─test_sample3.py\n    └─test_sample4\n        ├─conftest.py .......... test_sample5.py, test_sample6.py で参照可能\n        ├─test_sample5.py\n        └─test_sample6.py\n```\n\n## 標準出力のキャプチャ\n\n標準出力にメッセージを出力する関数をテストしたい時には標準出力をキャプチャして出力されたメッセージを確認することができます。例えば次のようなフィボナッチ数列を出力する関数を考えます。\n\n```python\ndef fibonacci(n: int):\n    a = 0\n    b = 1\n\n    for _ in range(n):\n        print(b)\n\n        a, b = b, a + b\n```\n\nこの関数を `fibonacci(5)` として呼び出すと標準出力には\n\n```\n1\n1\n2\n3\n5\n```\n\nと出力されます。本当にこのように出力されるかどうかをテストしたい時には次のように書きます。\n\n```python\ndef test_fibonacci(capsys):\n    fibonacci(5)\n\n    out, _ = capsys.readouterr()\n\n    assert out == (\n        '1\\n'\n        '1\\n'\n        '2\\n'\n        '3\\n'\n        '5\\n'\n    )\n```\n\n`capsys` は標準出力と標準エラー出力をキャプチャするためのフィクスチャです。\n\n```python\ncapsys.readouterr()\n```\n\nはキャプチャした標準出力と標準エラー出力の文字列をタプルとして返します。\n\n## モック\n\nモックとは関数やクラスが相互に依存して動作する時に、依存する関数やクラスが正しく使われているかどうかをテストする時に使われるオブジェクトのことです。例えば次のコードを見てみましょう。\n\n**interaction.py**\n\n```python\ndef send(message: str):\n    receive(message)\n\n\ndef receive(message: str):\n    print('received: {}'.format(message))\n```\n\nいま関数 `send()` は引数で受け取った文字列を `receive()` にそのまま渡さなければならないという仕様があったとします。このとき、 `send()` が仕様どおりに実装されているかどうかをテストするためには\n\n- `send()` は `receive()` を1回だけ呼び出しているか？\n- `send()` が受け取った文字列は `receive()` にそのまま渡されているか？\n\nを確認する必要があります。もしこの振る舞いをテストで確認することができれば\n\n```python\ndef send(message: str):\n    receive('[1]: {}'.format(message))\n    receive('[2]: {}'.format(message))\n```\n\nのように仕様に沿っていない実装を間違った実装として検出できるようになります。モックを使うとこのような確認がテストできるようになります。\n\n### モックの使い方\n\nモックを使うには [pytest-mock] という pytest のプラグインを使用します。インストールは pipenv で次のようにできます。\n\n```shell\n$ pipenv install -d pytest-mock\n```\n\n`send()` が正しい形式で `receive()` を呼び出しているかどうかを確認するためには `receive()` が受け取った引数と呼び出し回数を記憶する仕組みが必要になります。それを実現するために `receive()` を偽の実装にすり替えて、引数や呼び出し回数を保存できるオブジェクト（すなわちモック）にするというアプローチを取ります（これをモンキーパッチといいます）。`pytest-mock` をインストールすると `mocker` というフィクスチャが使用できるようになります。この `mocker` を使って次のように `receive()` をモックにすることができます。\n\n```python\ndef test_send(mocker):\n    receive = mocker.patch('studies.interaction.receive')\n```\n\n`mocker.patch()` は引数で受け取った文字列の関数をモック化して返す関数です。`mocker.patch()` を呼び出した後では `send()` が呼び出す `receive()` は `interaction.py` で定義された `receive()` の代わりにモック化された偽の `receive()` が呼び出されるようになります。\n\n```python\ndef test_send(mocker):\n    receive = mocker.patch('studies.interaction.receive')\n\n    send('Hello World!')\n```\n\nここで呼び出した `send()` は内部で `receive()` を呼んでいますがその `receive()` は `mocker.patch()` が作成したモック化された `receive` になります。そしてこの `receive` は引数で受け取った値や呼び出し回数を記録したオブジェクトになっています。\n\nさらに次のような行をテストコードに追加してみましょう。\n\n```python\nreceive.assert_called_once_with('Hello World!')\n```\n\nこれは `receive()` が `'Hello World!'` という文字列を受け取って 1 回だけ呼び出されたかどうかを確認するテストになります。テストコード全体は次のとおりになります。\n\n```python\ndef test_send(mocker):\n    receive = mocker.patch('studies.interaction.receive')\n\n    send('Hello World!')\n\n    receive.assert_called_once_with('Hello World!')\n```\n\n試しに `send()` の実装をわざと間違えた実装にしてみましょう。`receive.assert_called_once_with()` のところでテストが失敗するはずです。\n\n### 呼び出し履歴の確認\n\nモック `receive` は自分がどのような引数で何回呼ばれたのかを履歴として残しています。その呼び出し履歴を参照するには `receive.call_args_list` を参照します。\n\n```python\n>>> receive.call_args_list\n[call('Hello World!')]\n```\n\nこれは `receive()` が `'Hello World!'` を引数として1回だけ呼ばれたことを意味します。このリストの内容を確認しても `send()` が `receive()` を正しく呼んだかどうかをテストすることができます。\n\n```python\ndef test_send(mocker):\n    receive = mocker.patch('studies.interaction.receive')\n\n    send('Hello World!')\n\n    assert receive.call_args_list == [\n        mocker.call('Hello World!'),\n    ]\n```\n\n例えば `send()` が次のように実装されていたとすると\n\n```python\ndef send(message: str):\n    receive('[1]: {}'.format(message))\n    receive('[2]: {}'.format(message))\n```\n\n呼び出し履歴のテストは\n\n```python\nassert receive.call_args_list == [\n    mocker.call('[1]: Hello World!'),\n    mocker.call('[2]: Hello World!'),\n]\n```\n\nと書くことができます。\n\n### 戻り値の定義\n\n`send()` の振る舞いが `receive()` の戻り値に依存して変わるケースを考えます。\n\n```python\ndef send(message: str):\n    ok = receive(message)\n\n    if ok:\n        print('success')\n    else:\n        print('failure')\n\n\ndef receive(message: str) -> bool:\n    print('received: {}'.format(message))\n\n    return True\n```\n\nこの場合 `receive()` の戻り値に応じて `send()` が出力するメッセージが変わることをテストで確認する必要が出てきます。サンプルの `receive()` は常に `True` しか返さないので、 `False` を返した時の\n`send()` の振る舞いが確認できません。このような場合でもモックを使って `receive()` の戻り値を上手く制御することができます。\n\n```python\ndef test_send(mocker, capsys):\n    receive = mocker.patch('studies.interaction.receive', return_value=False)\n\n    send('Hello World!')\n\n    receive.assert_called_once_with('Hello World!')\n\n    out, _ = capsys.readouterr()\n\n    assert out == 'failure\\n'\n```\n\n`mocker.patch()` の引数に `return_value=False` を渡すと `send()` 内で呼び出している `receive()` は `False` を返すように偽装されます。\n\n### スパイ\n\nモックを使うと `receive()` の実装は完全に別物に置き換わりますが場合によっては本物の `receive()` を呼びつつ、呼び出し回数を確認したいこともあると思います。そのような場合はスパイを作成することで実現できます。例えば `receive()` が `studies/interaction.py` に定義されている場合\n\n```python\nimport studies.interaction\n\nreceive = mocker.spy(studies.interaction, 'receive')\n```\n\nとすることでスパイを作成することができます。`mocker.spy()` が返却する関数は本物の `receive()` に `assert_called_once_with()` などのメソッドが追加されたインスタンスになります。使い方はモンキーパッチの場合と同様です。\n\n[pytest]: https://docs.pytest.org/en/latest/\n[pytest-mock]: https://github.com/pytest-dev/pytest-mock\n"
  },
  {
    "path": "docs/ch09-01-tools.md",
    "content": "# ツール一覧\n\nPython には pip や venv 以外にも開発で使用するツールが多く存在しており、ネットで調べるときに混乱することが多いです。\nそこでどんなツールが使われているのかを整理して解説します。\n\nネットで検索して見つかる Python ツールは、おおむね次の 3 つに分類されます。\n\n1. Python 自体のバージョンを管理する\n2. 仮想環境を管理する\n3. パッケージやパッケージ間の依存関係を管理する\n\nツールによっては 2. と 3. の両方をサポートするようなツールもあるため、どういうシーンで利用すればよいのかがわかりにくいところがあります。\n\nネットで検索して見つかるツールには次のようなものがあります。\n\n| ツール                        | Python バージョン管理 | 仮想環境管理                     | パッケージ管理                   | 依存関係解決       | ロックファイル生成 | パフォーマンス     | 備考                           |\n| ----------------------------- | --------------------- | -------------------------------- | -------------------------------- | ------------------ | ------------------ | ------------------ | ------------------------------ |\n| pyenv                         | :white_check_mark:    |                                  |                                  |                    |                    | :star:             | Python のバージョン管理        |\n| [venv](./ch04-04-venv.md)     |                       | :white_check_mark:               |                                  |                    |                    | :star:             | Python 標準ライブラリ          |\n| virtualenv                    |                       | :white_check_mark:               |                                  |                    |                    | :star::star:       | `venv` で代用可能              |\n| [pip](./ch04-03-pip.md)       |                       |                                  | :white_check_mark:               |                    |                    | :star:             | Python 標準のパッケージ管理    |\n| pip-tools                     |                       |                                  | :white_check_mark:               | :white_check_mark: | :white_check_mark: | :star:             | `requirements.txt` 強化        |\n| pipx                          |                       |                                  | :white_check_mark:（グローバル） |                    |                    | :star::star:       | CLI ツール専用                 |\n| [pipenv](./ch09-02-pipenv.md) |                       | :white_check_mark:               | :white_check_mark:               | :white_check_mark: | :white_check_mark: | :octicons-star-24: | 遅いため最近は非推奨気味       |\n| [poetry](./ch09-03-poetry.md) |                       | :white_check_mark:               | :white_check_mark:               | :white_check_mark: | :white_check_mark: | :star::star:       | 近年の推奨ツール               |\n| rye                           | :white_check_mark:    | :white_check_mark:               | :white_check_mark:               | :white_check_mark: | :white_check_mark: | :star::star:       | 試験的だが統合ツールとして注目 |\n| uv                            |                       | :white_check_mark:（内部で管理） | :white_check_mark:               | :white_check_mark: | :white_check_mark: | :star::star::star: | `pip-tools` の超高速代替       |\n\n## どのツールを使うべきか\n\nどのツールを使う場合でも `requirements.txt` は生成しておくのがベターです\n（どのツールでも生成コマンドが用意されています）。\n`requirements.txt` があれば、Python の標準機能である pip を使ってパッケージのインストールができるようになるためです。\n\n`requirements.txt` さえ生成していれば、どのツールを使ってもよいですが、使い分けのおおまかな方針は次のようになります。\n\n### シンプルな開発\n\n- `venv` + `pip` （標準機能）\n- `pip-tools` （依存関係を固定したい場合）\n\n### より便利な管理を求める場合\n\n- `poetry` （仮想環境＋パッケージ管理）\n- `pipx` （CLI ツール管理）\n\n### 最新のトレンドを取り入れたい場合\n\n- `rye` （統合環境管理の試験的ツール）\n- `uv` （超高速なパッケージ管理）\n\n### Python のバージョン管理をしたい場合\n\n- `pyenv` （複数の Python バージョンを使いたい場合）\n"
  },
  {
    "path": "docs/ch09-02-pipenv.md",
    "content": "# pipenv\n\n`pipenv` は `pip` と `venv` の両方の機能を兼ね備えたサードパーティ製のパッケージ管理ツールです。`venv` で仮想環境を作成してから `pip` でパッケージをインストールするまでの手順では下記のように異なるコマンドを実行する必要がありますが、これを 1 つのコマンドで実行できるようにしたものが `pipenv` です。\n\n| 操作                     | コマンド (macOS, Linux) | コマンド (Windows)             |\n|--------------------------|-------------------------|--------------------------------|\n| 仮想環境の作成           | `python -m venv .venv`  | `py -m venv .venv`             |\n| 仮想環境を有効にする     | `. .venv/bin/activate`  | `.venv/Scripts/activate.bat`   |\n| 仮想環境を無効にする     | `deactivate`            | `.venv/Scripts/deactivate.bat` |\n| パッケージのインストール | `pip3 install [name]`   | `py -3 -m pip install [name]`  |\n\n各操作に応じて実行するコマンドも異なれば OS ごとにも異なっており、とても複雑です。しかし `pipenv` を使うと上記の操作は次のようになります。\n\n| 操作                     | コマンド                |\n|--------------------------|-------------------------|\n| 仮想環境の作成           | `pipenv --python 3`        |\n| 仮想環境を有効にする     | `pipenv shell`          |\n| 仮想環境を無効にする     | `exit`                  |\n| パッケージのインストール | `pipenv install [name]` |\n\nこのように `pipenv` というコマンド 1 つで仮想環境の作成とパッケージのインストールの両方が実行できるため、操作がシンプルになります。また実行するコマンドは OS によらず同じです。\n\n## 特徴\n\n`pipenv` はパッケージのインストールを必ず仮想環境内で実行するように作られています。そのため仮想環境を有効にしていない状態で\n\n```shell\n$ pipenv install [name]\n```\n\nというコマンドを打っても自動的に仮想環境を作成して、それを有効にした上でパッケージのインストールを実行します。\n\n## インストール\n\n`pipenv` のインストールは下記のようにします。\n\n```shell\n$ pip3 install pipenv\n```\n\n!!! note\n    `pipenv` のインストールは仮想環境内で行う必要はありません。なぜなら `pipenv` 自体が仮想環境を作成するツールだからです。\n\n## 使い方\n\nまず作業用ディレクトリを用意します。\n\n```shell\n$ mkdir sandbox\n```\n\n`pipenv` を使ってサードパーティライブラリの `requests` をインストールするには次のようにします。\n\n```shell\n$ cd sandbox\n$ pipenv install requests\n```\n\n自動的に仮想環境が作成され、その仮想環境内に `requests` がインストールされます。次に `requests` を使用した次のようなソースコードを用意します。\n\n**main.py**\n\n```python\n#!/usr/bin/env python\n\n\nimport requests\n\n\ndef main():\n    response = requests.get('http://example.com')\n    print(response.text)\n\n\nif __name__ == '__main__':\n    main()\n```\n\nソースコードを作成したら仮想環境を有効にして実行してみます。\n\n```shell\n$ pipenv shell\n(sandbox) $ python main.py\n```\n\n上記の 2 行のコマンドは次のように 1 行で実行することもできます。\n\n```shell\n$ pipenv run python main.py\n```\n\n`pipenv run [command]` は仮想環境を有効にした上で `[command]` を実行してくれる機能です。\n\n## Pipfile\n\n`pip` にはインストールしたいパッケージをテキストファイルに記述しておく `requirements.txt` という仕組みがありましたが、`pipenv` はこれの代替として `Pipfile` というテキストファイルが使用できます。先程の `requests` をインストールするとディレクトリ内に `Pipfile` が作成されていると思います。\n\n**Pipfile**\n\n```shell\n[[source]]\nname = \"pypi\"\nurl = \"https://pypi.org/simple\"\nverify_ssl = true\n\n[dev-packages]\n\n[packages]\nrequests = \"*\"\n\n[requires]\npython_version = \"3.7\"\n```\n\n`pipenv` はパッケージをインストールすると `Pipfile` にインストールしたパッケージを記録するようになっています。もしディレクトリ内に `Pipfile` がある場合、下記のコマンドを実行すると `Pipfile` 内に記述されたパッケージをインストールしてくれます。\n\n```shell\n$ pipenv install\n```\n\nつまり `Pipfile` をバージョン管理しておくことで他の人の環境でも自分がインストールしたパッケージと同じものをインストールできるようになります。\n\n## Pipfile.lock\n\n`Pipfile` と合わせて `Pipfile.lock` というファイルも作成されていると思います。このファイルはインストールしたパッケージのバージョンを保存しているファイルです。`pipenv install` でパッケージをインストールすると、インストールされるパッケージのバージョンはその時点での最新版が取得されるようになっているため、自分がインストールしたパッケージのバージョンとは厳密には異なるバージョンのパッケージが他の人の環境にインストールされる可能性があります。もしバージョンも含めて完全に一致するものをインストールしたい場合は `Pipfile` の代わりに `Pipfile.lock` を使ってインストールすることで実現できます。\n\n`Pipfile.lock` を使ってインストールするには次のようにします。\n\n```shell\n$ pipenv sync\n```\n\n## 公式サイト\n\n`pipenv` はここで説明した機能以外にも便利な機能がたくさんあります。詳細は公式サイトに説明がありますので参考にしてみてください。\n\n!!! note \"pipenv 公式サイト\"\n    [https://pipenv.readthedocs.io/en/latest/](https://pipenv.readthedocs.io/en/latest/)\n"
  },
  {
    "path": "docs/ch09-03-poetry.md",
    "content": "# poetry\n\n`poetry` は `pipenv`と同様の課題を解決するために作られたサードパーティ製のパッケージ管理ツールです。\n\n!!! note \"poetry 公式サイト\"\n    [https://python-poetry.org/](https://python-poetry.org/)\n\npoetry を使った場合の仮想環境の作成からパッケージのインストールまでの手順は下記のとおりです。\n\n| 操作                     | コマンド                |\n|--------------------------|-------------------------|\n| 仮想環境の作成           | なし（暗黙的に作られる）|\n| 仮想環境を有効にする     | `poetry shell`          |\n| 仮想環境を無効にする     | `exit`                  |\n| パッケージのインストール | `poetry add [name]`     |\n\n## インストール\n\n`poetry` のインストールは下記のようにします。\n\n=== \"Linux, macOS, Windows (WSL)\"\n\n    ```shell\n    $ curl -sSL https://install.python-poetry.org | python3 -\n    ```\n\n=== \"Windows (Powershell)\"\n\n    PowerShell 上で下記を実行します。\n\n    ```shell\n    (Invoke-WebRequest -Uri https://install.python-poetry.org -UseBasicParsing).Content | py -\n    ```\n\n## 使い方\n\nまず作業ディレクトリを用意します。\n\n```shell\n$ mkdir sandbox\n```\n\n次に poetry の設定ファイルを生成するコマンドを実行します。\n\n```shell\n$ poetry init -n\n```\n\nコマンドを実行すると `pyproject.toml` というファイルが作成されます。\n\n次に `pipenv` のときと同様に `requests` をインストールしてみます。\n\n```shell\n$ poetry add requests\n```\n\n`pipenv` の使い方で使用したソースコードを実行するには下記のようにします。\n\n```shell\n$ poetry shell\n(.venv) $ python main.py\n```\n\n上記の 2 行のコマンドは次のように 1 行で実行することもできます。\n\n```shell\n$ poetry run python main.py\n```\n\n## pyproject.toml と poetry.lock\n\n`pyproject.toml` は poetry の設定ファイルです。`pipenv` でいうところの `Pipfile` と同じ位置づけのファイルになります。\n\n**pyproject.toml**\n\n```toml\n[tool.poetry]\nname = \"sandbox\"\nversion = \"0.1.0\"\ndescription = \"\"\nauthors = [\"...\"]\n\n[tool.poetry.dependencies]\npython = \"^3.6\"\nrequests = \"^2.24.0\"\n\n[tool.poetry.dev-dependencies]\n\n[build-system]\nrequires = [\"poetry>=0.12\"]\nbuild-backend = \"poetry.masonry.api\"\n```\n\n`poetry.lock` はインストールしたパッケージのバージョンを保存しているファイルです。`pipenv` でいうところの `Pipfile.lock` と同じ位置づけのファイルになります。\n\n`pipenv` の場合 `Pipfile` や `Pipfile.lock` の内容をもとにパッケージをインストールするには下記のようにコマンドを使い分ける必要がありました。\n\n| 使用ファイル   | コマンド         |\n|----------------|------------------|\n| `Pipfile`      | `pipenv install` |\n| `Pipfile.lock` | `pipenv sync`    |\n\n`poetry` にも同等の機能があるのですが `pyproject.toml` の内容をもとにパッケージをインストールする場合も `poetry.lock` の内容をもとにパッケージをインストールする場合もコマンドは同じです。\n\n```shell\n$ poetry install\n```\n\n`pyproject.toml` と `poetry.lock` の両方がある場合は `poetry.lock` の内容が優先されるという仕組みになっています。\n\n## pipenv との違い\n\n詳細は割愛しますが `poetry` の方が `pipenv` よりも機能が豊富です。また `pyproject.toml` は `poetry` 専用の設定ファイルではなく Python が公式に策定したパッケージ管理用の設定ファイルになっているため、他のパッケージ管理ツールの設定ファイルとしても使われます。`pip` も新しいバージョンでは `pyproject.toml` を使用することができるようになっています。\n"
  },
  {
    "path": "docs/index.md",
    "content": "# ゼロから学ぶ Python\n\n<div align=\"center\">\n    <img src=\"img/python.svg\" />\n</div>\n\nこのサイトは Python を学ぶ人向けのオンライン学習サイトです。\n\n## 対象\n\n- Python を初めて学ぶ人\n- プログラム言語を 1 つ以上経験したことのある人\n\n関数やクラス・オブジェクト指向に対する知識をある程度前提にします。\n\n## Python の特徴\n\n- 学習コストが低い\n- 標準ライブラリが非常に豊富\n- インデントをすることが言語仕様になっている\n\n## Python のバージョンについて\n\n- `2.x.x`: 2020 年 1 月 1 日でサポート終了\n- `3.x.x`: 現行バージョン\n\n`2.x.x` 系は新規開発では使用すべきではありません。このサイトでは `3.x.x` をベースに説明を行います。\n"
  },
  {
    "path": "mkdocs.yml",
    "content": "site_name: ゼロから学ぶ Python\nsite_description: ゼロから学ぶ Python\nsite_author: IDA Kenichiro\nsite_url: http://rinatz.github.io/python-book\nrepo_name: rinatz/python-book\nrepo_url: https://github.com/rinatz/python-book\ncopyright: Copyright &copy 2025 IDA Kenichiro\n\ntheme:\n  name: material\n  palette:\n    # ライトモード\n    - media: \"(prefers-color-scheme: light)\"\n      scheme: default\n      primary: orange\n      accent: blue\n      toggle:\n        icon: material/weather-sunny\n        name: ダークモードに切り替え\n    # ダークモード\n    - media: \"(prefers-color-scheme: dark)\"\n      scheme: slate\n      primary: orange\n      accent: blue\n      toggle:\n        icon: material/weather-night\n        name: ライトモードに切り替え\n  font:\n    text: Noto Sans\n    code: Inconsolata\n  language: ja\n  logo: img/python.svg\n  favicon: img/python.svg\n  icon:\n    repo: fontawesome/brands/github\n  features:\n    - navigation.instant\n\nmarkdown_extensions:\n  - toc:\n      permalink: true\n  - admonition\n  - pymdownx.details\n  - pymdownx.superfences\n  - pymdownx.highlight\n  - pymdownx.inlinehilite\n  - pymdownx.tabbed\n  - footnotes\n  - pymdownx.emoji:\n      emoji_index: !!python/name:material.extensions.emoji.twemoji\n      emoji_generator: !!python/name:material.extensions.emoji.to_svg\n  - pymdownx.arithmatex:\n      generic: true\n  - meta\n\nnav:\n  - ホーム: index.md\n  - 1. Python を始める:\n    - 1.1. インストール: ch01-01-installation.md\n    - 1.2. Hello, World!: ch01-02-hello-world.md\n  - 2. 基本仕様:\n    - 2.1. 変数: ch02-01-variables.md\n    - 2.2. 関数: ch02-02-functions.md\n    - 2.3. コメント: ch02-03-comments.md\n    - 2.4. 条件文: ch02-04-conditions.md\n    - 2.5. ループ文: ch02-05-loops.md\n    - 2.6. リスト内包表記: ch02-06-list-comprehensions.md\n    - 2.7. ラムダ式: ch02-07-lambdas.md\n  - 3. クラス:\n    - 3.1. クラス: ch03-01-classes.md\n    - 3.2. スコープ: ch03-02-scopes.md\n    - 3.3. 特殊属性: ch03-03-special-attributes.md\n    - 3.4. プロパティ: ch03-04-properties.md\n  - 4. モジュールとパッケージ:\n    - 4.1. モジュール: ch04-01-modules.md\n    - 4.2. パッケージ: ch04-02-packages.md\n    - 4.3. pip: ch04-03-pip.md\n    - 4.4. venv: ch04-04-venv.md\n    - 4.7. プロジェクト構成: ch04-07-project-structures.md\n  - 5. ファイル操作:\n    - 5.1. ファイル操作: ch05-01-files.md\n    - 5.2. コンテキスト: ch05-02-contexts.md\n    - 5.3. CSV: ch05-03-csv.md\n    - 5.4. JSON: ch05-04-json.md\n  - 6. 例外:\n    - 6.1. 例外: ch06-01-exceptions.md\n  - 7. ジェネレータ:\n    - 7.1. ジェネレータ: ch07-01-generators.md\n  - 8. テスト:\n    - 8.1. doctest: ch08-01-doctest.md\n    - 8.2. pytest: ch08-02-pytest.md\n  - 9. 便利ツール:\n    - 9.1. ツール一覧: ch09-01-tools.md\n    - 9.2. pipenv: ch09-02-pipenv.md\n    - 9.3. poetry: ch09-03-poetry.md\n"
  },
  {
    "path": "pyproject.toml",
    "content": "[project]\nname = \"python-book\"\nversion = \"1.0.0\"\ndescription = \"ゼロから学ぶPython\"\nreadme = \"README.md\"\nrequires-python = \">=3.12\"\ndependencies = [\n    \"mkdocs-material>=9.5.50\",\n]\n"
  },
  {
    "path": "requirements.txt",
    "content": "# This file was autogenerated by uv via the following command:\n#    uv pip compile pyproject.toml\nbabel==2.16.0\n    # via mkdocs-material\ncertifi==2024.12.14\n    # via requests\ncharset-normalizer==3.4.1\n    # via requests\nclick==8.1.8\n    # via mkdocs\ncolorama==0.4.6\n    # via mkdocs-material\nghp-import==2.1.0\n    # via mkdocs\nidna==3.10\n    # via requests\njinja2==3.1.5\n    # via\n    #   mkdocs\n    #   mkdocs-material\nmarkdown==3.7\n    # via\n    #   mkdocs\n    #   mkdocs-material\n    #   pymdown-extensions\nmarkupsafe==3.0.2\n    # via\n    #   jinja2\n    #   mkdocs\nmergedeep==1.3.4\n    # via\n    #   mkdocs\n    #   mkdocs-get-deps\nmkdocs==1.6.1\n    # via mkdocs-material\nmkdocs-get-deps==0.2.0\n    # via mkdocs\nmkdocs-material==9.5.50\n    # via python-book (pyproject.toml)\nmkdocs-material-extensions==1.3.1\n    # via mkdocs-material\npackaging==24.2\n    # via mkdocs\npaginate==0.5.7\n    # via mkdocs-material\npathspec==0.12.1\n    # via mkdocs\nplatformdirs==4.3.6\n    # via mkdocs-get-deps\npygments==2.19.1\n    # via mkdocs-material\npymdown-extensions==10.14.1\n    # via mkdocs-material\npython-dateutil==2.9.0.post0\n    # via ghp-import\npyyaml==6.0.2\n    # via\n    #   mkdocs\n    #   mkdocs-get-deps\n    #   pymdown-extensions\n    #   pyyaml-env-tag\npyyaml-env-tag==0.1\n    # via mkdocs\nregex==2024.11.6\n    # via mkdocs-material\nrequests==2.32.3\n    # via mkdocs-material\nsix==1.17.0\n    # via python-dateutil\nurllib3==2.3.0\n    # via requests\nwatchdog==6.0.0\n    # via mkdocs\n"
  }
]