{"id":20324643,"url":"https://github.com/gh640/python-idioms-ja","last_synced_at":"2026-03-09T18:37:34.439Z","repository":{"id":74923723,"uuid":"158377974","full_name":"gh640/python-idioms-ja","owner":"gh640","description":"🤹‍♀️  (Japanese) Python 3 のイディオム集です。","archived":false,"fork":false,"pushed_at":"2021-06-23T07:37:18.000Z","size":26,"stargazers_count":8,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-06-20T03:43:23.342Z","etag":null,"topics":["idioms","japanese","python","python-3"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gh640.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-11-20T11:20:56.000Z","updated_at":"2023-02-18T13:05:17.000Z","dependencies_parsed_at":null,"dependency_job_id":"23191be4-3c63-44a9-940e-d629f7c0214f","html_url":"https://github.com/gh640/python-idioms-ja","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/gh640/python-idioms-ja","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gh640%2Fpython-idioms-ja","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gh640%2Fpython-idioms-ja/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gh640%2Fpython-idioms-ja/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gh640%2Fpython-idioms-ja/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gh640","download_url":"https://codeload.github.com/gh640/python-idioms-ja/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gh640%2Fpython-idioms-ja/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30307548,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-09T17:35:44.120Z","status":"ssl_error","status_checked_at":"2026-03-09T17:35:43.707Z","response_time":61,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["idioms","japanese","python","python-3"],"created_at":"2024-11-14T19:36:45.398Z","updated_at":"2026-03-09T18:37:34.412Z","avatar_url":"https://github.com/gh640.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Python 3 イディオム集\n\nPython 3.x のイディオム集です。\n\n## 目次\n\n変数宣言\n\n- [関係の強い複数の変数の定義](#関係の強い複数の変数の定義)\n\n名前\n\n- [使用しない変数の名前](#使用しない変数の名前)\n- [コレクション系の値の名前](#コレクション系の値の名前)\n\n組み込みデータ型\n\n- [`dict` のキーの存在チェック](#dict-のキーの存在チェック)\n- [`dict` のサブセットの取得](#dict-のサブセットの取得)\n- [複数の `dict` のマージ](#複数の-dict-のマージ)\n- [`list` のコピー](#list-のコピー)\n- [`list` の長さを変える](#list-の長さを変える)\n- [ネストされた `list` の要素の組み換え](#ネストされた-list-の要素の組み換え)\n\n内包表記\n\n- [複雑な内包表記の記述](#複雑な内包表記の記述)\n\n条件式\n\n- [コレクション系の値の非空チェック](#コレクション系の値の非空チェック)\n- [`not` が含まれる条件式](#not-が含まれる条件式)\n\n制御フロー\n\n- [多岐分岐](#多岐分岐)\n- [`for` ループ](#for-ループ)\n- [インデックスが必要な `for` ループ](#インデックスが必要な-for-ループ)\n- [複数の iterable の `for` ループ](#複数の-iterable-の-for-ループ)\n\n例外\n\n- [複数の例外のキャッチ](#複数の例外のキャッチ)\n\n改行\n\n- [行の長さ制限を守るための改行](#行の長さ制限を守るための改行)\n\n関数\n\n- [関数のデフォルト引数](#関数のデフォルト引数)\n- [引数の数が多い関数](#引数の数が多い関数)\n- [複数の戻り値](#複数の戻り値)\n\nクラス\n\n- [インタフェース](#インタフェース)\n- [メソッドチェーン](#メソッドチェーン)\n\nモジュール\n\n- [バージョンによって場所が異なる関数やクラスの `import`](#バージョンによって場所が異なる関数やクラスの-import)\n\nファイル\n\n- [ファイル利用](#ファイル利用)\n\n## 変数宣言\n\n### 関係の強い複数の変数の定義\n\n関係の強い複数の変数を定義するときはかっこ無しの `tuple` 表記を使うと、関係性がわかりやすくなります。\n\n```python\nimport datetime\n\nyear, month, day = 2018, 5, 27\n\n...\n\ndate = datetime.date(year, month, day)\n```\n\n## 名前\n\n### 使用しない変数の名前\n\n割り当てる必要があるがその後使用しない変数の名前には `_` などを使います。\n\n```python\nhead, *_ = calculation()\n```\n\n```python\nvalues = [1, 3, 5]\nvalues += [-1 for _ in range(10 - len(values))]\n```\n\n`_` が特定の用途に使われる文脈（たとえば Django では `_` が文字列を翻訳するための関数名としてよく使われます）では、衝突を避けるために `__` などを使います。\n\n### コレクション系の値の名前\n\n`list` ・ `tuple` 等のコレクション系の値の名前には単語の複数形を使います。\n\n```python\n# ○:\nnumbers = [1, 3, 5, ...]\nurls = (\n    'https://www.google.co.jp',\n    'https://www.facebook.com',\n    'https://twitter.com',\n)\nmenu_items = (\n    ('/about/', '○○とは'),\n    ('/services/', 'サービス'),\n    ('/contact/', '問い合わせ'),\n)\n\n# ✕:\nnumber = [...]\nurl = (\n    ...,\n)\nmenu_item = (\n    ...,\n)\n```\n\n`for` ループや内包表記でその要素を取り出すときは単数形を使います。\nスコープが狭く意味が明白な場合は 1 文字変数を使っても大丈夫です。\n\n```python\n# ○:\nfor n in numbers:\n    ...\n\nfor url in urls:\n    ...\n\nfor i in menu_items:\n    ...\n```\n\n## 組み込みデータ型\n\n### `dict` のキーの存在チェック\n\n`dict` に存在するかどうかわからないキーで要素にアクセスする場合は例外処理を使用します。\n\n```python\n# ○:\ntry:\n    value = adict[key]\nexcept KeyError:\n    ...\n...\n\n# ✕:\nif key in adict:\n    value = adict[key]\n    ...\n```\n\nこのスタイルは「 EAFP 」スタイル（ Easier to Ask for Forgiveness than Permission ）と呼ばれたりします。\n\n- [EAFP ― Glossary — Python 3.x documentation](https://docs.python.org/3/glossary.html#term-eafp)\n\n他方の `if` 文を使ったスタイルは「 LBYL 」スタイル（ Look Before You Leap ）と呼ばれます。\n\n- [LBYL ― Glossary — Python 3.x documentation](https://docs.python.org/3/glossary.html#term-lbyl)\n\n### `dict` のサブセットの取得\n\n`dict` のサブセットの取得には `{}` を使った `dict` の内包表記を使用します。\n\n```python\nadict = {'tokyo': 'T', 'hokkaido': 'H', 'okinawa': 'O', 'kagoshima': 'K'}\ntargets = ['tokyo', 'kagoshima']\n\n# ○:\nsubdict = {k: adict[k] for k in targets}\n# {'tokyo': 'T', 'kagoshima': 'K'}\n\n# ○:\nsubdict = {k: adict[k] for k in adict.keys() \u0026 targets}\n# {'kagoshima': 'K', 'tokyo': 'T'}\n```\n\n### 複数の `dict` のマージ\n\n複数の `dict` を組み合わせて新たな `dict` を作りたいときは `dict` のアンパック演算を使用します。\n\n```python\ndict1 = {...}\ndict2 = {...}\ndict3 = {...}\n\nmerged_dict = {**dict1, **dict2, **dict3}\n```\n\nキーの衝突が発生した場合は後に方に記述された `dict` の値が残ります:\n\n```python\nitems1 = {'コーラ': 'ペプシ', 'ジンジャーエール': 'ウィルキンソン'}\nitems2 = {'ジンジャーエール': 'カナダドライ'}\n\nmerged = {**items1, **items2}\n# =\u003e {'コーラ': 'ペプシ', 'ジンジャーエール': 'カナダドライ'}\n```\n\n`dict` の数が不定の場合は `dict` の内容表記（ dict comprehension ）を使うとシンプルに書けます。\n\n```python\nmany_dicts = [dict1, dict2, ..., dictn]\n\nmerged_dict = {k: v for d in many_dicts for k, v in d.items()}\n```\n\n### `list` のコピー\n\n`list` のコピー（複製）には `copy()` メソッドを使用します。\n\n```python\nalist = [...]\n\n# ○:\ncloned_list = alist.copy()\n```\n\nPython 3.3 未満（ 3.2 以下）のバージョンでは `copy()` メソッドが提供されていないので次の書き方を使います。\n\n```python\nalist = [...]\n\n# ○:\ncloned_list = alist[:]\n```\n\n### `list` の長さを変える\n\n`list` の長さを変えるには次のようなやり方があります。\n\n短くする:\n\n```python\noriginal = [x ** 2 for x in range(11)]\n# =\u003e [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]\n\n# 先頭を残して長さを 3 にする\noriginal[:3]\n# =\u003e [0, 1, 4]\n\n# 末尾を残して長さを 3 にする\noriginal[-3:]\n# =\u003e [64, 81, 100]\n```\n\n長くする:\n\n```python\n# 末尾に追加する\noriginal = [x ** 2 for x in range(3)]  # =\u003e [0, 1, 4]\nlength = 5\noriginal += [None for _ in range(length - len(original))]\noriginal\n# =\u003e [0, 1, 4, None, None]\n\n# 先頭に追加する\noriginal = [x ** 2 for x in range(3)]  # =\u003e [0, 1, 4]\nlength = 5\noriginal = [None for _ in range(length - len(original))] + original\noriginal\n# =\u003e [None, None, 0, 1, 4]\n```\n\n規定の長さに揃える:\n\n```python\ndef normalize_length(alist, length, fallback):\n    \"\"\"list の長さを揃える\"\"\"\n    shortened = alist[:length]\n    return shortened + [fallback for _ in range(length - len(shortened))]\n```\n\n### ネストされた `list` の要素の組み換え\n\nネストされた `list` （または `tuple` ）の要素を組み替えるには `*` 演算子（スプラット演算子）と `zip()` 関数を使うとシンプルに書けます。\n\n```python\noriginal = [['ね', 'ねずみ'], ['うし', 'うし'], ['とら', 'とら'], ['う', 'うさぎ']]\n\nshorts, fulls = [x for x in zip(*original)]\nshorts\n# =\u003e ('ね', 'うし', 'とら', 'う')\nfulls\n# =\u003e ('ねずみ', 'うし', 'とら', 'うさぎ')\n```\n\nネストされた `list` を行列と見るなら、これは「行列の行と列を入れ替える方法」ということができます。\n\n## 内包表記\n\n### 複雑な内包表記の記述\n\n複雑な内包表記を読みやすくするには、処理の一部をローカルの関数にして抽出する、小さなジェネレータ式に分割して記述する、等の方法があります。\n\n```python\nclass MyModel:\n    FIELD_LABEL_MAP = {...}\n\n    # 整理前: 複雑な内包表記\n    def get_target_field_labels(self):\n        return [\n            self.FIELD_LABEL_MAP.get(field.name, '')\n            for field in seld.model.get_fields()\n            if isinstance(field, models.CharField) and field.editable\n        ]\n\n    # 整理後: 処理の一部をローカルの関数にして抽出する\n    def get_target_field_labels(self):\n        def label(field):\n            return self.FIELD_LABEL_MAP.get(field.name, '')\n\n        def is_target(field):\n            return isinstance(field, models.CharField) and field.editable\n\n        return [\n            label(field)\n            for field in seld.model.get_fields()\n            if is_target(field)\n        ]\n\n    # 整理後: 小さなジェネレータ式に分割して記述する\n    def get_target_field_labels(self):\n        target_fields = (x for x in seld.model.get_fields()\n                         if isinstance(x, models.CharField) and x.editable)\n        labels = (self.FIELD_LABEL_MAP.get(x.name) for x in target_fields)\n        return list(labels)\n```\n\n\n## 条件式\n\n### コレクション系の値の非空チェック\n\n`list` ・ `tuple` ・ `dict` 等のコレクション系の値の非空チェックは名前を `if` 文に直接渡して行います。\n\n```python\nlinks = magical_func_collecting_links(url)\n\n# ○:\nif links:\n    ...\n\n# ✕:\nif len(links):\n    ...\n\n# ✕:\nif len(links) \u003e 0:\n    ...\n```\n\n### `not` が含まれる条件式\n\n`not` が含まれる条件式は人間が読んで読みやすい形（≒英語の語順に近い形）で書きます。\n\n```python\n# ○:\nif value is not None:\n    ...\n\n# ✕:\nif not value is None:\n    ...\n```\n\n```python\n# ○:\nif key not in adict:\n    ...\n\n# ✕:\nif not key in adict:\n    ...\n\n# ✕:\nif not (key in adict):\n    ...\n```\n\n## 制御フロー\n\n### 多岐分岐\n\nPython 3.10 で `match` ~ `case` 構文が導入されたので、 Python 3.10 以降では `match` ~ `case` 構文を使います。\n\n```python\n# ○:\ndef printer_factory(name):\n    match name:\n        case 'html':\n            return HtmlPrinter()\n        case 'pdf':\n            return PdfPrinter()\n        case 'toml':\n            return TomlPrinter()\n        case 'dsv':\n            return DsvPrinter()\n        case _:\n            raise ValueError(f'不正な name が指定されました: {name}。')\n```\n\n#### 以前の説明（ Python 3.9 以前）\n\n他の言語にある `switch`/`case` のようなことをしたい場合は `dict` を使用します。\n\n```python\n# ○:\ndef printer_factory(name):\n    printer_map = {\n        'html': HtmlPrinter,\n        'pdf': PdfPrinter,\n        'toml': TomlPrinter,\n        'dsv': DsvPrinter,\n    }\n\n    try:\n        return printer_map[name]()\n    except KeyError as e:\n        raise ValueError('不正な name が指定されました: {}。'.format(name))\n```\n\n### `for` ループ\n\niterable のループには原則インデックスを使いません。\n\n```python\nurls = [\n    'https://www.google.co.jp',\n    'https://www.facebook.com',\n    'https://twitter.com',\n]\n\n# ○:\nfor url in urls:\n    print(url)\n\n# ✕:\nfor i in range(len(urls)):\n    print(urls[i])\n```\n\n### インデックスが必要な `for` ループ\n\nインデックスが必要な `for` ループには `enumerate()` を使用します。\n\n```python\nanimals = [\n    '子',\n    '丑',\n    '寅',\n]\n\n# ○:\nfor i, animal in enumerate(animals):\n    print('順位 {:02d}: {}'.format(i, animal))\n# =\u003e\n# 順位 00: 子\n# 順位 01: 丑\n# 順位 02: 寅\n\n# ○:\nfor i, animal in enumerate(animals, start=1):\n    print('順位 {:02d}: {}'.format(i, animal))\n# =\u003e\n# 順位 01: 子\n# 順位 02: 丑\n# 順位 03: 寅\n```\n\n### 複数の iterable の `for` ループ\n\n`for` ループで複数の iterable を同時に回したい場合は `zip` を使用します。\n\n```python\nanimals = ['猫', '馬', '河童']\nanimals_en = ['cat', 'horse', 'kappa']\n\n# ○:\nfor animal, animal_en in zip(animals, animals_en):\n    print('{} は英語で {} です。'.format(animal, animal_en))\n\n# ✕:\nfor i in range(min(len(animals), len(animals_en))):\n    print('{} は英語で {} です。'.format(animals[i], animals_en[i]))\n```\n\n2 つの iterable の長さが異なる場合、 `zip()` は短い方の長さだけループを回します。\n長い方の長さにあわせたい場合は `itertools.zip_longest()` を使用します。\n\n```python\nfrom itertools import zip_longest\n\n# ○:\nfor animal, animal_en in zip_longest(animals, animals_en):\n    ...\n```\n\n## 例外\n\n### 複数の例外のキャッチ\n\n複数の例外をキャッチする場合は、「小さい例外」（例外クラスの継承ツリーにおいて子孫側の例外）を先に、「大きい例外」を後にキャッチします。\n\n```python\nclass CustomBaseError(Exception):\n    pass\n\nclass InvalidValueError(CustomBaseError):\n    pass\n\n# ○:\ntry:\n    myfunc()\nexcept InvalidValueError as e:\n    ...\nexcept CustomBaseError as e:\n    ...\n\n# ✕:\ntry:\n    myfunc()\nexcept CustomBaseError as e:\n    ...\nexcept InvalidValueError as e:\n    ...\n```\n\n## 改行\n\n### 行の長さ制限を守るための改行\n\nコードをそのまま書くと 80 文字や 100 文字等の行長さ制限にひっかかる場合は、 `()` を使用したり式を分割したりして制限以内に収めます。\n\n関数・メソッド呼び出し:\n\n```python\n# ○:\nclass Student(models.Model):\n    year_in_school = models.CharField(\n        max_length=2,\n        choices=YEAR_IN_SCHOOL_CHOICES,\n        default=FRESHMAN,\n        db_index=True,\n    )\n\n# ✕\nclass Student(models.Model):\n    year_in_school = models.CharField(max_length=2, choices=YEAR_IN_SCHOOL_CHOICES, default=FRESHMAN, db_index=True)\n\n```\n\nメソッドチェーン:\n\n```python\n# ○:\nclass PublishedBookRelatedManager(models.Manager):\n    def get_queryset(self):\n        books_published = Book.published_objects.all()\n        return (\n            super()\n            .get_queryset()\n            .distinct()\n            .filter(book__in=books_published)\n        )\n\n# ✕:\nclass PublishedBookRelatedManager(models.Manager):\n    def get_queryset(self):\n        return super().get_queryset().distinct().filter(book__in=Book.published_objects.all())\n\n# ✕:\nclass PublishedBookRelatedManager(models.Manager):\n    def get_queryset(self):\n        books_published = Book.published_objects.all()\n        return super().get_queryset() \\\n            .distinct() \\\n            .filter(book__in=books_published)\n```\n\n文字列:\n\n```python\nclass MyFormView(FormView):\n    def form_valid(self, form):\n        # この形で書かれた文字列リテラルは自動的に連結されるので `+` 演算子は不要です\n        message = (\n            'お問い合わせいただきありがとうございます。'\n            'ご入力いただいたメールアドレスに 3 営業日以内にご連絡差し上げます。'\n            '連絡が無い場合は大変お手数ですが再度お問い合わせいただきますようお願いいたします。'\n        )\n        messages.success(message)\n        return super().form_valid(form)\n```\n\n## 関数\n\n### 関数のデフォルト引数\n\n関数のデフォルト引数には原則 mutable な値は使いません。\n\n```python\n# ○:\ndef merge_dicts(d1=None, d2=None):\n    d1 = d1 or {}\n    d2 = d2 or {}\n\n    d1.update(d2)\n    return d1\n\n# ✕:\ndef merge_dicts(d1={}, d2={}):\n    d1.update(d2)\n    return d1\n\nmerge_dicts(d2={'a': 1})\n# =\u003e {'a': 1}\nmerge_dicts(d2={'b': 2})\n# =\u003e {'a': 1, 'b': 2}\nmerge_dict()\n# =\u003e {'a': 1, 'b': 2}\n```\n\n### 引数の数が多い関数\n\n引数の数が多い関数を使用するときは、実行側でキーワード指定で引数を渡します。\n\n```python\ndef easy_to_misuse_func(file, column, cond, coerce):\n    ...\n\n# ○:\neasy_to_misuse_func(file=a, column=b, cond=c, coerce=d)\n\n# ✕:\neasy_to_misuse_func(a, b, c, d)\n```\n\n関数の定義側で引数の間に `*,` を置くことで、キーワード指定での引数渡しを強制することもできます。\n\n```python\ndef easy_to_misuse_func(*, file, column, cond, coerce):\n    ...\n\neasy_to_misuse_func(a, b, c, d)\n# =\u003e\n# TypeError: easy_to_misuse_func() takes 0 positional arguments but 4 were given\n\neasy_to_misuse_func(file=a, column=b, cond=c, coerce=d)\n# =\u003e OK\n```\n\n\u003e Parameters after “\\*” or “\\*identifier” are keyword-only parameters and may only be passed used keyword arguments.\n\n- [Function definitions ― Compound statements — Python 3 documentation](https://docs.python.org/3/reference/compound_stmts.html#function-definitions)\n\n### 複数の戻り値\n\n関数やメソッドに複数の戻り値を持たせたい場合は `tuple` を使用します。\n\n```python\nimport requests\n\n# ○:\ndef get_page(url):\n    res = requests.get(url)\n    return res.ok, res.content\n\nis_ok, content = get_page('https://www.yahoo.co.jp/')\n```\n\n`tuple` ではまかなえなくなったら、 `collections.namedtuple` や独自クラスのインスタンスを使います。\n\n## クラス\n\n### インタフェース\n\nPython 3 にはオブジェクト指向言語で一般的な「インタフェース」が言語仕様として備わっていません。\n\n「継承先クラスにメソッドの実装を矯正する」という意味でインタフェースに近い挙動を実現するには、標準モジュール `abc` のクラス `ABC` とデコレータ `abc.abstractmethod` を使用します。\n\n```python\nimport abc\n\n\nclass ControllerInterface(abc.ABC):\n    @abc.abstractmethod\n    def dispatch(self, request):\n        pass\n\n\nclass HomePageController(ControllerInterface):\n    def dispatch(self, request):\n        ...\n\n\nclass InvalidController(ControllerInterface):\n    # `dispatch()` が定義されていないのでインスタンス生成時に `TypeError` があがる\n    pass\n```\n\n`abc.abstractmethod` に似たデコレータに以下のものがあります。\n\n- `abc.abstractclassmethod`\n- `abc.abstractstaticmethod`\n\n`abc.abstractmethod` のようにインスタンス生成時にチェックは走りませんが、例外 `NotImplementedError` を使用する方法もあります:\n\n```python\nfrom abc import ABC\n\n\nclass ControllerInterface(ABC):\n    def dispatch(self, request):\n        raise NotImplementedError()\n\n\nclass HomePageController(ControllerInterface):\n    def dispatch(self, request):\n        ...\n\n\nclass InvalidController(ControllerInterface):\n    # `dispatch()` が定義されていないので `dispatch()` が呼び出されたときに `NotImplementedError` があがる\n    pass\n```\n\nただし、いずれの場合でもクラス宣言時にエラーがあがるわけではないため、インタフェースが正しく実装されていることの確認にはテスト等を使用する必要があります。\n\n### メソッドチェーン\n\n自作のクラスでメソッドを連ねて呼び出したい場合は、メソッドが `self` （または新しいインスタンス）を返すようにします。\n\n```python\n# ○:\nclass Query:\n    def select(self, columns):\n        ...\n        return self\n\n    def where(self, column, value):\n        ...\n        return self\n\n\nfigure1 = (Query()\n           .select(['figure'])\n           .where('rhand', 'チョキ')\n           .where('lhand', 'グー'))\nfigure2 = (Query()\n           .select(['figure'])\n           .where('rhand', 'パー')\n           .where('lhand', 'パー'))\n```\n\n## モジュール\n\n### バージョンによって場所が異なる関数やクラスの `import`\n\nモジュールのバージョンによって場所が異なる関数やクラスの `import` には `try` `except` を使用します。\n\n```python\n# ○:\ntry:\n    from urllib.parse import urlparse\nexcept:\n    from urlparse import urlparse\n```\n\n## ファイル\n\n### ファイル利用\n\nファイルを利用する際は原則 `with` 文（コンテキストマネージャ）を使用します。\n\n```python\npath = 'sample.txt'\n\n# ○:\nwith open(path) as f:\n    ...\n\n# ✕:\nf = open(path)\n...\nf.close()\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgh640%2Fpython-idioms-ja","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgh640%2Fpython-idioms-ja","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgh640%2Fpython-idioms-ja/lists"}