Нормальні аргументи проти аргументів ключових слів


290

Чим "аргументи ключових слів" відрізняються від звичайних аргументів? Не можна передавати всі аргументи як name=valueзамість використання синтаксису позицій?


6
Ви також можете прочитати PEP 3102 - вони прибирають частину цього матеріалу на Python 3. Див.: Python.org/dev/peps/pep-3102
Бен Хойт

І чи є значення за замовчуванням не має нічого спільного з ним (крім того, чи потрібно вам передавати значення для нього), правда?
mk12


@Ben Hoyt Додав відповідь нижче, що стосується Python 3, необхідні аргументи ключового слова
Крістоф Руссі

Відповіді:


347

Існують два пов'язані поняття, обидва називаються " аргументами ключових слів ".

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

Інша концепція знаходиться на частині визначення функції: ви можете визначити функцію, яка приймає параметри за назвою - і вам навіть не потрібно вказувати, що це за імена. Це чисті ключові аргументи , і їх не можна передавати позиційно. Синтаксис є

def my_function(arg1, arg2, **kwargs)

Усі аргументи ключових слів, які ви передаєте цій функції, будуть розміщені у словнику з назвою kwargs. Ви можете вивчити ключі цього словника під час виконання, як це:

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

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

{'a': 12, 'b': 'abc'}

5
+1 та прийнято: ти єдиний, хто говорив про обидва типи позиційних + аргументів ключових слів, а всі інші думали, що я говорю про перший чи другий (але вони все ще були хорошими повідомленнями). Дякую!
mk12

34
Формулювання незрозуміле: зазвичай ви говорите про аргументи на стороні виклику, а про параметри на стороні, що викликається.
glglgl

3
Чи має бути ім'я параметра kwargsчи я можу перейменувати його на sth. як options( def my_fuction(arg1, arg2, **options))?
Брюс Нд

1
Ім'я може бути будь-яким, хоча kwargsце умова, коли немає більш підходящого імені
Метт Циммерман

Я думаю, що друга пояснена тут концепція технічно називається довільним аргументом ключового слова.
Аншул Дахія

188

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

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

Ці функції використовуються рідко, але періодично вони дуже корисні, і важливо знати, які аргументи є позиційними або ключовими словами.


3
Відмінна відповідь! Просто зауваження, що необхідні позиційні аргументи можуть бути передані раніше, *positionalі **keywordsякщо ми змінимо визначення функції на зразок def foo(arg1, *positional, **keywords):. Ось arg1позиційна і необхідна. Зверніть увагу, що позиція у відповіді означає необов'язкове та змінне число позиційних аргументів.
shaffooo

2
Так, точна відповідь. Ще одна примітка: Якщо ви викликаєте свою функцію, foo(bar=True)ви можете отримати значення, використовуючи такі bar = keywords.pop('bar')ж, як bar = keywords.pop('bar', None). Для значення за замовчуванням використовуйтеbar = keywords.pop('bar', False)
olibre

111

Використання аргументів ключових слів - те саме, що і звичайні аргументи, за винятком порядку. Наприклад, виклики двох функцій нижче однакові:

def foo(bar, baz):
    pass

foo(1, 2)
foo(baz=2, bar=1)

3
Дякую за це Це неймовірно корисно , що я можу і вказати ключове слово аргумент в позиційній ARG, і позиційної арг в якості ключового слова аргумент.
Люк Девіс

47

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

Перед ними немає ключових слів. Порядок важливий!

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)

8
ІМХО, 3-й приклад (аргументи за замовчуванням) не зрозумілий. Я думаю, ви говорите про те, що відбувається, коли один або кілька параметрів оголошують значення за замовчуванням, а виклик використовує позиційне позначення, але постачає менше, ніж кількість оголошених параметрів. Однак у вашому прикладі є 3 оголошених та 3 у виклику, тому значення за замовчуванням взагалі не мають ефекту! Чи ви мали намір опустити 3-й арг. наприклад func("bar", 5)? А потім скажіть, що helloотримує значення за замовчуванням 3.
ToolmakerSteve

25

Існує два способи присвоєння значень аргументу параметрам функції, обидва використовуються.

  1. По позиції. Позиційні аргументи не мають ключових слів і призначаються першими.

  2. За ключовим словом Аргументи ключових слів мають ключові слова та призначаються другими, після позиційних аргументів.

Зауважте, що у вас є можливість використовувати позиційні аргументи.

Якщо ви не використовуєте позиційні аргументи, то - так - все, що ви написали, виявляється аргументом ключового слова.

Під час виклику функції ви приймаєте рішення використовувати позицію, ключове слово або суміш. Ви можете вибрати всі ключові слова, якщо хочете. Деякі з нас не роблять цього вибору і використовують позиційні аргументи.


1
О, я думав, що з параметрів, коли те, що це насправді є аргументами (те, що я передаю). Дякую!
mk12

24

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

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

11
+1 за корисну техніку. Ваша думка була б зрозумілішою, без цього , **kwargs. Це свідчить про те, що навіть простий функціонал із фіксованим числом параметрів може надавати словник. Тобто, це не вимагає нічого фантазійного у визначенні. ТІЛЬКО ви можете додати другий приклад із визначенням ** kwargs у визначенні та показати, як елементи EXTRA у словнику доступні через це.
ToolmakerSteve

1
Я бачив, як це трапляється у вихідному коді різних бібліотек, і був так заплутаний. Дякуємо, що очистили його!
Крейг Лабенц

3
Четвертий офіційний параметр вище - ** kwargs необхідний, якщо ви коли-небудь викликаєте func зі словником, який містить інші клавіші, ніж 'a', 'b' та 'c'.
Едуардо

Для мене print 'a:%s, b:%s, c:%s' % (a, b, c)дає синтаксичну помилку, проте print('a:%s, b:%s, c:%s' % (a, b, c))працює. Щось із версією Python? У будь-якому випадку дякую за це розуміння, до цього часу я використовував більш print('a:{}, b:{}, c:{}'.format(a, b, c))
химерний

17

Використовуючи 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'`

Це може допомогти у випадках, коли у вас є багато подібних аргументів поруч, особливо якщо вони одного типу, в такому випадку я вважаю за краще використовувати аргументи з назвою або створювати власний клас, якщо аргументи належать разом.


3
Потрібно варіант є досить корисним. Він закликає надати аргументи по імені, не надаючи значення за замовчуванням, що часто не має сенсу.
ТНТ

Значення за замовчуванням виглядають чудово і можуть допомогти вам заощадити час, коли ви починаєте, але в довгостроковому періоді значення за замовчуванням можуть бути PITA.
Крістоф Руссі

11

Я здивований, що ніхто не згадав про те, що ви можете змішувати позиційні та ключові аргументи, щоб робити підступні речі, як це, використовуючи *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

Я шукав приклад, у якого 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 {}

0

Просто доповніть / додайте спосіб визначення значення аргументів за замовчуванням, яке не присвоюється ключовим словам при виклику функції:

def func(**keywargs):
if 'my_word' not in keywargs:
    word = 'default_msg'
else:
    word = keywargs['my_word']
return word

зателефонуйте цьому:

print(func())
print(func(my_word='love'))

ви отримаєте:

default_msg
love

читайте більше про *argsі **kwargsв python: https://www.digitalocean.com/community/tutorials/how-to-use-args-and-kwargs-in-python-3

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.