Обычные аргументы против ключевых слов - PullRequest
252 голосов
/ 14 сентября 2009

Чем «аргументы ключевых слов» отличаются от обычных аргументов? Разве все аргументы не могут передаваться как name=value вместо использования позиционного синтаксиса?

Ответы [ 9 ]

315 голосов
/ 14 сентября 2009

есть две взаимосвязанные концепции, обе называются «аргументами ключевых слов».

На вызывающей стороне, о которой упоминали другие комментаторы, у вас есть возможность указать аргументы некоторых функций по имени. Вы должны упомянуть их после всех аргументов без имен (позиционные аргументы), и должны быть значения по умолчанию для любых параметров, которые не были упомянуты вообще.

Другая концепция находится на стороне определения функции: вы можете определить функцию, которая принимает параметры по имени - и вам даже не нужно указывать, каковы эти имена. Это чисто ключевые аргументы, и они не могут быть переданы позиционно. Синтаксис

def my_function(arg1, arg2, **kwargs)

Все ключевые аргументы, которые вы передаете в эту функцию, будут помещены в словарь с именем kwargs. Вы можете проверить ключи этого словаря во время выполнения, например:

def my_function(**kwargs):
    print str(kwargs)

my_function(a=12, b="abc")

{'a': 12, 'b': 'abc'}
172 голосов
/ 14 сентября 2009

Есть одна последняя языковая особенность, где важно различение. Рассмотрим следующую функцию:

def foo(*positional, **keywords):
    print "Positional:", positional
    print "Keywords:", keywords

Аргумент *positional будет хранить все позиционные аргументы, переданные foo(), без ограничения на количество, которое вы можете предоставить.

>>> foo('one', 'two', 'three')
Positional: ('one', 'two', 'three')
Keywords: {}

Аргумент **keywords будет хранить любые ключевые аргументы:

>>> 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'}

Эти функции используются редко, но иногда они очень полезны, и важно знать, какие аргументы являются позиционными или ключевыми словами.

94 голосов
/ 14 сентября 2009

Использование аргументов с ключевыми словами - это то же самое, что и обычные аргументы, за исключением того, что порядок не имеет значения. Например, два вызова функций ниже одинаковы:

def foo(bar, baz):
    pass

foo(1, 2)
foo(baz=2, bar=1)
43 голосов
/ 14 сентября 2009

Позиционные аргументы

У них нет ключевых слов перед ними. Порядок важен!

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)
23 голосов
/ 14 сентября 2009

Существует два способа присвоения значений аргументов параметрам функции, оба используются.

  1. По должности. Позиционные аргументы не имеют ключевых слов и назначаются первыми.

  2. По ключевому слову. Аргументы ключевых слов имеют ключевые слова и назначаются вторыми после позиционных аргументов.

Обратите внимание, что у вас есть возможность использовать позиционные аргументы.

Если вы не используете позиционные аргументы, то - да - все, что написанное you окажется ключевым аргументом.

Когда вы вызываете функцию, вы принимаете решение об использовании позиции, ключевого слова или смеси. Вы можете сделать все ключевые слова, если хотите. Некоторые из нас не делают этого выбора и используют позиционные аргументы.

21 голосов
/ 04 мая 2013

Я удивлен, что никто, кажется, не указал, что можно передать словарь параметров аргументов с ключами, которые удовлетворяют формальным параметрам, например.

>>> 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
>>> 
14 голосов
/ 06 апреля 2016

Используя 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'`

Это может помочь в случаях, когда у вас есть много похожих аргументов рядом друг с другом, особенно если они одного типа, в этом случае я предпочитаю использовать именованные аргументы или создаю собственный класс, если аргументы принадлежат друг другу.

11 голосов
/ 14 сентября 2009

Я удивлен, что никто не упомянул тот факт, что вы можете смешивать позиционные аргументы и аргументы ключевых слов, чтобы делать такие хитрые вещи, используя *args и **kwargs ( с этого сайта ):

def test_var_kwargs(farg, **kwargs):
    print "formal arg:", farg
    for key in kwargs:
        print "another keyword arg: %s: %s" % (key, kwargs[key])

Это позволяет вам использовать произвольные аргументы ключевых слов, которые могут иметь ключи, которые вы не хотите задавать заранее.

0 голосов
/ 16 ноября 2018

Я искал пример, который имел 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 {}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...