Pythonを扱っていて気づいたいくつかの点
クラス内外の変数を区別する必要がある
Pythonではクラス変数を宣言する際にselfオブジェクトを用いる方法が一般的ですが、この方法は正確にはインスタンスで使用する内部変数を使用する方法です。該当クラス変数へのアクセスにはインスタンス生成が必須となるため、すべてのオブジェクトで同一値を保証する必要がある場合や、C#やJavaなどの他の言語のstaticキーワードと似た効果を意図したい場合などには、__init__()関数の外部に宣言する必要があります。
class Person:
''' 以下のように宣言できます。
'''
type = "person"
def __init__(self):
self.name = name
self.age = age
# ...
この変数はすべてのインスタンスで同一の値として提供されます。このとき、オブジェクトへのアクセスはオブジェクト内部でさえもクラス名.変数名のように行われることに注意する必要があります。例えば上記のPeopleクラス内でtype変数値をanother_people_typeのように修正する必要がある場合、People.type = another_people_typeでアクセスできます。
Pythonでもgetter、setterを使用できる
C#、Javaなどの言語のようにgetterとsetterと呼ばれるものではありませんが、クラス内部変数と公開用プロパティを接続するという概念は同じです。クラス内部変数を隠蔽化する用途にも有用ですが、それよりもある変数の値が変更される時のロジックを接続できるという点でより便利なので、知っておく必要があります。
class Example:
def __init__(self):
self._variable = None
@property
def variable(self):
return self._variable
@variable.setter(self, value):
self._variable = value
他の言語でgetterだけを宣言した時に読み取り専用として動作するのと同様に、@propertyだけを宣言すると、そのプロパティで変数を修正しようとした時にエラーが発生するので注意が必要です。
モジュール名にクラス個数を反映できる
基本的に関数はコードの分類単位、クラスは関数と変数の分類単位、モジュールはクラスの分類単位です。この観点を概念的によりよく実装する方法の一つは、1つのモジュールに複数のクラスがある場合、モジュール名を単に複数形で明記することです。
myproject/
│
├── app/
│ ├── users/
│ │ ├── models.py
│ │ ├── views.py
│ │ └── controllers.py
│ ├── products/
│ └── orders/
│
└── main.py
このときmodels.pyには、実際のプロジェクトの例ではないため具体的ではありませんが、例えばUserModel()またはProductModelのように名前+種別形式のクラス名を使用できます。こうした構造は、1モジュールに1クラスがある場合に比べて、クラスに対する分類が明確になり、モジュールを使用する際にfrom models import UserModel as UMのように自然な表現を使用できる利点があります。
比喩を使うよりも直感的な名前の方が良い
比喩を用いる場合、その直感性は大概半分だけです。その半分のおかげでコードを初めて見た時に動作過程が簡潔になり、読むのがより楽しくなりますが、残り半分のおかげでコードが書かれた意図が曖昧になるという欠点があるため、可能な限り避けるのが正しいと思います。
def main():
''' 宝石細工職人をテーマにするとこんな感じ
'''
self.mining()
self.cutting()
self.crafting()
self.selling()
def main()
''' ファインダイニングシェフをテーマにするとこんな感じ
'''
self.washing()
self.cutting()
self.cooking()
self.plating()
コードの全体的な動作を上記のように宝石販売をテーマに採掘-切削-細工-販売過程に喩えたり、料理人が料理をする過程を模倣して洗浄-下処理-調理-プレーティングの構造で表現するなど、上記の例以外にもいくつか比喩法を使ってコードを構造化してみましたが、比喩法を経た関数名がコードの役割を明確に反映しないという問題がありました。
このため意味をよく理解するまでの過程に一段階追加され、他人または未来の自分がコードを読む時に意味を直感的に理解するのに不必要な困難が発生し、時には主客転倒してクラスと関数が持っているテーマを意識しながら書く場合もありました。
代わりに、面白さは少なくてもクラスの役割を正統的に書く方がすっきりしました。
def main():
''' ただの一般的な場合
'''
download_data()
basic_process()
save_results()
四字熟語や有名な逸話を引用するなど、比喩において補助観念が持つ直感性が圧倒的な場合はまた良いかもしれませんが、それ以外のほとんどの場合には、上記のようにコードの動作自体を簡潔に描写するように書く方がより実用的でした。