🗒️

Python Cheat Sheet

2024/07/15に公開

他のプログラミング言語の経験がある方や久々にPythonを使う方向けに、短時間でPythonの言語仕様を思い出すためのCheat Sheetを作成した。

初版ではPythonチュートリアルの内容を中心に記載しているが、今後も内容を追加予定。

制御構文

while文

a, b = 0, 1
while a < 10:
    print(a)
    a, b = b, a + b

for文

# シーケンス型に対する反復を行う。
# while文とfor文はbreak, continueでの制御が可能。
animals = ['cat', 'dog']
# dictやtupleのリストをfor a, b in xの形式で受け取ることも可能。
for a in animals:
    print(a)
# else: 最後のループの後に実行される。
else:
    print("end")

if文

if x < 0:
    print('negative')
elif x == 0:
    print('zero')
else:
    print('positive')

match文

# caseに記述したパターンとのマッチングを順に行い、最初にマッチしたパターンを実行する。
# Pythonにswitch文はなく3.10で構造的パターンマッチングが可能なmatchが導入された。
match a:
    # | (or) で複数パターンをまとめて記述できる。
    case 0 | 1:
        print(p)
    # シーケンスやオブジェクトに対してunpackと同様の構文で変数に代入できる。
    case (x, 1):
        print(x)
    # ワイルドカードパターン
    case _:
        raise ValueError("Not a point")

関数定義

# =でデフォルトの引数値を設定できる。
# *args, **kwargs で残りの位置引数、キーワード引数を受け取れる。
def f(x, y=1, *args, **kwargs):
    # ドキュメンテーション文字列
    # 各セクションの記述方法にはNumpy, Google (下記の記載例)などの流派がある。
    """Do something.

    Args:
        x: a parameter
        ...
    """
    print(f"x={x}, y={y}, args={args}, kwargs={kwargs}")

# /と*で仮引数を区切ることで引数の指定方法を以下の3種類に制限できる。
# (1) 位置専用、(2) 位置またはキーワード、(3) キーワード専用
def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):
    pass

ラムダ式

def make_incrementor(n):
    return lambda x: x + n

デコレータ

import functools

# 引数の関数を実行するラッパー関数を返却する関数を作成する。
def debug(func):
    @functools.wraps(func) # __name__等の関数の情報をコピーするためのデコレータ
    def wrapper(*args, **kwargs):
        print(f"args: {args}, kwargs: {kwargs}")
        func(*args, **kwargs)
    return wrapper

@debug
def sum(a: int, b: int):
    return a + b

データ構造

リスト・タプル

# 内包表記
users = [f"{name}-{i}" for name in ["taro", "hanako"] for i in range(2)]

# 主要なメソッド
users.index('taro-1') # 1
users.pop(1) # taro-1 (要素が削除される)
users.remove("hanako-0")
users.append('jiro-0')
users.sort()
users.reverse()
users.clear() # del users[:] と同じ

# インデックスを使ったループ。enumerateはシーケンス型に対して使える。
for i, u in enumerate(users):
    print(f"{i}: {u}")

# タプル
# リストと異なり不変オブジェクト。複数の型を要素に設定されることが多い。
t = (1, "abc") # この場合 () は省略可能。1要素の場合は 1, と記述です。
_, a = t # アンパック

集合型

# 重複する要素をもたない、順序づけられていない要素の集まり
s = {1, 2, 3, 1} # {1, 2, 3}
s = set([1, 2, 3, 1]) # set()にシーケンス型を渡して生成もできる。
s = set() # 空のsetを生成する。{}は空のdictを生成することに注意。

辞書型

d = {'a': 1, 2: 'b'}

# 値の取得
d['c'] = 3 # 存在しないキーの場合KeyErrorとなる。d.get()を使うとNoneとなる。
# 項目の削除
del d['a']

# キー・値でのループ。キーのみの場合はd.keys()、値のみの場合はd.values()と記述できる。
for k, v in d.items():
    print(k, v)

モジュール・パッケージ

# パッケージ・モジュールのインポート
# importしたオブジェクトを自モジュールの名前空間に設定する。
# a/                      トップレベルパッケージa
#     __init__.py         パッケージとして認識させるために必要なファイル
#                         (例外としてnamespace packageではファイルを省略できる。)
#                         パッケージaの初期化処理を記述する。
#     b/                  サブパッケージb
#          __init__.py    パッケージbの初期化処理を記述する。
#          c.py           モジュールc (func関数が定義されているとする)
import a               # a.b.c.func()
from a.b.c import func # func()
from a.b import b as d # d.c.func()
from a import *        # b.c.func() 
                       # パッケージaの全て (_で始まるもの以外)の名前をインポートする。
                       # 名前空間の意図しない変更リスクがあり、推奨されない記述方法。

例外処理

try:
    # raiseで例外を発生させる。fromで例外の連鎖を設定できる。
    raise ValueError('error') from err
# ValueErrorもしくはその派生クラスを捕捉する。
except ValueError as err:
    # except節で例外をraiseすると自動的に元の例外がスタックに追加される。
    # 例外の連鎖を無効にするには raise RuntimeError() from None とする。
    # https://docs.python.org/3/tutorial/errors.html#exception-chaining
    raise RuntimeError()
except Exception as err:
    # 例外に対して情報を追加できる。
    # https://docs.python.org/ja/3/tutorial/errors.html#enriching-exceptions-with-notes
    err.add_note('additional information')
    # raiseのみ記述すると同じ例外を再度発生させることができる。
    raise
# else: try節で例外が発生しなかった場合に実行される
else:
    print("result is", result)
finally:
    print("executing finally clause")

# ユーザー定義例外
# https://docs.python.org/3/tutorial/errors.html#user-defined-exceptions
# 典型的にはExceptionもしくはその派生クラスを継承する。
class MyError(Exception):
    pass
    
# ExceptionGroup: 例外をまとめて扱える。通常の例外同様にraise、exceptできる。
# https://docs.python.org/3/tutorial/errors.html#raising-and-handling-multiple-unrelated-exceptions
try:
    excs = [OSError(), SystemError()]
    raise ExceptionGroup('errors', excs)
# except*でグループ内の例外を絞り込んで捕捉することもできる。
# 要素が絞り込まれたExceptionGroupが渡される。
except* OSError as e:
    print(e.exceptions) # (OSError(),)

クラス

# クラス定義
# 参考: https://docs.python.org/3/tutorial/classes.html
class Foo:

    # 静的メソッド: 実体は単なる関数。クラスと関連が深い関数をまとめる目的で使う。
    # 参考: https://docs.python.org/3/library/functions.html#staticmethod
    @staticmethod
    def foo(x, y):
        pass
    
    # クラスメソッド: 第一引数でクラスが渡される。慣習的に変数名はclsとする。
    #               ファクトリメソッドの実装が典型的な利用例。
    # 参考: https://docs.python.org/3/library/functions.html#classmethod
    @classmethod
    def bar (cls, x, y):
        pass
    
    # クラス変数: クラス定義の直下で宣言する。
    x = 1
    
    # コンストラクタ: 第一引数でインスタンスが渡される。慣習的に変数名はselfとする。
    def __init__(self, x, y):
        # インスタンス変数: private修飾子はなく慣習的に先頭に_を付けて区別する。
        self._x = x
    
    # メソッド: 第一引数でインスタンスが渡される。慣習的に変数名はselfとする。
    #          private修飾子はなく慣習的に先頭に_を付けて区別する。
    def baz(self, x, y):
        pass
    
    # プロパティ: @property, @{name}.setter, @{name}.deleterデコレータを設定すると、
    #            属性として参照 (obj.x)、代入 (obj.x = val)、削除 (del obj.x) ができる。
    @property
    def y(self):
        return self._y
    @y.setter
    def y(self, y)
        self._y = y

    # __str__: special methodの1つ。クラスを文字列型にキャストする際に呼び出される。
    # その他のspecial method: __getattr__, __iter__, __add__, ...
    # https://docs.python.org/3/reference/datamodel.html#special-method-names
    def __str__(self):
        return f"<Foo(x={self._x})>"

# インスタンス化
f = Foo(1, 2)
# メソッドの呼び出し
f.baz(3, 4)

# 継承: 多重継承は class X(A, B, C, ...) のように記述する。
# 参考: https://docs.python.org/3/tutorial/classes.html#inheritance
class Bar(Foo):
    
    # メソッドのオーバーライド: 親クラスと同名のメソッドを定義するとオーバーライドできる。
    # 親クラスのメソッドは `super().{メソッド名}` で呼び出せる。
    # 参考: https://docs.python.org/3/library/functions.html#super
    def __str__(self):
        return f"<Bar(x={self._x})>"

# dataclass: いわゆるrecord型を作る機能。__init__や__repr__が自動的に定義される。
# 参考: https://docs.python.org/3/library/dataclasses.html#module-dataclasses
@dataclass
class Baz:
    x: str
    y: int = 0 # デフォルト値の設定

イテレータとジェネレータ

# for文でのループはイテレータという仕組みで動作する。
# for c in 'abc' は以下の処理と同じことをする。
it = iter('abc') # 'abc'.__iter__() を呼び出してイテレータオブジェクトを取得する。
next(it) # it.__next__() を呼び出して次の要素を取得する。要素がない場合はStopIteration例外が発生する。

# yield文を使ってiteratorを作成できる。
def reverse(data):
    for index in range(len(data)-1, -1, -1):
        yield data[index] # この値をnext()で取り出せ、次のnext()呼び出しまで処理が一時中断する。

# Generatorは内包表記で生成することもできる。
g = (i*i for i in range(10))

Discussion