¿En qué se diferencian los "argumentos de palabras clave" de los argumentos regulares? ¿No se pueden pasar todos los argumentos en name=value
lugar de utilizar la sintaxis posicional?
¿En qué se diferencian los "argumentos de palabras clave" de los argumentos regulares? ¿No se pueden pasar todos los argumentos en name=value
lugar de utilizar la sintaxis posicional?
Respuestas:
Hay dos conceptos relacionados, ambos llamados " argumentos de palabras clave ".
En el lado de la llamada, que es lo que han mencionado otros comentaristas, 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 cualquier parámetro que no se mencionó en absoluto.
El otro concepto está en el lado de la definición de funciones: puede definir una función que tome parámetros por nombre, y ni siquiera tiene que especificar cuáles son esos nombres. Estos son argumentos de palabras clave puras 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'}
kwargs
o puedo cambiarle el nombre a algo? como options
( def my_fuction(arg1, arg2, **options)
)?
kwargs
es la convención cuando no hay un nombre más apropiado
Hay una última característica del idioma donde la distinción es importante. Considere la siguiente función:
def foo(*positional, **keywords):
print "Positional:", positional
print "Keywords:", keywords
El *positional
argumento almacenará todos los argumentos posicionales pasados foo()
, sin límite de cuántos puede proporcionar.
>>> foo('one', 'two', 'three')
Positional: ('one', 'two', 'three')
Keywords: {}
El **keywords
argumento almacenará cualquier argumento de palabra clave:
>>> foo(a='one', b='two', c='three')
Positional: ()
Keywords: {'a': 'one', 'c': 'three', 'b': 'two'}
Y, por supuesto, puede usar ambos al mismo tiempo:
>>> foo('one','two',c='three',d='four')
Positional: ('one', 'two')
Keywords: {'c': 'three', 'd': 'four'}
Estas características rara vez se usan, pero ocasionalmente son muy útiles, y es importante saber qué argumentos son posicionales o palabras clave.
*positional
y **keywords
si cambiamos la definición de la función como def foo(arg1, *positional, **keywords):
. Aquí arg1
es posicional y requerido. Tenga en cuenta que posicional en respuesta significa un número opcional y variable de argumentos posicionales.
foo(bar=True)
, puede obtener los valores utilizando el bar = keywords.pop('bar')
mismo que bar = keywords.pop('bar', None)
. Para el valor predeterminado, usebar = keywords.pop('bar', False)
Usar argumentos de palabras clave es lo mismo que los argumentos normales, excepto que el orden no importa. Por ejemplo, las dos llamadas de funciones a continuación son las mismas:
def foo(bar, baz):
pass
foo(1, 2)
foo(baz=2, bar=1)
No tienen palabras clave antes que ellos. ¡El orden es importante!
func(1,2,3, "foo")
Tienen palabras clave en el frente. ¡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 usa argumentos predeterminados y descuida insertar las palabras clave, ¡entonces el orden será importante!
def func(foo=1, baz=2, hello=3): ...
func("bar", 5, 123)
func("bar", 5)
? Y luego decir que hello
obtiene su valor predeterminado de 3
.
Hay dos formas de asignar valores de argumentos a los parámetros de función, ambos se utilizan.
Por puesto. Los argumentos posicionales no tienen palabras clave y se asignan primero.
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 usted tiene la opción de utilizar argumentos posicionales.
Si usted no utiliza argumentos posicionales, a continuación, - sí - todo lo que escribiste resulta ser un argumento de palabra clave.
Cuando se llama a una función de tomar una decisión de posición de uso o una 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.
Me sorprende que nadie parezca haber señalado que se puede pasar un diccionario de parámetros de argumentos clave, que satisfacen los parámetros formales, de esa manera.
>>> 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
>>>
, **kwargs
. Eso demostraría que incluso una simple función def, con un número fijo de parámetros, se puede suministrar un diccionario. Es decir, no requiere nada elegante en la definición. ENTONCES puede 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.
print 'a:%s, b:%s, c:%s' % (a, b, c)
da error de sintaxis, sin embargo print('a:%s, b:%s, c:%s' % (a, b, c))
funciona. ¿Algo con la versión de Python? De todos modos, gracias por esta idea, hasta ahora estaba usando el más torpeprint('a:{}, b:{}, c:{}'.format(a, b, c))
Con Python 3 puede tener argumentos de palabras clave tanto obligatorios como no obligatorios :
Opcional : (valor predeterminado definido para el parámetro 'b')
def func1(a, *, b=42):
...
func1(value_for_a) # b is optional and will default to 42
Obligatorio (sin valor predeterminado definido para el 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'`
Esto puede ayudar en casos en los que tiene muchos argumentos similares uno al lado del otro, especialmente si son del mismo tipo, en ese caso prefiero usar argumentos con nombre o creo una clase personalizada si los argumentos van de la mano.
Me sorprende que nadie haya mencionado el hecho de que puede mezclar argumentos posicionales y de palabras clave para hacer cosas furtivas como esta usando *args
y **kwargs
( desde este sitio ):
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 utilizar argumentos de palabras clave arbitrarias que pueden tener claves que no desea definir por adelantado.
Estaba buscando un ejemplo que tuviera kwargs predeterminados usando la anotación de tipo:
def test_var_kwarg(a: str, b: str='B', c: str='', **kwargs) -> str:
return ' '.join([a, b, c, str(kwargs)])
ejemplo:
>>> 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 {}
Simplemente suplemente / agregue una forma de definir el valor predeterminado de los argumentos que no se asignan en palabras clave al llamar a la función:
def func(**keywargs):
if 'my_word' not in keywargs:
word = 'default_msg'
else:
word = keywargs['my_word']
return word
llama a esto por:
print(func())
print(func(my_word='love'))
obtendrás:
default_msg
love
Lea más sobre *args
y **kwargs
en Python: https://www.digitalocean.com/community/tutorials/how-to-use-args-and-kwargs-in-python-3