Argumentos normais vs. argumentos de palavras-chave

289

Qual a diferença entre "argumentos de palavras-chave" e argumentos regulares? Todos os argumentos não podem ser passados ​​como em name=valuevez de usar a sintaxe posicional?

mk12
fonte
6
Você também pode querer ler o PEP 3102 - eles estão arrumando algumas dessas coisas em Python 3. Ver: python.org/dev/peps/pep-3102
Ben Hoyt
E se existe ou não um valor padrão não tem nada a ver com ele (exceto se você precisa ou não passar um valor para ele), certo?
Mk12 14/09/09
@ Ben Hoyt Adicionado uma resposta abaixo cobrindo Python 3, exigido argumentos de palavra-chave
Christophe Roussy

Respostas:

346

Existem dois conceitos relacionados, ambos chamados " argumentos de palavras-chave ".

No lado de chamada, que é o que outros comentadores mencionaram, você pode especificar alguns argumentos de função por nome. Você deve mencioná-los depois de todos os argumentos sem nomes ( argumentos posicionais ) e deve haver valores padrão para quaisquer parâmetros que não foram mencionados.

O outro conceito está no lado da definição de função: você pode definir uma função que aceita parâmetros por nome - e nem precisa especificar quais são esses nomes. Estes são argumentos puros de palavras-chave e não podem ser passados ​​posicionalmente. A sintaxe é

def my_function(arg1, arg2, **kwargs)

Qualquer argumento de palavra-chave que você passar para esta função será colocado em um dicionário chamado kwargs. Você pode examinar as chaves deste dicionário em tempo de execução, assim:

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

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

{'a': 12, 'b': 'abc'}
Ian Clelland
fonte
5
+1 e aceito: você é o único que falou sobre os dois tipos de argumentos posicionais + de palavras-chave, todo mundo pensou que eu estava falando sobre o primeiro ou o segundo (mas ainda eram boas postagens). Obrigado!
Mk12 14/09/09
34
A redação não é clara: normalmente você fala de argumentos no lado de chamada, enquanto de parâmetros no lado de chamada.
glglgl
3
O nome do parâmetro precisa ser kwargsou posso renomeá-lo para sth. like options( def my_fuction(arg1, arg2, **options))?
Bruce Sun
1
O nome pode ser qualquer coisa, mas kwargsé a convenção quando não há um nome mais apropriado
Matt Zimmerman
Penso que o segundo conceito explicado aqui é tecnicamente chamado de Argumentos Arbitrários de Palavras-Chave.
Anshul Dahiya 03/12/19
188

Há um último recurso de idioma em que a distinção é importante. Considere a seguinte função:

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

O *positionalargumento armazenará todos os argumentos posicionais passados ​​para foo(), sem limite para quantos você pode fornecer.

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

O **keywordsargumento armazenará qualquer argumento de palavra-chave:

>>> foo(a='one', b='two', c='three')
Positional: ()
Keywords: {'a': 'one', 'c': 'three', 'b': 'two'}

E é claro, você pode usar os dois ao mesmo tempo:

>>> foo('one','two',c='three',d='four')
Positional: ('one', 'two')
Keywords: {'c': 'three', 'd': 'four'}

Esses recursos raramente são usados, mas ocasionalmente são muito úteis e é importante saber quais argumentos são posicionais ou palavras-chave.

muito php
fonte
3
Excelente resposta! Apenas uma observação de que argumentos posicionais necessários podem ser passados ​​antes *positionale **keywordsse mudarmos a definição de função como def foo(arg1, *positional, **keywords):. Aqui arg1é posicional e obrigatório. Observe que a resposta posicional significa número opcional e variável de argumentos posicionais.
shaffooo
2
Sim, boa resposta. Outra observação: se você chamar sua função, foo(bar=True)poderá obter os valores usando o bar = keywords.pop('bar')mesmo que bar = keywords.pop('bar', None). Para o valor padrão, usebar = keywords.pop('bar', False)
olibre
111

Usar argumentos de palavra-chave é a mesma coisa que argumentos normais, exceto que a ordem não importa. Por exemplo, as duas chamadas de funções abaixo são as mesmas:

def foo(bar, baz):
    pass

foo(1, 2)
foo(baz=2, bar=1)
Eli Gray
fonte
3
Obrigado por isso. É incrivelmente útil que eu posso tanto especificar uma palavra-chave arg como arg posicional, e um arg posicional como palavra-chave arg.
Luke Davis
47

Argumentos posicionais

Eles não têm palavras-chave antes deles. A ordem é importante!

func(1,2,3, "foo")

Argumentos de palavras-chave

Eles têm palavras-chave na frente. Eles podem estar em qualquer ordem!

func(foo="bar", baz=5, hello=123)

func(baz=5, foo="bar", hello=123)

Você também deve saber que, se você usar argumentos padrão e negligenciar a inserção das palavras-chave, o pedido será importante!

def func(foo=1, baz=2, hello=3): ...
func("bar", 5, 123)
Desconhecido
fonte
8
IMHO, o terceiro exemplo (argumentos padrão) não é claro. Acho que você está falando sobre o que acontece quando um ou mais parâmetros declaram valores padrão e a chamada usa notação posicional, mas fornece MENOS que o número de parâmetros declarados. No entanto, seu exemplo tem 3 declarados e 3 na chamada, portanto os valores padrão não têm efeito algum! Você pretendia omitir o terceiro argumento. por exemplo func("bar", 5)? E então diga que helloobtém seu valor padrão de 3.
usar o seguinte
25

Existem duas maneiras de atribuir valores de argumento aos parâmetros de função, ambos são usados.

  1. Por posição. Argumentos posicionais não possuem palavras-chave e são atribuídos primeiro.

  2. Por palavra-chave. Os argumentos de palavra-chave possuem palavras-chave e são atribuídos em segundo lugar, após argumentos posicionais.

Observe que você tem a opção de usar argumentos posicionais.

Se você não usar argumentos posicionais, tudo o que você escreveu será um argumento de palavra-chave.

Quando você chamar uma função de tomar uma decisão para a posição de utilização ou palavra-chave ou uma mistura. Você pode optar por fazer todas as palavras-chave, se quiser. Alguns de nós não fazem essa escolha e usam argumentos posicionais.

S.Lott
fonte
1
Ohh, eu estava pensando nos parâmetros, quando o que realmente são os argumentos (o que eu passo). Obrigado!
Mk12 14/09/09
24

Estou surpreso que ninguém parece ter apontado que alguém pode passar um dicionário de parâmetros de argumento com chave, que satisfazem os parâmetros formais, assim.

>>> 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
>>> 
Sherman
fonte
11
+1 para uma técnica útil. Seu ponto de vista seria mais claro, sem , **kwargs. Isso demonstraria que mesmo um simples func def, com um número fixo de parâmetros, pode receber um dicionário. Ou seja, não requer nada sofisticado na definição. ENTÃO, você pode adicionar um segundo exemplo, WITH ** kwargs na definição, e mostrar como os itens EXTRA no dicionário estão disponíveis por meio disso.
Página
1
Eu já vi isso acontecer no código fonte de várias bibliotecas e fiquei muito confuso. Obrigado por esclarecê-lo!
Craig Labenz 3/02
3
O quarto parâmetro formal acima - ** kwargs é necessário se você chamar func com um dicionário que contenha chaves diferentes de 'a', 'b' e 'c'.
Eduardo
Para mim print 'a:%s, b:%s, c:%s' % (a, b, c)dá erro de sintaxe, no entanto print('a:%s, b:%s, c:%s' % (a, b, c))funciona. Algo com a versão Python? De qualquer forma, obrigado por essa visão, até agora eu estava usando o mais desajeitadoprint('a:{}, b:{}, c:{}'.format(a, b, c))
Axel Bregnsbo
17

Usando Python 3 você pode ter ambos palavra-chave necessários e não necessários argumentos :


Opcional : (valor padrão definido para o parâmetro 'b')

def func1(a, *, b=42):
    ...
func1(value_for_a) # b is optional and will default to 42

Necessário (nenhum valor padrão definido para o parâmetro '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'`

Isso pode ajudar nos casos em que você tem muitos argumentos semelhantes, especialmente se forem do mesmo tipo; nesse caso, prefiro usar argumentos nomeados ou crio uma classe personalizada se os argumentos pertencerem.

Christophe Roussy
fonte
3
A variante necessária é bastante útil. Ele pede que os argumentos sejam nomeados sem fornecer padrões, o que geralmente não faz sentido.
TNT
Os valores padrão parecem bons e podem ajudar a economizar tempo quando você inicia, mas, a longo prazo, os valores padrão podem ser uma PITA.
Christophe Roussy
11

Estou surpreso que ninguém tenha mencionado o fato de que você pode misturar argumentos posicionais e de palavras-chave para fazer coisas sorrateiras como essa usando *argse **kwargs( deste site ):

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

Isso permite que você use argumentos arbitrários de palavras-chave que podem ter chaves que você não deseja definir antecipadamente.

Gabriel Hurley
fonte
0

Eu estava procurando por um exemplo que tivesse kwargs padrão usando a anotação de tipo:

def test_var_kwarg(a: str, b: str='B', c: str='', **kwargs) -> str:
     return ' '.join([a, b, c, str(kwargs)])

exemplo:

>>> 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 {}
jmunsch
fonte
0

Basta suplementar / adicionar uma maneira de definir o valor padrão dos argumentos que não são atribuídos em palavras-chave ao chamar a função:

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

chame isso por:

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

você terá:

default_msg
love

leia mais sobre *argse **kwargsem python: https://www.digitalocean.com/community/tutorials/how-to-use-args-and-kwargs-in-python-3

sonictl
fonte