Хотя большинство ответов говорят, что, например,
def f(**kwargs):
foo = kwargs.pop('foo')
bar = kwargs.pop('bar')
...etc...
такой же как"
def f(foo=None, bar=None, **kwargs):
...etc...
это неправда. В последнем случае f
может быть вызвано как f(23, 42)
, тогда как в первом случае принимаются только именованные аргументы - никаких позиционных вызовов. Часто вы хотите позволить вызывающей стороне максимальную гибкость, и поэтому вторая форма, как утверждают большинство ответов, предпочтительнее, но это не всегда так. Когда вы принимаете много необязательных параметров, из которых обычно передаются только несколько, может оказаться отличной идеей (избегая аварий и нечитаемого кода на ваших сайтах вызовов!) Принудительно использовать именованные аргументы - threading.Thread
пример. Первая форма - это то, как вы реализуете это в Python 2.
Эта идиома настолько важна, что в Python 3 теперь он имеет специальный поддерживающий синтаксис: каждый аргумент после единственного *
в def
подписи является ключевым словом, то есть не может быть передан как позиционный аргумент, а только как именованный. Таким образом, в Python 3 вы можете написать код выше:
def f(*, foo=None, bar=None, **kwargs):
...etc...
Действительно, в Python 3 вы даже можете иметь аргументы только для ключевых слов, которые не являются необязательными ( аргументы без значения по умолчанию).
Однако в Python 2 впереди долгие годы продуктивной жизни, поэтому лучше не забывать методы и идиомы, которые позволяют реализовывать в Python 2 важные идеи проектирования, которые непосредственно поддерживаются в языке Python 3!