【Python】現役エンジニアがメンティーさんのPythonコードをレビューしてみた
背景
ありがたいことに、最近私のメンターを受講いただけるメンティーさんが増えてきました。
そこで、これから私のメンターをお受けになる方にもぜひ知っていただきたい考え方を記述することにしました。
オブジェクト指向
、命名規則
に関する大切な考え方なので、ぜひ身につけてOUTPUTしてみてください!
コードレビュー
コードレビュー前のコード
# coding: utf-8
# ----------------------------------------------------------------------------------
# テキストを適正な大きさに分割するクラス
# 2023/2/18 制作
#---バージョン---
# Python==3.8.10
# ----------------------------------------------------------------------------------
import os
from transformers import GPT2Tokenizer
class ChatgptTextSplitSave:
def chatgpt_text_split_save():
file_path = "whisper_write_file.txt"
block_size = 1500 # このバーを超えたらテキストファイルを変える。少し余力を持ったものにする
separat_part = '\n'
output_dir = "/Users/XXX/Desktop/ProgramFile/project_file/voice_transcription/chatgpt/data_division_box"
tokenizer = GPT2Tokenizer.from_pretrained('gpt2')
with open(file_path, 'r', encoding='utf-8') as f:
text = f.read()
# 一つ一つを区切ってるパーツによって分解
lines = text.split(separat_part)
# 各ボックスの初期化
blocks = []
block = ''
token_count = 0
for line in lines:
# lineにあるトークンをカウント
t = len(tokenizer.encode(line))
# トークンカウントが0以上(初期ではない)+block_sizeを超えてしまったら新しくリストに追加する
if token_count > 0 and block_size < (token_count + t):
blocks.append(block)
token_count = 0
block = ''
# トークンカウントを追加
token_count += t
# ブロックに区切れた部分を追加する(区切られたもの自体も追加)
block += line + separat_part
# 最後のblock_sizeに達してないものも追加(ここまでのものは全てblocksに追加されてるためない)
if block:
blocks.append(block)
if not os.path.exists(output_dir):
os.makedirs(output_dir)
for i, block in enumerate(blocks):
output_text = os.path.join(output_dir, f'{i+1}_text_block.txt')
with open(output_text, 'w', encoding='utf-8') as output_file:
output_file.write(block)
print(f"{output_text} 保存完了")
解説
-
クラス名、メソッド名について
クラス名class ChatgptTextSplitSave
とメソッド名def chatgpt_text_split_save
両者でchatgpt
とsplit
、save
という文言に被りが出てしまい冗長になっています。
このまま放置すると、とても長い名前のメソッド名をつけてしまうので、被りは取り除きそれぞれで意味を保証するようにしましょう! -
1機能1メソッド
オブジェクト指向プログラミングで重要なのはクラスメソッド設計です。
基本的には1機能1メソッドで設計しましょう!
今回の場合は「文字列の分裂」と「テキストファイルの保存」という決して大きな機能ではないのでメソッドを分けることは必須ではありませんが、基本的にクラス内に1メソッドだとオブジェクト指向の意味があまり感じられないので、今回はわけることとします。
コードレビュー後のコード
# coding: utf-8
# ----------------------------------------------------------------------------------
# テキストを適正な大きさに分割するクラス
# 2023/2/18 制作
#---バージョン---
# Python==3.8.10
# ----------------------------------------------------------------------------------
import os
from transformers import GPT2Tokenizer
class ChatgptText:
def split():
file_path = "whisper_write_file.txt"
block_size = 1500 # このバーを超えたらテキストファイルを変える。少し余力を持ったものにする
separat_part = '\n'
output_dir = "/Users/XXX/Desktop/ProgramFile/project_file/voice_transcription/chatgpt/data_division_box"
tokenizer = GPT2Tokenizer.from_pretrained('gpt2')
with open(file_path, 'r', encoding='utf-8') as f:
text = f.read()
# 一つ一つを区切ってるパーツによって分解
lines = text.split(separat_part)
# 各ボックスの初期化
blocks = []
block = ''
token_count = 0
for line in lines:
# lineにあるトークンをカウント
t = len(tokenizer.encode(line))
# トークンカウントが0以上(初期ではない)+block_sizeを超えてしまったら新しくリストに追加する
if token_count > 0 and block_size < (token_count + t):
blocks.append(block)
token_count = 0
block = ''
# トークンカウントを追加
token_count += t
# ブロックに区切れた部分を追加する(区切られたもの自体も追加)
block += line + separat_part
return block
def save(block):
# 最後のblock_sizeに達してないものも追加(ここまでのものは全てblocksに追加されてるためない)
if block:
blocks.append(block)
if not os.path.exists(output_dir):
os.makedirs(output_dir)
for i, block in enumerate(blocks):
output_text = os.path.join(output_dir, f'{i+1}_text_block.txt')
with open(output_text, 'w', encoding='utf-8') as output_file:
output_file.write(block)
print(f"{output_text} 保存完了")
解説
クラス名をclass ChatgptText
、メソッドを2つdef split
とdef save
としました。これで何に関するクラスで、その中でどんな機能があるのか一目でわかると思います。このように被りなくすることで、名前が冗長になったり、機能を保証することができます。
おわりに
オブジェクト指向に則ったレビューをしてみました。いかがでしたでしょうか?
この考え方は実際に現場で使用されている考え方で、現役のエンジニアの方から教えてもらわないと絶対に知り得ない実践的なコーディング手法です!
あたなも是非、現役フリーランスエンジニアのメンターを受けてみてください!
きっと世界が変わります!
お気軽にご相談ください〜(https://menta.work/plan/13015?ref=mentor_profile)