2011-12-13 12 views
8

estoy leyendo los códigos fuente de mercurio, y encontraron una definición tal func en commands.py:pitón argumentos posicionales y argumentos de palabras clave

def import_(ui, repo, patch1=None, *patches, **opts): 
    ... 

en Python, args postional debe ser puesto por delante de argumentos de palabra clave. Pero aquí, patch1 es un argumento de palabra clave, seguido de un argumento posicional *patches. ¿Por qué está esto bien?

+1

¿Ya ha resuelto esto? Si es así, sería bueno que seleccionas la respuesta que te hizo resolver el problema como "aceptado" y anulas todas las útiles (¡si aún no lo has hecho!). :) – mac

+0

lo siento, he estado muy ocupado todos estos días. Ahora leeré sobre tus respuestas y seleccionaré una. Gracias a todos :) – guoqiao

Respuesta

8

Solo eche un vistazo a PEP 3102 y parece estar relacionado de alguna manera con this.

Para resumir, los parches y las opciones están ahí para aceptar argumentos variables pero la última es para aceptar argumentos de palabra clave. Los argumentos de palabra clave se pasan como un diccionario donde variable positional arguments would be wrapped as tuples.

de su ejemplo

def import_(ui, repo, patch1=None, *patches, **opts): 

Los parámetros posicionales después u1,repo and patch1 podría ser envuelto como tuplas de parches. Todos los argumentos de palabra clave que siguen a los argumentos posicionales de variables se envolverán como objetos de diccionario mediante opts.

Otra cosa importante es que la responsabilidad recae en la persona que llama para asegurarse de que no se infringe la condición non-keyword arg after keyword arg.

Así que algo que viola esto podría generar un error de sintaxis ..

Por ejemplo

llamadas como

import_(1,2,3,test="test") 
import_(1,2,3,4,test="test") 
import_(1,2,3,4,5) 
import_(1,2,patch1=3,test="test") 

son válidas, pero

import_(1,2,3,patch1=4,5) 

elevarían un error de sintaxis SyntaxError: non-keyword arg after keyword arg

En el primer caso válido import_(1,2,3,test="test")

u1 = 1, repo = 2, patch1 = 3, patches =() and opts={"test":"test"} 

En el segundo caso válido import_(1,2,3,patch1=4,test="test")

u1 = 1, repo = 2, patch1 = 3 , patches = (4) and opts={"test":"test"} 

En el tercer caso válido import_(1,2,3,4,5)

u1 = 1, repo = 2, patch1 = 3 , patches=(4,5), and opts={} 

En el cuarto caso válido import_(1,2,patch1=3,test="test")

u1 = 1, repo = 2, patch1 = 3 , patches=(), and opts={"test":"test"} 
you can use patch1 as a keywords argument but doing so you cannot wrap any variable positional arguments within patches 
+0

Gracias por sus ejemplos y referencias, creo que recibo mi respuesta. Los argumentos de Python son tan flexibles que no sabía lo suficiente antes de este problema. – guoqiao

2

Porque pasar la clave a un argumento de palabra clave puede ser opcional si la posición de la misma no es ambigua. Observe:

>>> def f(ui, patch1=None, *patches, **opts): 
...  print patch1 
... 
>>> f(1, 2) 
2 
>>> f(1, patch1='a', 3) 
    File "<stdin>", line 1 
SyntaxError: non-keyword arg after keyword arg 
>>> f(1, 'a', 3) 
a 

Como se puede ver, la omisión de la clave de patch1 hacen que el argumento de una palabra clave no uno, por lo tanto no desencadenar la excepción SyntaxError.


EDIT: moooeeeep en su respuesta dice que

"patch1 no es una palabra clave arg, es un arg posicional con un valor por defecto asignado argumento."

Esto no es malo, pero el siguiente caso de la OMI, ilustra por qué tal definición es ambigua:

>>> def f(ui, p1=None, p2=None, *patches, **opts): 
... print p1, p2 
... 
>>> f(1, 'a', 'b', 3) #p2 is a positional argument with default value? 
a b 
>>> f(1, p2='b') #p2 is a keyword argument? 
None b 

HTH!

+0

sí ... en mi opinión, es una ambigüedad en tiempo de ejecución, no una ambigüedad de definición de tiempo. Como OP está relacionado con la definición de la función [Estaba describiendo la definición de la función] (http://stackoverflow.com/a/8486166/1025391). Pero reconozco que este es un buen punto para tener en cuenta. – moooeeeep

3

Probablemente esté confundiendo un poco la definición de función y la sintaxis de llamada de función.

patch1 no es una palabra clave arg, es un argumento posicional con un valor de argumento predeterminado asignado.

*patches es una lista de argumentos, y no un argumento posicional.


favor, eche un vistazo a esta sección de los tutoriales oficiales:

Ahora vamos a resumir los puntos principales de utilizar esta función como un ejemplo:

def f1(a1, a2, a3=None, *args, **kwargs): 
    print a1, a2, a3, args, kwargs 

Función Definición

usted tiene un número de argumentos que se definen explícitamente por su nombre (a1, a2 y a3), de los cuales a3 habrá inicializado por defecto None si no se suministra durante la llamada. Los argumentos a1 y a2 se deben suministrar en cualquier llamada válida de esa función.

La función se puede invocar con argumentos adicionales que aparecerán en el diccionario kwargs (cuando se proporciona por palabra clave) o en la lista args (cuando no se proporciona por palabra clave). Si args y kwargs no estuvieran presentes en la definición de la función, la persona que llama no podría agregar más argumentos además de los explícitamente nombrados en la definición de función para la llamada a la función.

En la definición de la función, primero debe especificar los argumentos explícitos sin inicializador predeterminado, segundo los argumentos explícitos con inicializador predeterminado, tercero la lista de argumentos, por último, el diccionario de palabras clave y argumentos.

llamada a función

Hay varias maneras de llamar a la función. Por ejemplo serán las siguientes llamadas producir resultados iguales:

f1(1, 2)  # pass a1 and a2 as positional arguments 
f1(a2=2, a1=1) # pass a1 and a2 as keyword arguments 
f1(1, a2=2) # pass a1 as positional argument, a2 as keyword argument 

Es decir, los argumentos de la función que se resuelvan ya sea por su posición (argumentos posicionales, o no de la palabra clave) o por su nombre especificado (argumentos de palabra clave).

Al llamar a la función, primero debe poner los argumentos que no son palabras clave y finalmente los argumentos de la palabra clave, p. Ej.

# demonstrate how some additional positional and keyword arguments are passed 
f1(1, 2, 3, 4, 5, 6, 7, a4=8, a5=9, a6=10) 
# prints: 
# 1 2 3 (4, 5, 6, 7) {'a5': 9, 'a4': 8, 'a6': 10} 

Ahora, los argumentos posicionales que no encajan en la lista de argumentos especificados en la definición de función se añadirá a la lista de argumentos *args, y los argumentos de palabras clave que no encajan en la lista de argumentos especificados en la definición de la función se insertará en el diccionario de argumentos de palabra clave **kwargs.

+0

Encuentro esta definición ligeramente ambigua (aunque no incorrecta). Ver ediciones en mi respuesta sobre por qué. – mac

+0

gracias! vea mi comentario en su respuesta:] – moooeeeep

+0

Vea mi ejemplo, puede usar patch1 como argumento de palabra clave siempre que no haya argumentos posicionales después de él. – Abhijit

2

Creo que cuando llamando una función con:

function(arg1="value") 

Esto sería utilizar un argumento "palabra clave", pero cuando define la interfaz de una de función con:

def function(arg1="value"): 

se está definiendo un "valor por defecto" .()

Para responder a su pregunta; Tener un valor predeterminado después de un argumento posicional es perfectamente normal, y también lo es llamar a una función con un argumento que no sea de palabra clave antes de una palabra clave.

También tenga en cuenta que al llamar a una función, no puede tener un argumento que no sea una palabra clave después de una palabra clave.

+0

gracias por su respuesta. – guoqiao

Cuestiones relacionadas