@ Jan-PhilipGehrckeが指摘しているpythonic
ように、定量化するのは難しい場合があります。私にとってそれは意味します:
- 読みやすい
- メンテナンスが簡単
- 単純な方が複雑な方が良い
- etcetera、etceteraなど(インタプリタ
Zen of Python
に入力して取得する完全なリストについては、を参照してください)import this
したがって、最もpythonicなソリューションは、サポートされている初期化子ごとに何をする必要があるか、およびそれらの数に依存します。ほんの一握りで、それぞれが数行のコードで処理できる場合は、andを使用isinstance
し__init__
ます。
class MyClass(object):
def __init__(self, initializer):
"""
initialize internal data structures with 'initializer'
"""
if isinstance(initializer, dict):
for k, v in itit_dict.items():
# do something with k & v
setattr(self, k, v)
elif isinstance(initializer, (list, tuple)):
for item in initializer:
setattr(self, item, None)
一方、可能な初期化子が多数ある場合、またはそれらのいずれかで処理するために多くのコードが必要な場合は、classmethod
可能なinitタイプごとに1つのコンストラクターが必要になります。最も一般的な使用法は、次の__init__
とおりです。
class MyClass(object):
def __init__(self, init_dict={}):
"""
initialize internal data structures with 'init_dict'
"""
for k, v in itit_dict.items():
# do something with k & v
setattr(self, k, v)
@classmethod
def from_sequence(cls, init_list):
"""
initialize internal data structures with 'init_list'
"""
result = cls()
for item in init_list:
setattr(result, item, None)
return result
これにより、可能な各コンストラクターがシンプルでクリーン、そして理解しやすくなります。
補足として:デフォルトとして可変オブジェクトを使用することは(上記のように__init__
)注意して行う必要があります。その理由は、デフォルトは1回だけ評価され、その後のすべての呼び出しで結果が何であれ使用されるためです。これは、関数でそのオブジェクトを変更する場合にのみ問題になります。これらの変更は、後続のすべての呼び出しで確認されるためです。また、探している動作ではない可能性のあるキャッシュを作成する場合を除きます。私は変更していないので、これは私の例では問題ではありません。init_dict
それを繰り返すだけです(これは、呼び出し元が空であるために置き換えていない場合は何もしません)。