¿Por qué los argumentos no predeterminados no pueden seguir a los argumentos predeterminados?

138

¿Por qué este fragmento de código arroja un 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

Mientras el siguiente fragmento de código se ejecuta sin errores visibles:

>>> def fun1(x, y, a="who is you", b="True"):
...     print a,b,x,y
... 
Dotslash
fuente
en Python, así es como es la estructura cuando se define una función def myfunction(position_arguments, *arguments, **keywords):`....`
abhishekgarg

Respuestas:

172

Todos los parámetros requeridos deben colocarse antes de cualquier argumento predeterminado. Simplemente porque son obligatorios, mientras que los argumentos predeterminados no lo son. Sintácticamente, sería imposible para el intérprete decidir qué valores coinciden con qué argumentos si se permitieran modos mixtos. Se SyntaxErrorgenera A si los argumentos no se dan en el orden correcto:

Echemos un vistazo a los argumentos de palabras clave, utilizando su función.

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

Supongamos que está permitido declarar la función como se indica arriba. Luego, con las declaraciones anteriores, podemos hacer las siguientes llamadas de argumentos posicionales o de palabras clave:

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

Cómo sugerirá la asignación de variables en la llamada a la función, cómo se utilizarán los argumentos predeterminados junto con los argumentos de palabras clave.

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

Referencia O'Reilly - Core-Python
Donde, como esta función, utiliza los argumentos predeterminados sintácticamente correctos para las llamadas a funciones anteriores. La invocación de argumentos de palabras clave resulta útil para poder proporcionar argumentos posicionales fuera de orden, pero, junto con los argumentos predeterminados, también se pueden usar para "omitir" los argumentos faltantes.

Rahul Gautam
fuente
44
<q> Sintácticamente, sería imposible para el intérprete decidir qué valores coinciden con qué argumentos si se permitieran modos mixtos. </q> Ruby permite argumentos no predeterminados después de los predeterminados. <q> Cómo sugerirás la asignación de variables en la llamada a la función </q> Solo usa func1(x=1, y=2).
débil
Hola @weakish, gracias por el comentario, Python tiene una buena manera de lograr esto. Busque * args y ** kwargs
Rahul Gautam
Hola @Rahul Gautam, estoy confundido. Pensé **kwargsque no se puede hacer def fun1(a="who is you", b="True", x, y)o trabajo similar. Si usa def f(**kwargs), ¿necesita manejar los valores predeterminados en el cuerpo?
débil
@weakish def fun1(a="who is you", b="True", x, y)lo mismo se logra con un estilo diferente. if def fun1 (** kwrgs) `entonces llame fun1({'a': 'who is you', 'b': True})sin necesidad de pasar x e y.
Rahul Gautam
2
¿Por qué escribe "sintácticamente, sería imposible para el intérprete decidir qué valores coinciden con qué argumentos si se permitieran modos mixtos"? Creo que el algoritmo en PEP 3102 podría funcionar exactamente igual, incluso si def foo(x=None, y)se permitiera. Así que todavía tengo curiosidad por qué Python no permite esto. ¿Existe una razón fundamental real o es simplemente "no lo permitimos porque no lo permitimos"?
Jeroen Demeyer
15
SyntaxError: non-default argument follows default argument

Si permitiera esto, los argumentos predeterminados se volverían inútiles porque nunca podría usar sus valores predeterminados, ya que los argumentos no predeterminados vienen después .

Sin embargo, en Python 3, puede hacer lo siguiente:

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

qué marca xy ypalabra clave solo para que pueda hacer esto:

fun1(x=2, y=2)

Esto funciona porque ya no hay ambigüedad. Tenga en cuenta que aún no puede hacerlo fun1(2, 2)(eso establecería los argumentos predeterminados).

jamylak
fuente
Los argumentos de solo palabras clave son una característica ordenada de Python 3. Lástima que el parche para hacerlos retroceder a Python 2.6 y 2.7 acaba de expirar .
Nick Chammas
10

Déjame aclarar dos puntos aquí:

  • En primer lugar, el argumento no predeterminado no debe seguir el argumento predeterminado, significa que no puede definir (a = b, c) en función, el orden de definición de parámetros en función es:
    • parámetro posicional o parámetro no predeterminado, es decir (a, b, c)
    • parámetro de palabra clave o parámetro predeterminado, es decir (a = "b", r = "j")
    • parámetro de solo palabra clave, es decir (* args)
    • parámetro de palabra clave var es decir (** kwargs)

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

(a, b) son parámetros posicionales

(c = ninguno) es un parámetro opcional

(r = "w") es el parámetro de palabra clave

(d = []) es el parámetro de lista

(* ae) es solo palabra clave

(** ab) es el parámetro var-keyword

  • ahora lo secundario es si intento algo como esto: def example(a, b, c=a,d=b):

el argumento no se define cuando se guardan los valores predeterminados, Python calcula y guarda los valores predeterminados cuando define la función

cyd no están definidos, no existe, cuando esto sucede (existe solo cuando se ejecuta la función)

"a, a = b" no está permitido en el parámetro.

Aaditya Ura
fuente
0

Los argumentos obligatorios (los que no tienen valores predeterminados) deben estar al principio para permitir que el código del cliente solo suministre dos. Si los argumentos opcionales estuvieran al principio, sería confuso:

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

¿Qué haría eso en tu primer ejemplo? En el último, x es "quién es quién", y es 3 y a = "jack".

cforbish
fuente