Python Language
* args y ** kwargs
Buscar..
Observaciones
Hay algunas cosas a tener en cuenta:
Los nombres
args
ykwargs
se usan por convención, no forman parte de la especificación del lenguaje. Por lo tanto, estos son equivalentes:def func(*args, **kwargs): print(args) print(kwargs)
def func(*a, **b): print(a) print(b)
No puede tener más de un
args
o más de un parámetro dekwargs
(sin embargo, no son necesarios)def func(*args1, *args2): # File "<stdin>", line 1 # def test(*args1, *args2): # ^ # SyntaxError: invalid syntax
def test(**kwargs1, **kwargs2): # File "<stdin>", line 1 # def test(**kwargs1, **kwargs2): # ^ # SyntaxError: invalid syntax
Si algún argumento posicional sigue a
*args
, son argumentos de palabra clave que solo se pueden pasar por nombre. Se puede usar una sola estrella en lugar de*args
para forzar que los valores sean argumentos de palabras clave sin proporcionar una lista de parámetros variadic. Las listas de parámetros de palabras clave solo están disponibles en Python 3.def func(a, b, *args, x, y): print(a, b, args, x, y) func(1, 2, 3, 4, x=5, y=6) #>>> 1, 2, (3, 4), 5, 6
def func(a, b, *, x, y): print(a, b, x, y) func(1, 2, x=5, y=6) #>>> 1, 2, 5, 6
**kwargs
deben estar en último lugar en la lista de parámetros.def test(**kwargs, *args): # File "<stdin>", line 1 # def test(**kwargs, *args): # ^ # SyntaxError: invalid syntax
Usando * args al escribir funciones
Puede usar la estrella * al escribir una función para recopilar todos los argumentos posicionales (es decir, sin nombre) en una tupla:
def print_args(farg, *args):
print("formal arg: %s" % farg)
for arg in args:
print("another positional arg: %s" % arg)
Método de llamada:
print_args(1, "two", 3)
En esa llamada, farg se asignará como siempre, y los otros dos se introducirán en la tupla de args, en el orden en que se recibieron.
Usando ** kwargs al escribir funciones
Puede definir una función que tome un número arbitrario de argumentos de palabra clave (nombrados) usando la estrella doble **
antes del nombre de un parámetro:
def print_kwargs(**kwargs):
print(kwargs)
Al llamar al método, Python construirá un diccionario de todos los argumentos de palabras clave y lo pondrá a disposición en el cuerpo de la función:
print_kwargs(a="two", b=3)
# prints: "{a: "two", b=3}"
Tenga en cuenta que el parámetro ** kwargs en la definición de la función siempre debe ser el último parámetro, y solo coincidirá con los argumentos que se pasaron después de los anteriores.
def example(a, **kw):
print kw
example(a=2, b=3, c=4) # => {'b': 3, 'c': 4}
Dentro del cuerpo de la función, los kwargs
se manipulan de la misma manera que un diccionario; para acceder a elementos individuales en kwargs
, solo tienes que recorrerlos como lo harías con un diccionario normal:
def print_kwargs(**kwargs):
for key in kwargs:
print("key = {0}, value = {1}".format(key, kwargs[key]))
Ahora, al llamar a print_kwargs(a="two", b=1)
muestra el siguiente resultado:
print_kwargs(a = "two", b = 1)
key = a, value = "two"
key = b, value = 1
Usando * args al llamar a funciones
Un caso de uso común para *args
en una definición de función es delegar el procesamiento a una función envuelta o heredada. Un ejemplo típico podría estar en el método __init__
una clase
class A(object):
def __init__(self, b, c):
self.y = b
self.z = c
class B(A):
def __init__(self, a, *args, **kwargs):
super(B, self).__init__(*args, **kwargs)
self.x = a
Aquí, el a
parámetro es procesado por la clase niño después de todos los otros argumentos (posicionales y de palabras clave) son pasados a - y procesados por - la clase base.
Por ejemplo:
b = B(1, 2, 3)
b.x # 1
b.y # 2
b.z # 3
Lo que sucede aquí es que la función de clase B
__init__
ve los argumentos 1, 2, 3
. Sabe que necesita tomar un argumento posicional ( a
), por lo que toma el primer argumento pasado en ( 1
), por lo que en el alcance de la función a == 1
.
A continuación, ve que necesita tomar un número arbitrario de argumentos posicionales ( *args
), por lo que toma el resto de los argumentos posicionales pasados en ( 1, 2
) y los mete en *args
. Ahora (en el ámbito de la función) args == [2, 3]
.
Luego, llama a la función __init__
clase A
con *args
. Python ve el *
delante de args y "desempaqueta" la lista en argumentos. En este ejemplo, cuando la clase B
's __init__
llamadas de función de clase A
' s __init__
función, será pasado los argumentos 2, 3
(es decir, A(2, 3)
).
Finalmente, establece su propia propiedad x
en el primer argumento posicional a
, que es igual a 1
.
Usando ** kwargs al llamar a funciones
Puede usar un diccionario para asignar valores a los parámetros de la función; usando los parámetros nombre como claves en el diccionario y el valor de estos argumentos enlazados a cada clave:
def test_func(arg1, arg2, arg3): # Usual function with three arguments
print("arg1: %s" % arg1)
print("arg2: %s" % arg2)
print("arg3: %s" % arg3)
# Note that dictionaries are unordered, so we can switch arg2 and arg3. Only the names matter.
kwargs = {"arg3": 3, "arg2": "two"}
# Bind the first argument (ie. arg1) to 1, and use the kwargs dictionary to bind the others
test_var_args_call(1, **kwargs)
Usando * args al llamar a funciones
El efecto de usar el operador *
en un argumento al llamar a una función es el de desempaquetar la lista o un argumento de tupla
def print_args(arg1, arg2):
print(str(arg1) + str(arg2))
a = [1,2]
b = tuple([3,4])
print_args(*a)
# 12
print_args(*b)
# 34
Tenga en cuenta que la longitud del argumento destacado debe ser igual al número de argumentos de la función.
Un lenguaje común en Python es usar el operador de desempaquetado *
con la función zip
para revertir sus efectos:
a = [1,3,5,7,9]
b = [2,4,6,8,10]
zipped = zip(a,b)
# [(1,2), (3,4), (5,6), (7,8), (9,10)]
zip(*zipped)
# (1,3,5,7,9), (2,4,6,8,10)
Argumentos solo de palabra clave y requeridos de palabra clave
Python 3 le permite definir argumentos de función que solo pueden asignarse por palabra clave, incluso sin valores predeterminados. Esto se hace usando star * para consumir parámetros posicionales adicionales sin configurar los parámetros de palabras clave. Todos los argumentos después del * son argumentos de palabra clave solamente (es decir, no posicionales). Tenga en cuenta que si los argumentos de solo palabras clave no tienen un valor predeterminado, todavía son necesarios al llamar a la función.
def print_args(arg1, *args, keyword_required, keyword_only=True):
print("first positional arg: {}".format(arg1))
for arg in args:
print("another positional arg: {}".format(arg))
print("keyword_required value: {}".format(keyword_required))
print("keyword_only value: {}".format(keyword_only))
print(1, 2, 3, 4) # TypeError: print_args() missing 1 required keyword-only argument: 'keyword_required'
print(1, 2, 3, keyword_required=4)
# first positional arg: 1
# another positional arg: 2
# another positional arg: 3
# keyword_required value: 4
# keyword_only value: True
Poblando los valores kwarg con un diccionario
def foobar(foo=None, bar=None):
return "{}{}".format(foo, bar)
values = {"foo": "foo", "bar": "bar"}
foobar(**values) # "foobar"
** kwargs y valores por defecto
Para usar los valores por defecto con ** kwargs
def fun(**kwargs):
print kwargs.get('value', 0)
fun()
# print 0
fun(value=1)
# print 1