Open9

Python サプー

KiYuRoKiYuRo

第1章 良いコードの特徴

  • 可読性:読みやすいコード
  • 安全性:不正な動作をしにくいコード
  • 保守性:変更が容易なコード
  • 効率性:消費リソースが少なく処理時間が短いコード
KiYuRoKiYuRo

第2章 まずはコードの見た目を整える

PEP8に従いコードを書く

  • VSCodeの拡張機能blackを使えばよい
KiYuRoKiYuRo

第3章 読みやすいコードに改善するテクニック

コードを分割する

処理のまとまりを関数化する

  • 1度しか呼び出されなくてもよい
  • 関数名を使って処理に名前つけすることで分かりやすくなる
  • 関数が多い場合はモジュールに切り出す
関数化
def read_sales_data():
    """売上データを読み込む"""
    with open("sales1.txt") as f:
        sales1 = f.read()
    with open("sales2.txt") as f:
        sales2 = f.read()
    return sales1, sales2


def calc_total_avg(sales1, sales2):
    """合計と平均を計算する"""
    ...
    return total, avg


def write_total_avg(total, avg):
    """合計と平均を書き出す"""
    with open("sample.txt", "w") as f:
        f.write("...")
        f.write("...")


def main():
    sales1, sales2 = read_sales_data()
    total, avg = calc_total_avg(sales1, sales2)
    write_total_avg(total, avg)


if __name__ == "__main__":
    mian()
モジュール化
import file_reader as fr
import file_writer as fw


def main():
    csv = fr.read_csv()
    txt = fr.read_txt()
    fw.write_csv()


if __name__ == "__main__":
    mian()
KiYuRoKiYuRo

すっきりしたif文を書く

  • 条件式をまとめる
  • 条件式の左側は調査対象の変数
  • 辞書オブジェクトを使う
  • 複雑な条件式は関数にする
  • 早期リターンを使う
条件式をまとめる
# bad
if 1 <= x and x <= 100:
# good
if 1 <= x <= 100:
条件式の左側は調査対象の変数
# bad
if "on_sale" == label:
# good
if label == "on_sale"
辞書オブジェクトを使う
# bad
if x == 1:
    print("睦月")
elif x == 2:
    print("如月")
elif x == 3:
    print("弥生")
# good
jp_month = {1: "睦月", 2: "如月", 3: "弥生"}
print(jp_month[x])
複雑な条件式は関数にする
# bad
if (
    login_cnt >= 100
    and buy_amount > 100
    and buy_cnt >= 10
):
    print("ヘビーユーザー")

# good
def is_heavy_user(login_cnt, buy_amount, buy_cnt):
    return (
        login_cnt >= 100
        and buy_amount > 100
        and buy_cnt >= 10
    )


if is_heavy_user(login_cnt, buy_amount, buy_cnt):
    print("ヘビーユーザー")
早期リターンを使う
# bad
def foo(x, y, z):
    ...
    ...
    if x > 0:
        return x + y + z

# good
def foo(x, y, z):
    if x <= 0:
        return
    ...
    ...
    return x + y + z
KiYuRoKiYuRo

ネストを深くしない

  • 関数に切り出す
  • リスト内包表記や高階関数(map, filter)を使う
  • データ構造を工夫
  • 早期リターン
関数に切り出す
# bad
def process_data(data):
    for item in data:
        if item['status'] == 'active':
            if item['value'] > 10:
                print(f"Processing item: {item}")

# good
def is_active(item):
    return item['status'] == 'active'

def is_high_value(item):
    return item['value'] > 10

def process_data(data):
    for item in data:
        if is_active(item) and is_high_value(item):
            print(f"Processing item: {item}")

リスト内包表記
# bad
squared_numbers = []
for i in range(10):
    if i % 2 == 0:
        squared_numbers.append(i ** 2)

# good
squared_numbers = [i ** 2 for i in range(10) if i % 2 == 0]
データ構造を工夫
# bad
def get_active_user_ids(data):
    active_users = []
    for user in data:
        if user['status'] == 'active':
            active_users.append(user['id'])
    return active_users

# good
def get_active_user_ids(data):
    return {user['id'] for user in data if user['status'] == 'active'}
早期リターン
# bad
def process_item(item):
    if item:
        if item['status'] == 'active':
            print("Processing item")
        else:
            print("Inactive item")
    else:
        print("No item to process")

# good
def process_item(item):
    if not item:
        print("No item to process")
        return
    
    if item['status'] != 'active':
        print("Inactive item")
        return
    
    print("Processing item")
KiYuRoKiYuRo

適切な名前を付ける

  • 命名規則
用途 命名規則
変数名 スネーク型 age = 20user_nam = "佐藤"
定数名 アッパースネーク型 FILE_PATH = "user/path"
クラス名 パスカル型 class UserAccount
関数名・メソッド名 スネーク型 def calculate_total()
ファイル名・モジュール名 スネーク型 user_account.py
  • 具体的な名前を付ける
# bad
def pring_full_name(x, y):
    print(f"{y} {x}")
# good
def pring_full_name(first_name, last_name):
    print(f"{last_name} {first_name}")
  • 対になる対義語を使う
英語 対義語 日本語の意味
start stop 開始・停止
begin end 始まり・終わり
open close 開く・閉じる
increase decrease 増加・減少
add remove 追加・削除
enter exit 入る・出る
up down 上・下
in out 内・外
on off オン・オフ
create destroy 作成・破壊
enable disable 有効化・無効化
include exclude 含む・除外する
show hide 表示・非表示
connect disconnect 接続・切断
push pull 押す・引く
load unload 読み込み・解放
import export インポート・エクスポート
insert delete 挿入・削除
save load 保存・読込
download upload ダウンロード・アップロード
accept reject 受け入れる・拒否する
join split 結合・分割
  • ブール型はTrue/Falseが分かる名前にする
# good
student_flg = True
# bad
is_student = True
パターン 具体例 意味
is + 名詞 is_admin 管理者である
has + 名詞 has_access アクセスを持つ
can + 動詞 can_edit 編集できる
should + 動詞 should_run 実行するべきである
needs + 名詞 needs_update 更新が必要である
supports + 名詞 supports_ssl SSLをサポートする
KiYuRoKiYuRo

分かりやすいコメントを書く

  • コメントの場所と量に注意
  • Docstrignを使う
関数
def calculate_total(price, quantity):
    """
    単価と数量に基づいて合計金額を計算します。

    Args:
        price (float): 1つあたりの価格。
        quantity (int): 購入する個数。

    Returns:
        float: 計算された合計金額。
    """
    return price * quantity
クラス
class User:
    """
    ユーザーを表すクラスです。

    Attributes:
        name (str): ユーザーの名前。
        age (int): ユーザーの年齢。

    Methods:
        greet(): ユーザーの名前を使用して挨拶を出力します。
    """

    def __init__(self, name, age):
        """
        名前と年齢を指定してユーザーを初期化します。

        Args:
            name (str): ユーザーの名前。
            age (int): ユーザーの年齢。
        """
        self.name = name
        self.age = age

    def greet(self):
        """
        ユーザーの名前を使用して挨拶を出力します。
        """
        print(f"こんにちは、私は{self.name}です!")
モジュール
"""
user_module.py

このモジュールは、ユーザー情報の管理に関連する機能を提供します。
ユーザーの作成、データの更新、および統計の計算などの機能を含みます。

Classes:
    User: ユーザーを表すクラス。

Functions:
    calculate_average_age(users): ユーザーの平均年齢を計算します。
"""

class User:
    """ユーザーを表すクラスです。"""
    pass

def calculate_average_age(users):
    """ユーザーの平均年齢を計算します。"""
    pass