解答例
課題1
personとあり、この規則に即していない。
class宣言時は、すぐ近くにclassが書いてあるからいいが、そのクラスを使うプログラマーは、ソースコードを読むか、IDEの機能で判断しなけらばならない。しかし、ルールに則ってCapWords(キャメルケース)で書いていれば、名前からクラスであることがわかる。
# クラスの名前はCapWords(=キャメルケース)を使う。
#class person:
class Person:
def __init__(self, name: str, old: int):
self._name:str = name
self._old:int = old
total_count: int = 0
def count(num: int) -> int:
total_count += num
return total_count
# クラスの名前はCapWords(=キャメルケース)を使う。
# 元の場合、関数と見分けがつかない。
# person1: Person = person(“kj”, 30)
person1: Person = Person(“kj”, 30)
count1: int = count(1)
課題2
関数の名前は小文字のみにすべきです。また、読みやすくするために、必要に応じて単語をアンダースコアで区切るべきです。
変数の名前についても、関数と同じ規約に従います。
関数名や変数名に大文字があったりし、この規約に則していない。
課題1にあったように、関数なのかクラスなのかわからなくなる。また、この課題では、規約に則っている変数と則っていない変数がごちゃ混ぜになっていて、統一感がなく読みにくい。また、何か意図があるのではと勘ぐってしまい、余計な時間がかかる。
class Point:
pass
# 本当はちゃんと実装
# 関数の名前は小文字のみにする。
# 読みやすくするために必要に応じてアンダースコアで区切る。
# 要するにスネークケース
# def ComputeDistance(point0: Point, point1: Point) -> float:
def compute_distance(point0: Point, point1: Point) -> float:
# … 計算
return distance
point0: Point = Point()
# 変数名もスネークケースで
# Point1: Point = Point()
point1:Point = Point()
# ルール守ってたり守ってなかったりバラバラだと統一感がなくて読みにくい
# ルールを守っていないと、何か意図があるのかと勘ぐってしまう
# Distance = ComputeShortestDistance(point0, Point1)
distance: float = compute_distance(point0, point1)
課題3
関数の命名規約を使ってください。つまり、名前は小文字のみにして、読みやすくするために必要に応じて単語をアンダースコアで区切ります。
公開されていないメソッドやインスタンス変数にだけ、アンダースコアを先頭に付けてください。
サブクラスと名前が衝突した場合は、Python のマングリング機構を呼び出すためにアンダースコアを先頭に二つ付けてください。
メソッド名やインスタンス変数名は問題なさそう。
しかし、公開に関する規約に則していない。面積を計算する_calc_area()は外部から呼びたいメソッドのはずだが、アンダースコアが先頭に来ている。また、idにアンダースコアがついておらず、公開していると判断できるため、外部から値を書き換えても良いように見えてしまうが、idは簡単に変更していい情報ではない。
また、今回は使っていないが、サブクラスからインスタンス変数を見えなくする(いわゆるprivate)にはアンダースコアを二つつけるとできる。ただ、これは完全にprivateになったわけじゃなくて、マングリングにより、クラス名が先頭についているだけで、アクセスはできます。
class Widget:
def __init__(self, name: str, x: int, y: int, width: int, height: int):
# idは非公開情報
# self.id: UUID = uuid4()
self._id: UUID = uuid4()
self.name: str = name
self.x: int = x
self.y: int = y
self.width: int = width
self.height: int = height
# 公開メソッド
# def _calc_area(self) -> float:
def calc_area(self) -> float:
return width * height
# idを読み込みのみ可にする
@property
def id(self) -> UUID:
return self._id
widget: Widget = Widget(“Sample Dialogue”, 0, 0, 100, 50)
area: float = widget.calc_area()
#idに書き込もうとするとerror
#widget.id = uuid4()
課題4
定数は通常モジュールレベルで定義します。全ての定数は大文字で書き、単語をアンダースコアで区切ります。例として MAX_OVERFLOW や TOTAL があります。
positionの範囲を指定する定数を設けているが、定数の書き方に則していない。そもそも区切りがなく読みにくいものや、変数名のルールに従っていて、書き換えてもよさそうに見えるものがある。(python は言語仕様上、定数にできない)
MAX_POSITION_X: int = 1000
MAX_POSITION_Y: int = 1000
MIN_POSITION_X: int = 0
MIN_POSITION_Y: int = 0
# 区切りがなくて読みにくい
# maxpositiony: int = 1000
# 書き方にルールがなくて読みにくい
# MINPositionX: int = 0
# スネークケースは変数名のルールなので、変数に見えてしまう
# min_position_y: int = 0
class Widget:
def __init__(self, name: str, x: int, y: int, width: int, height: int):
self.id: UUID = uuid.uuid4()
self.name: str = name
self.x: int = min(max(x, MINPositionX), MAX_POSITION_X)
self.y: int = min(max(y, min_position_y), maxpositiony)
self.width: int = width
self.height: int = height
def _calc_area(self) -> float:
return width * height
終わりに
リーダブルコード「2.6 名前のフォーマットで情報を伝える」を元に、プログラミング言語ごとにある命名規則について触れてみた。
課題に関しては、やってみるとなかなか難しかった。間違っているとか、こう書いた方がいいのでは?などあったら是非コメントして欲しい。