Обычные аргументы против.аргументы ключевого слова
-
07-07-2019 - |
Вопрос
Чем «аргументы ключевых слов» отличаются от обычных аргументов?Невозможно передать все аргументы как name=value
вместо использования позиционного синтаксиса?
Решение
есть две взаимосвязанные концепции, обе называются " аргументы ключевых слов ".
На вызывающей стороне, о чем упоминали другие комментаторы, у вас есть возможность указать аргументы некоторых функций по имени. Вы должны упомянуть их после всех аргументов без имен (позиционные аргументы), и должны быть значения по умолчанию для любых параметров, которые не были упомянуты вообще.
Другая концепция находится на стороне определения функции: вы можете определить функцию, которая принимает параметры по имени, и вам даже не нужно указывать, что это за имена. Это чисто ключевые аргументы, и они не могут быть переданы позиционно. Синтаксис
def my_function(arg1, arg2, **kwargs)
Все аргументы ключевых слов, которые вы передаете в эту функцию, будут помещены в словарь с именем kwargs. Вы можете проверить ключи этого словаря во время выполнения, например:
def my_function(**kwargs):
print str(kwargs)
my_function(a=12, b="abc")
{'a': 12, 'b': 'abc'}
Другие советы
Есть одна последняя языковая особенность, где важно различение. Рассмотрим следующую функцию:
def foo(*positional, **keywords):
print "Positional:", positional
print "Keywords:", keywords
Аргумент * positional
будет хранить все позиционные аргументы, переданные в foo ()
, без ограничения на количество, которое вы можете предоставить.
>>> foo('one', 'two', 'three')
Positional: ('one', 'two', 'three')
Keywords: {}
Аргумент ** keyword
будет хранить любые аргументы ключевого слова:
>>> foo(a='one', b='two', c='three')
Positional: ()
Keywords: {'a': 'one', 'c': 'three', 'b': 'two'}
И, конечно, вы можете использовать оба одновременно:
>>> foo('one','two',c='three',d='four')
Positional: ('one', 'two')
Keywords: {'c': 'three', 'd': 'four'}
Эти функции используются редко, но иногда они очень полезны, и важно знать, какие аргументы являются позиционными или ключевыми словами.
Использование аргументов с ключевыми словами - это то же самое, что и обычные аргументы, за исключением того, что порядок не имеет значения. Например, два вызова функций ниже одинаковы:
def foo(bar, baz):
pass
foo(1, 2)
foo(baz=2, bar=1)
Позиционные аргументы
У них нет ключевых слов перед ними. Порядок важен!
func(1,2,3, "foo")
Аргументы ключевых слов
У них есть ключевые слова спереди. Они могут быть в любом порядке!
func(foo="bar", baz=5, hello=123)
func(baz=5, foo="bar", hello=123)
Вы также должны знать, что если вы используете аргументы по умолчанию и пренебрегаете вставкой ключевых слов, тогда порядок будет иметь значение!
def func(foo=1, baz=2, hello=3): ...
func("bar", 5, 123)
Существует два способа присвоения значений аргументов параметрам функции, оба используются.
<Ол>По позиции. Позиционные аргументы не имеют ключевых слов и назначаются первыми.
По ключевому слову. Аргументы ключевых слов имеют ключевые слова и назначаются вторыми после позиционных аргументов.
Обратите внимание, что у вас есть возможность использовать позиционные аргументы.
Если вы не используете позиционные аргументы, то - да - все, что вы написали, оказывается аргументом с ключевым словом.
Когда вы вызываете функцию, вы принимаете решение использовать позицию, ключевое слово или сочетание. Вы можете сделать все ключевые слова, если хотите. Некоторые из нас не делают этого выбора и используют позиционные аргументы.
Я удивлен, что никто, кажется, не указал, что можно передать словарь параметров аргументов с ключами, которые удовлетворяют формальным параметрам, например.
>>> def func(a='a', b='b', c='c', **kwargs):
... print 'a:%s, b:%s, c:%s' % (a, b, c)
...
>>> func()
a:a, b:b, c:c
>>> func(**{'a' : 'z', 'b':'q', 'c':'v'})
a:z, b:q, c:v
>>>
Используя Python 3 , вы можете иметь как обязательное, так и необязательное ключевое слово аргументы :
Необязательно : (значение по умолчанию определено для 'b')
def func1(a, *, b=42):
...
func1(value_for_a) # b is optional and will default to 42
Обязательный (для 'b' не задано значение по умолчанию):
def func2(a, *, b):
...
func2(value_for_a, b=21) # b is set to 21 by the function call
func2(value_for_a) # ERROR: missing 1 required keyword-only argument: 'b'`
Это может помочь в случаях, когда у вас есть много похожих аргументов рядом друг с другом, особенно когда они одного типа, в этом случае я предпочитаю использовать именованные аргументы или создаю собственный класс, если аргументы принадлежат друг другу.
Я удивлен, что никто не упомянул тот факт, что вы можете смешивать позиционные и ключевые аргументы, чтобы делать такие хитрые вещи, используя * args
и ** kwargs
(< a href = "http://www.saltycrane.com/blog/2008/01/how-to-use-args-and-kwargs-in-python/" rel = "noreferrer"> с этого сайта ): р>
def test_var_kwargs(farg, **kwargs):
print "formal arg:", farg
for key in kwargs:
print "another keyword arg: %s: %s" % (key, kwargs[key])
Это позволяет вам использовать произвольные аргументы ключевых слов, которые могут иметь ключи, которые вы не хотите задавать заранее.
Я искал пример, в котором kwargs по умолчанию использовал аннотацию типа:
def test_var_kwarg(a: str, b: str='B', c: str='', **kwargs) -> str:
return ' '.join([a, b, c, str(kwargs)])
пример:
>>> print(test_var_kwarg('A', c='okay'))
A B okay {}
>>> d = {'f': 'F', 'g': 'G'}
>>> print(test_var_kwarg('a', c='c', b='b', **d))
a b c {'f': 'F', 'g': 'G'}
>>> print(test_var_kwarg('a', 'b', 'c'))
a b c {}