Python の優れた点の 1 つは、その対話型インタープリターです。次のようなコードを書くと:
>>> def assign(self, input=None, output=None, param=None, p1=None, p2=None):
... pass
...
関数の使用方法を理解するのは非常に簡単です。
>>> help(assign)
Python Library Documentation: function assign in module __main__
assign(self, input=None, output=None, param=None, p1=None, p2=None)
比較すると:
>>> def assign2(self, **kwargs):
... pass
...
与えます:
>>> help(assign2)
Python Library Documentation: function assign2 in module __main__
assign2(self, **kwargs)
最初の形式が望ましい理由を理解していただければ幸いです。ただし、すべてを 2 回 (引数と本文で) 記述することは避けたいと考えています。
最初の質問は、なぜこのような性質のコードを書いているのですか? 持ち運ぶ属性のヒープを持つクラスが必要になるのは非常に一般的なケースですが、これらの属性のセットは基本的に固定されています。最も一般的なケースでは、これらの属性はオブジェクトの存続期間中は変更されません。その場合、python にはまさにそのためのヘルパーが組み込まれています。
>>> import collections
>>> Assignment = collections.namedtuple('Assignment', 'input output param p1 p2')
>>> assign = Assignment(None, None, None, None, None)._replace
>>> assign(p1=10)
Assignment(input=None, output=None, param=None, p1=10, p2=None)
>>> help(Assignment)
Python Library Documentation: class Assignment in module __main__
class Assignment(__builtin__.tuple)
| Assignment(input, output, param, p1, p2)
|
... SNIP
namedtuple
は通常のクラスであり、それらを継承して特別な動作を与えることができます。残念ながら、それらは不変であり、それが必要になった場合は、別の手法が必要になります。ただし、ほとんどの場合、最初に名前付きタプルに到達する必要があります。それ以外の場合は、他の魔法を利用できます。関数の開始時に引数のみを含むすべてのローカル変数を取得できます。
>>> class Assignable(object):
... def assign(self, input=None, output=None, param=None, p1=None, p2=None):
... _kwargs = vars()
... _kwargs.pop('self')
... vars(self).update((attr, value) for attr, value in _kwargs.items() if value is not None)
...
>>> a = Assignable()
>>> vars(a)
{}
>>> a.assign(p1=6)
>>> vars(a)
{'p1': 6}
>>> a.p1
6
そしてhelp()
テキストはまだ非常に役に立ちます!
>>> help(a.assign)
Python Library Documentation: method assign in module __main__
assign(self, input=None, output=None, param=None, p1=None, p2=None) method of __main__.Assignable instance