2009-09-13 11 views
198

¿En qué se diferencian los "argumentos de palabras clave" de los argumentos comunes? ¿No se pueden pasar todos los argumentos como name=value en lugar de utilizar la sintaxis posicional?Argumentos normales de Python contra argumentos de palabra clave

+5

Es posible que también desee leer PEP 3102: están ordenando algunas de estas cosas en Python 3. Consulte: http://www.python.org/dev/peps/pep-3102/ –

+0

Y si o no hay un valor predeterminado que no tenga nada que ver con eso (excepto si necesita o no pasarle un valor), ¿verdad? – mk12

+0

Más información sobre [argumentos posicionales/de palabras clave de python] (http://symfony-world.blogspot.com/2013/07/python-positional-arguments-and-keyword.html) – ducin

Respuesta

256

hay dos conceptos relacionados, ambos denominados "argumentos de palabra clave".

Por el lado de las llamadas, que es lo que otros comentadores han mencionado, usted tiene la capacidad de especificar algunos argumentos de función por nombre. Debe mencionarlos después de todos los argumentos sin nombres (argumentos posicionales), y debe haber valores predeterminados para los parámetros que no se mencionaron en absoluto.

El otro concepto está en el lado de la definición de función: Puede definir una función que tome parámetros por nombre, y usted ni siquiera tiene que especificar cuáles son esos nombres. Estos son argumentos puros de palabras clave, y no se pueden pasar posicionalmente. La sintaxis es

def my_function(arg1, arg2, **kwargs) 

Cualquier argumento de palabra clave que pase a esta función se colocará en un diccionario llamado kwargs. Puede examinar las claves de este diccionario en tiempo de ejecución, así:

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

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

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

+1 y aceptado: Usted es el único que habló sobre ambos tipos de argumentos posicionales + palabras clave, todos los demás pensaron que estaba hablando del primero o el segundo (pero aún así eran buenas publicaciones). ¡Gracias! – mk12

+17

La redacción no está clara: normalmente habla de argumentos en el lado de la llamada mientras que de parámetros en el lado de la llamada. – glglgl

20

Hay dos formas de asignar valores de argumento a los parámetros de función, ambos se utilizan.

  1. Por posición. Los argumentos posicionales no tienen palabras clave y se asignan primero.

  2. Por palabra clave. Los argumentos de palabras clave tienen palabras clave y se asignan en segundo lugar, después de los argumentos posicionales.

Tenga en cuenta que que tiene la opción de utilizar argumentos posicionales.

Si que no utilizan argumentos posicionales, a continuación, - sí - todo lo que escribió resulta ser un argumento de palabra clave.

Cuando usted llama a una función que toma la decisión de usar posición o palabra clave o una mezcla. Puede elegir hacer todas las palabras clave si lo desea. Algunos de nosotros no hacemos esta elección y usamos argumentos posicionales.

+1

Ohh, estaba pensando en los parámetros, cuando lo que realmente es son los argumentos (qué * I * pasar). ¡Gracias! – mk12

+2

Si pudiera aceptar dos el suyo sería el siguiente. – mk12

80

El uso de argumentos de palabra clave es lo mismo que los argumentos normales, excepto que el orden no importa. Por ejemplo las dos funciones llamadas a continuación son los mismos:

def foo(bar, baz): 
    pass 

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

Gracias por esto.Es increíblemente útil que ** pueda ** especificar una palabra clave arg como una arg posicional, ** y ** una arg posicional como una palabra clave arg. –

32

argumentos posicionales

No tienen palabras clave ante ellos. ¡El orden es importante!

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

argumentos clave

Tienen palabras clave en la parte delantera. ¡Pueden estar en cualquier orden!

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

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

También debe saber que si utiliza argumentos predeterminados y olvida insertar las palabras clave, ¡entonces el orden será importante!

def func(foo=1, baz=2, hello=3): ... 
func("bar", 5, 123) 
+3

en mi humilde opinión, el tercer ejemplo (argumentos por defecto) no es claro. Creo que estás hablando de lo que sucede cuando uno o más parámetros declaran valores predeterminados, y la llamada usa notación posicional, pero proporciona MENOS que el número de parámetros declarados. Sin embargo, su ejemplo tiene 3 declarados y 3 en la llamada, por lo que los valores predeterminados no tienen ningún efecto. ¿Pensabas omitir el 3er arg? p.ej. 'func (" barra ", 5)'? Y luego diga que 'hello' obtiene su valor predeterminado de' 3'. – ToolmakerSteve

10

Me sorprende que nadie ha mencionado el hecho de que se puede mezclar argumentos posicionales y de palabras clave para hacer cosas como esta disimulados mediante *args y **kwargs (from this site):

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

Esto le permite a utilice argumentos arbitrarios de palabras clave que pueden tener claves que no desea definir por adelantado.

138

Hay una característica del último idioma donde la distinción es importante. Considere la siguiente función:

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

El argumento *positional almacenará todos los argumentos posicionales pasados ​​a foo(), sin límite en la cantidad que se puede brindar.

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

El argumento **keywords almacenará los argumentos de palabras clave:

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

Y, por supuesto, puede utilizar ambos al mismo tiempo:

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

Estas características se usan muy poco, pero ocasionalmente son muy útiles, y es importante saber qué argumentos son posicionales o palabras clave.

+0

¡Excelente respuesta! Solo se puede pasar una nota que requiera argumentos posicionales antes de '* positional' y' ** keywords' si cambiamos la definición de función como 'def foo (arg1, * positional, ** keywords):'. Aquí 'arg1' es posicional y obligatorio. Tenga en cuenta que posicional en respuesta significa número opcional y variable de argumentos posicionales. – shaffooo

18

Me sorprende que nadie parece haber señalado que se puede pasar de un diccionario de parámetros de argumentos con llave, que satisfacen los formales parámetros, como tal.

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

+1 para una técnica útil. Su punto sería más claro, sin ', ** kwargs'. Eso demostraría que incluso una definición de función simple, con un número fijo de parámetros, puede suministrarse en un diccionario. Es decir, no requiere nada sofisticado en la definición. ENTONCES podría agregar un segundo ejemplo, CON ** kwargs en definición, y mostrar cómo los elementos EXTRA en el diccionario están disponibles a través de eso. – ToolmakerSteve

+0

He visto esto suceder en el código fuente de varias bibliotecas y estaba tan confundido. ¡Gracias por aclararme! –

+2

El cuarto parámetro formal anterior - ** kwargs es necesario si alguna vez llama a func con un diccionario que contiene claves distintas de 'a', 'b' y 'c'. – Eduardo

11

Usando Python 3 puede tener tanto necesaria y la palabra clave arguments no requiere:

Opcional: (valor predeterminado definido para 'b')

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

Obligatorio (no se ha definido un valor predeterminado para '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'` 

Esto puede ayudar en los casos en que tenga muchos argumentos similares uno al lado del otro, especialmente si son del mismo tipo, en ese caso prefiero usar argumentos con nombre o crear una clase personalizada si los argumentos van juntos.

+2

La variante * requerida * es bastante útil. Insta a dar los args por nombre sin proporcionar los valores predeterminados, que a menudo no tiene sentido. – TNT

+0

Los valores predeterminados se ven bien y pueden ayudarlo a ahorrar tiempo cuando comienza, pero a la larga los valores predeterminados pueden ser un PITA. –

Cuestiones relacionadas