Open9
Python サプー
Python サプー読書メモ
第1章 良いコードの特徴
- 可読性:読みやすいコード
- 安全性:不正な動作をしにくいコード
- 保守性:変更が容易なコード
- 効率性:消費リソースが少なく処理時間が短いコード
第2章 まずはコードの見た目を整える
PEP8に従いコードを書く
- VSCodeの拡張機能blackを使えばよい
第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()
すっきりした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
ネストを深くしない
- 関数に切り出す
- リスト内包表記や高階関数(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")
適切な名前を付ける
- 命名規則
用途 | 命名規則 | 例 |
---|---|---|
変数名 | スネーク型 |
age = 20 ,user_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をサポートする |
分かりやすいコメントを書く
- コメントの場所と量に注意
- 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