Одна из больших вещей о Python является его интерактивный интерпретатор. При написании кода, как это:
>>> 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)
Надеюсь, лет Вы понимаете, почему первая форма предпочтительнее. Но вы все же хотите избегать писать все дважды (в аргументах и в теле).
Первый вопрос: Почему Вы пишете код этого типа? Я считаю очень распространенным явлением, что мне нужен класс с кучей атрибутов, который он будет носить, но набор этих атрибутов по существу фиксирован. В самом общем случае эти атрибуты никогда не меняются в течение всего жизненного цикла объекта; в этом случае у 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
«s регулярные классы, вы можете наследовать от них, чтобы дать им специальные поведения. они, к сожалению, неизменны, и если вам это понадобится, вам понадобится другая техника; но вы должны почти всегда использовать для названного кортежа в первую очередь. В противном случае мы можем использовать другую магию; мы можем получить все локальные переменные, которые при запуске функции, включает только аргументы:
>>> 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
В качестве примечания, существует потенциальная проблема с вашим кодом: что делать, если вы хотите фактически присвоить значение «Нет»? Если это имеет значение, вы можете обойти это, создав оценочное значение (например, 'sentinel = object()', затем 'input = sentinel, output = sentinel, ...' в параметрах, затем проверьте «если вход не является достоянием» вместо 'if input'). – abarnert
@abarnert Я вижу. Изменившись на '** kwargs', мне теперь не нужно заботиться о часовом. –
Нет проблем. Как я уже сказал, это всего лишь «потенциальная проблема». Если нет допустимых значений false-y ('None',' 0', '' '', '[]' и т. Д.), Которые вы когда-либо захотите сохранить в своих атрибутах, это совершенно нормально. – abarnert