Por que argumentos não padrão não podem seguir argumentos padrão?


137

Por que esse trecho de código gera um SyntaxError?

  >>> def fun1(a="who is you", b="True", x, y):
...     print a,b,x,y
... 
  File "<stdin>", line 1
SyntaxError: non-default argument follows default argument

Enquanto o seguinte trecho de código é executado sem erros visíveis:

>>> def fun1(x, y, a="who is you", b="True"):
...     print a,b,x,y
... 

em python, é assim que a estrutura é quando você define uma função def myfunction(position_arguments, *arguments, **keywords):`....`
abhishekgarg

Respostas:


172

Todos os parâmetros necessários devem ser colocados antes de qualquer argumento padrão. Simplesmente porque eles são obrigatórios, enquanto argumentos padrão não são. Sintaticamente, seria impossível para o intérprete decidir quais valores correspondem a quais argumentos se modos mistos fossem permitidos. A SyntaxErroré gerado se os argumentos não forem fornecidos na ordem correta:

Vamos dar uma olhada nos argumentos das palavras-chave, usando sua função.

def fun1(a="who is you", b="True", x, y):
...     print a,b,x,y

Suponha que seja permitido declarar a função como acima. Em seguida, com as declarações acima, podemos fazer as seguintes chamadas de argumento de posição ou de palavra-chave (regulares):

func1("ok a", "ok b", 1)  # Is 1 assigned to x or ?
func1(1)                  # Is 1 assigned to a or ?
func1(1, 2)               # ?

Como você sugerirá a atribuição de variáveis ​​na chamada de função, como os argumentos padrão serão usados ​​junto com os argumentos das palavras-chave.

>>> def fun1(x, y, a="who is you", b="True"):
...     print a,b,x,y
... 

Referência O'Reilly - Core-Python
Onde, como esta função, utilize os argumentos padrão sintaticamente corretos para as chamadas de função acima. A chamada de argumentos de palavras-chave se mostra útil por poder fornecer argumentos posicionais fora de ordem, mas, juntamente com argumentos padrão, eles também podem ser usados ​​para "pular" argumentos ausentes.


4
<q> Sintaticamente, seria impossível para o intérprete decidir quais valores correspondem a quais argumentos se modos mistos fossem permitidos. </q> Ruby permite argumentos não padrão seguindo os padrões. <q> Como você sugerirá a atribuição de variáveis ​​na chamada de função </q> Basta usar func1(x=1, y=2).
weakish

Oi @weakish, obrigado pelo comentário, Python tem uma boa maneira de conseguir isso, por favor, vá procurar args * e ** kwargs
Rahul Gautam

Oi @Rahul Gautam Estou confuso. Eu pensei **kwargsque não pode fazer def fun1(a="who is you", b="True", x, y)ou trabalho semelhante. Se você usa def f(**kwargs), precisa lidar com valores padrão no corpo?
weakish

@ frágil def fun1(a="who is you", b="True", x, y)a mesma coisa pode ser alcançada com um estilo diferente. se def fun1 (** kwrgs) `então fun1({'a': 'who is you', 'b': True})não precisa passar x e y.
Rahul Gautam

2
Por que você escreve "Sintaticamente, seria impossível para o intérprete decidir quais valores correspondiam a quais argumentos se modos mistos eram permitidos"? Penso que o algoritmo do PEP 3102 poderia funcionar exatamente da mesma forma, mesmo def foo(x=None, y)que fosse permitido. Ainda estou curioso para saber por que isso não é permitido pelo Python. Existe uma verdadeira razão fundamental ou é apenas "não permitimos porque não permitimos".
Jeroen Demeyer

15
SyntaxError: non-default argument follows default argument

Se você permitir isso, os argumentos padrão serão inúteis, porque você nunca poderá usar seus valores padrão, uma vez que os argumentos não padrão vêm depois .

No Python 3, no entanto, você pode fazer o seguinte:

def fun1(a="who is you", b="True", *, x, y):
    pass

que cria apenas uma palavra x- ychave para que você possa fazer isso:

fun1(x=2, y=2)

Isso funciona porque não há mais ambiguidade. Observe que você ainda não pode fazer fun1(2, 2)(isso definiria os argumentos padrão).


Os argumentos somente de palavras-chave são um recurso interessante do Python 3. Pena que o patch para suportá-los para o Python 2.6 e 2.7 foi deixado para expirar .
21415 Nick Chammas

10

Deixe-me esclarecer dois pontos aqui:

  • primeiro, o argumento não padrão não deve seguir o argumento padrão, significa que você não pode definir (a = b, c) na função a ordem de definição do parâmetro na função é:
    • parâmetro posicional ou parâmetro não padrão, isto é (a, b, c)
    • parâmetro de palavra-chave ou parâmetro padrão, ou seja, (a = "b", r = "j")
    • parâmetro apenas de palavra-chave, ou seja (* args)
    • parâmetro var-keyword, ou seja, (** kwargs)

def example(a, b, c=None, r="w" , d=[], *ae, **ab):

(a, b) são parâmetros posicionais

(c = nenhum) é parâmetro opcional

(r = "w") é o parâmetro da palavra-chave

(d = []) é o parâmetro da lista

(* ae) é apenas palavra-chave

(** ab) é o parâmetro var-keyword

  • Agora coisa secundária é se eu tentar algo parecido com isto: def example(a, b, c=a,d=b):

argumento não é definido quando os valores padrão são salvos, o Python calcula e salva os valores padrão quando você define a função

c e d não estão definidos, não existem, quando isso acontece (existe apenas quando a função é executada)

"a, a = b" não é permitido no parâmetro


0

Os argumentos necessários (aqueles sem padrões) devem estar no início para permitir que o código do cliente forneça apenas dois. Se os argumentos opcionais estivessem no início, seria confuso:

fun1("who is who", 3, "jack")

O que isso faria no seu primeiro exemplo? No último, x é "quem é quem", y é 3 e a = "valete".

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.