¿Qué hace ** (doble estrella/asterisco) y * (estrella/asterisco) para los parámetros?


En las siguientes definiciones de métodos, ¿qué hacen * y ** para param2?

def foo(param1, *param2):
def bar(param1, **param2):
Author: Florian_1990, 2008-08-31

18 answers

El *args y **kwargs es un modismo común para permitir un número arbitrario de argumentos a las funciones como se describe en la sección más sobre la definición de funciones en la documentación de Python.

El *args le dará todos los parámetros de función como una tupla :

In [1]: def foo(*args):
   ...:     for a in args:
   ...:         print a
   ...:         
   ...:         

In [2]: foo(1)
1


In [4]: foo(1,2,3)
1
2
3

El **kwargs te dará todo argumentos de palabras clave excepto aquellos que corresponden a un parámetro formal como un diccionario.

In [5]: def bar(**kwargs):
   ...:     for a in kwargs:
   ...:         print a, kwargs[a]
   ...:         
   ...:         

In [6]: bar(name='one', age=27)
age 27
name one

Ambos modismos se pueden mezclar con argumentos normales para permitir un conjunto de argumentos fijos y algunos variables:

def foo(kind, *args, **kwargs):
   pass

Otro uso del modismo *l es para desempaquetar listas de argumentos cuando se llama a una función.

In [9]: def foo(bar, lee):
   ...:     print bar, lee
   ...:     
   ...:     

In [10]: l = [1,2]

In [11]: foo(*l)
1 2

En Python 3 es posible usar *l en el lado izquierdo de una asignación ( Extended Iterable Unpacking ), aunque da una lista en lugar de una tupla en este contexto:

first, *rest = [1,2,3,4]
first, *l, last = [1,2,3,4]

También Python 3 agrega nueva semántica (consulte PEP 3102):

def func(arg1, arg2, arg3, *, kwarg1, kwarg2):
    pass

Tal función acepta solo 3 argumentos posicionales, y todo después de * solo se pueden pasar como argumentos de palabras clave.

 1618
Author: Peter Hoffmann,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-28 12:54:20

También vale la pena señalar que puede usar * y ** cuando llame a funciones también. Este es un atajo que le permite pasar varios argumentos a una función directamente usando una lista/tupla o un diccionario. Por ejemplo, si tiene la siguiente función:

def foo(x,y,z):
    print("x=" + str(x))
    print("y=" + str(y))
    print("z=" + str(z))

Puedes hacer cosas como:

>>> mylist = [1,2,3]
>>> foo(*mylist)
x=1
y=2
z=3

>>> mydict = {'x':1,'y':2,'z':3}
>>> foo(**mydict)
x=1
y=2
z=3

>>> mytuple = (1, 2, 3)
>>> foo(*mytuple)
x=1
y=2
z=3

Nota: Las claves en mydict tienen que ser nombradas exactamente como los parámetros de la función foo. De lo contrario lanzará un TypeError:

>>> mydict = {'x':1,'y':2,'z':3,'badnews':9}
>>> foo(**mydict)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() got an unexpected keyword argument 'badnews'
 468
Author: Lorin Hochstein,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-07 01:53:17

El sencillo * significa que puede haber cualquier número de argumentos posicionales adicionales. foo() se puede invocar como foo(1,2,3,4,5). En el cuerpo de foo() param2 es una secuencia que contiene 2-5.

El doble ** significa que puede haber cualquier número de parámetros adicionales con nombre. bar() se puede invocar como bar(1, a=2, b=3). En el cuerpo de bar() param2 es un diccionario que contiene {'a':2,'b': 3}

Con el siguiente código:

def foo(param1, *param2):
    print param1
    print param2

def bar(param1, **param2):
    print param1
    print param2

foo(1,2,3,4,5)
bar(1,a=2,b=3)

La salida es

1
(2, 3, 4, 5)
1
{'a': 2, 'b': 3}
 135
Author: nickd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-31 15:20:21

¿Qué hace ** (doble estrella) y * (estrella) para los parámetros

Permiten que las funciones se definan para aceptar y que los usuarios pasen cualquier número de argumentos, posicionales (*) y palabras clave (**).

Definir funciones

*args permite cualquier número de argumentos posicionales opcionales (parámetros), que se asignarán a una tupla llamada args.

**kwargs permite cualquier número de palabras clave opcionales argumentos (parámetros), que estarán en un dict llamado kwargs.

Puede (y debe) elegir cualquier nombre apropiado, pero si la intención es que los argumentos sean de semántica no específica, args y kwargs son nombres estándar.

Expansión, Pasando cualquier número de argumentos

También puede usar *args y **kwargs para pasar parámetros de listas (o cualquier iterable) y dicts (o cualquier asignación), respectivamente.

La función que recibe los parámetros no hay que saber que se están expandiendo.

Por ejemplo, xrange de Python 2 no espera explícitamente *args, pero como toma 3 enteros como argumentos:

>>> x = xrange(3) # create our *args - an iterable of 3 integers
>>> xrange(*x)    # expand here
xrange(0, 2, 2)

Como otro ejemplo, podemos usar la expansión dict en str.format:

>>> foo = 'FOO'
>>> bar = 'BAR'
>>> 'this is foo, {foo} and bar, {bar}'.format(**locals())
'this is foo, FOO and bar, BAR'

Nuevo en Python 3: Definir funciones con argumentos solo para palabras clave

Puede tener solo argumentos de palabra clave después de *args - por ejemplo, aquí, kwarg2 debe darse como un argumento de palabra clave-no posicionalmente:

def foo(arg, kwarg=None, *args, kwarg2=None, **kwargs): 
    return arg, kwarg, args, kwarg2, kwargs

Uso:

>>> foo(1,2,3,4,5,kwarg2='kwarg2', bar='bar', baz='baz')
(1, 2, (3, 4, 5), 'kwarg2', {'bar': 'bar', 'baz': 'baz'})

También, * se puede usar por sí mismo para indicar que la palabra clave solo sigue argumentos, sin permitir argumentos posicionales ilimitados.

def foo(arg, kwarg=None, *, kwarg2=None, **kwargs): 
    return arg, kwarg, kwarg2, kwargs

Aquí, kwarg2 de nuevo debe ser un argumento de palabra clave explícitamente nombrado:

>>> foo(1,2,kwarg2='kwarg2', foo='foo', bar='bar')
(1, 2, 'kwarg2', {'foo': 'foo', 'bar': 'bar'})

Y ya no podemos aceptar argumentos posicionales ilimitados porque no tenemos *args*:

>>> foo(1,2,3,4,5, kwarg2='kwarg2', foo='foo', bar='bar')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() takes from 1 to 2 positional arguments 
    but 5 positional arguments (and 1 keyword-only argument) were given

De nuevo, más simplemente, aquí requerimos kwarg que se nos dé por nombre, no posicionalmente:

def bar(*, kwarg=None): 
    return kwarg

En este ejemplo, vemos que si intentamos pasar kwarg posicionalmente, obtenemos un error:

>>> bar('kwarg')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: bar() takes 0 positional arguments but 1 was given

Debemos pasar explícitamente el parámetro kwarg como argumento de palabra clave.

>>> bar(kwarg='kwarg')
'kwarg'

Demos compatibles con Python 2

*args (típicamente dicho "star-args") y **kwargs (las estrellas se pueden implicar diciendo "kwargs", pero ser explícito con" kwargs de doble estrella") son expresiones comunes de Python para usar la notación * y **. Estos nombres de variables específicas no son necesarios (por ejemplo, podría usar *foos y **bars), pero es probable que una desviación de la convención enfurezca a sus compañeros codificadores de Python.

Normalmente usamos estos cuando no sabemos qué va a recibir nuestra función o cuántos argumentos podemos estar pasando, y a veces incluso cuando nombrar cada variable por separado se volvería muy desordenado y redundante (pero este es un caso donde generalmente lo explícito es mejor que lo implícito).

Ejemplo 1

Lo siguiente la función describe cómo se pueden usar y demuestra el comportamiento. Note que el argumento named b será consumido por el segundo argumento posicional antes de :

def foo(a, b=10, *args, **kwargs):
    '''
    this function takes required argument a, not required keyword argument b
    and any number of unknown positional arguments and keyword arguments after
    '''
    print('a is a required argument, and its value is {0}'.format(a))
    print('b not required, its default value is 10, actual value: {0}'.format(b))
    # we can inspect the unknown arguments we were passed:
    #  - args:
    print('args is of type {0} and length {1}'.format(type(args), len(args)))
    for arg in args:
        print('unknown arg: {0}'.format(arg))
    #  - kwargs:
    print('kwargs is of type {0} and length {1}'.format(type(kwargs),
                                                        len(kwargs)))
    for kw, arg in kwargs.items():
        print('unknown kwarg - kw: {0}, arg: {1}'.format(kw, arg))
    # But we don't have to know anything about them 
    # to pass them to other functions.
    print('Args or kwargs can be passed without knowing what they are.')
    # max can take two or more positional args: max(a, b, c...)
    print('e.g. max(a, b, *args) \n{0}'.format(
      max(a, b, *args))) 
    kweg = 'dict({0})'.format( # named args same as unknown kwargs
      ', '.join('{k}={v}'.format(k=k, v=v) 
                             for k, v in sorted(kwargs.items())))
    print('e.g. dict(**kwargs) (same as {kweg}) returns: \n{0}'.format(
      dict(**kwargs), kweg=kweg))

Podemos consultar la ayuda en línea para la firma de la función, con help(foo), que nos dice

foo(a, b=10, *args, **kwargs)

Llamemos a esta función con foo(1, 2, 3, 4, e=5, f=6, g=7)

Que imprime:

a is a required argument, and its value is 1
b not required, its default value is 10, actual value: 2
args is of type <type 'tuple'> and length 2
unknown arg: 3
unknown arg: 4
kwargs is of type <type 'dict'> and length 3
unknown kwarg - kw: e, arg: 5
unknown kwarg - kw: g, arg: 7
unknown kwarg - kw: f, arg: 6
Args or kwargs can be passed without knowing what they are.
e.g. max(a, b, *args) 
4
e.g. dict(**kwargs) (same as dict(e=5, f=6, g=7)) returns: 
{'e': 5, 'g': 7, 'f': 6}

Ejemplo 2

También podemos llamarlo usando otra función, en la que solo proporcionamos a:

def bar(a):
    b, c, d, e, f = 2, 3, 4, 5, 6
    # dumping every local variable into foo as a keyword argument 
    # by expanding the locals dict:
    foo(**locals()) 

bar(100) impresiones:

a is a required argument, and its value is 100
b not required, its default value is 10, actual value: 2
args is of type <type 'tuple'> and length 0
kwargs is of type <type 'dict'> and length 4
unknown kwarg - kw: c, arg: 3
unknown kwarg - kw: e, arg: 5
unknown kwarg - kw: d, arg: 4
unknown kwarg - kw: f, arg: 6
Args or kwargs can be passed without knowing what they are.
e.g. max(a, b, *args) 
100
e.g. dict(**kwargs) (same as dict(c=3, d=4, e=5, f=6)) returns: 
{'c': 3, 'e': 5, 'd': 4, 'f': 6}

Ejemplo 3: uso práctico en decoradores

OK, así que tal vez no estamos viendo la utilidad todavía. Así que imagine que tiene varias funciones con código redundante antes y / o después del código diferenciador. Las siguientes funciones son solo pseudo-código para fines ilustrativos.

def foo(a, b, c, d=0, e=100):
    # imagine this is much more code than a simple function call
    preprocess() 
    differentiating_process_foo(a,b,c,d,e)
    # imagine this is much more code than a simple function call
    postprocess()

def bar(a, b, c=None, d=0, e=100, f=None):
    preprocess()
    differentiating_process_bar(a,b,c,d,e,f)
    postprocess()

def baz(a, b, c, d, e, f):
    ... and so on

Podríamos ser capaces de manejar esto de manera diferente, pero ciertamente podemos extraer la redundancia con un decorador, y así nuestro el siguiente ejemplo demuestra cómo *args y **kwargs pueden ser muy útiles:

def decorator(function):
    '''function to wrap other functions with a pre- and postprocess'''
    @functools.wraps(function) # applies module, name, and docstring to wrapper
    def wrapper(*args, **kwargs):
        # again, imagine this is complicated, but we only write it once!
        preprocess()
        function(*args, **kwargs)
        postprocess()
    return wrapper

Y ahora cada función envuelta se puede escribir mucho más sucintamente, ya que hemos factorizado la redundancia:

@decorator
def foo(a, b, c, d=0, e=100):
    differentiating_process_foo(a,b,c,d,e)

@decorator
def bar(a, b, c=None, d=0, e=100, f=None):
    differentiating_process_bar(a,b,c,d,e,f)

@decorator
def baz(a, b, c=None, d=0, e=100, f=None, g=None):
    differentiating_process_baz(a,b,c,d,e,f, g)

@decorator
def quux(a, b, c=None, d=0, e=100, f=None, g=None, h=None):
    differentiating_process_quux(a,b,c,d,e,f,g,h)

Y al factorizar nuestro código, lo que *args y **kwargs nos permite hacer, reducimos las líneas de código, mejoramos la legibilidad y mantenibilidad, y tenemos ubicaciones canónicas únicas para la lógica en nuestro programa. Si necesitamos cambiar cualquier parte de esta estructura, tenemos un lugar en el que haz cada cambio.

 112
Author: Aaron Hall,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-20 20:21:05

Primero entendamos qué son los argumentos posicionales y los argumentos de palabras clave. A continuación se muestra un ejemplo de definición de función con argumentos posicionales .

def test(a,b,c):
     print(a)
     print(b)
     print(c)

test(1,2,3)
#output:
1
2
3

Así que esta es una definición de función con argumentos posicionales. También puede llamarlo con argumentos de palabra clave/nombre:

def test(a,b,c):
     print(a)
     print(b)
     print(c)

test(a=1,b=2,c=3)
#output:
1
2
3

Ahora estudiemos un ejemplo de definición de función con argumentos de palabra clave :

def test(a=0,b=0,c=0):
     print(a)
     print(b)
     print(c)
     print('-------------------------')

test(a=1,b=2,c=3)
#output :
1
2
3
-------------------------

Puede llamar a esta función con argumentos posicionales como bien:

def test(a=0,b=0,c=0):
    print(a)
    print(b)
    print(c)
    print('-------------------------')

test(1,2,3)
# output :
1
2
3
---------------------------------

Así que ahora sabemos definiciones de funciones con argumentos posicionales y de palabras clave.

Ahora estudiemos el operador '*' y el operador'**'.

Tenga en cuenta que estos operadores se pueden usar en 2 áreas:

A) llamada a la función

B) definición de función

El uso del operador '*' y el operador '**' en la llamada a la función .

Vayamos directamente a un ejemplo y luego discutámoslo.

def sum(a,b):  #receive args from function calls as sum(1,2) or sum(a=1,b=2)
    print(a+b)

my_tuple = (1,2)
my_list = [1,2]
my_dict = {'a':1,'b':2}

# Let us unpack data structure of list or tuple or dict into arguments with help of '*' operator
sum(*my_tuple)   # becomes same as sum(1,2) after unpacking my_tuple with '*'
sum(*my_list)    # becomes same as sum(1,2) after unpacking my_list with  '*'
sum(**my_dict)   # becomes same as sum(a=1,b=2) after unpacking by '**' 

# output is 3 in all three calls to sum function.

So recuerda

Cuando se usa el operador ' * ' o '* * ' en una llamada a la función -

El operador

'*' descomprime la estructura de datos como una lista o tupla en los argumentos necesarios para la definición de la función.

El operador

'**' descomprime un diccionario en argumentos necesarios para la definición de la función.

Ahora estudiemos el uso del operador '*' en la definición de la función . Ejemplo:

def sum(*args): #pack the received positional args into data structure of tuple. after applying '*' - def sum((1,2,3,4))
    sum = 0
    for a in args:
        sum+=a
    print(sum)

sum(1,2,3,4)  #positional args sent to function sum
#output:
10

En function definition el operador ' * ' empaqueta los argumentos recibidos en una tupla.

Ahora veamos un ejemplo de '* * ' usado en la definición de la función:

def sum(**args): #pack keyword args into datastructure of dict after applying '**' - def sum({a:1,b:2,c:3,d:4})
    sum=0
    for k,v in args.items():
        sum+=v
    print(sum)

sum(a=1,b=2,c=3,d=4) #positional args sent to function sum

En function definition El operador '**' empaqueta los argumentos recibidos en un diccionario.

Así que recuerda:

En una llamada a la función el '*' descomprime la estructura de datos de la tupla o lista en argumentos posicionales o de palabras clave para ser recibidos por la definición de la función.

En una llamada a la función el '* * ' descomprime la estructura de datos del diccionario en argumentos posicionales o de palabras clave para ser recibidos por la definición de la función.

En una definición de función el ' * ' empaqueta argumentos posicionales en una tupla.

En una definición de función el '**' empaqueta los argumentos de la palabra clave en un diccionario.

 38
Author: Karan Ahuja,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-06 19:53:44

* y ** tienen un uso especial en la lista de argumentos de la función. * implica que el argumento es una lista y ** implica que el argumento es un diccionario. Esto permite que las funciones tomen un número arbitrario de argumentos

 20
Author: ronak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-11 10:59:30

De la documentación de Python:

Si hay más argumentos posicionales que ranuras de parámetros formales, se genera una excepción TypeError, a menos que esté presente un parámetro formal que use la sintaxis "*identifier"; en este caso, ese parámetro formal recibe una tupla que contiene los argumentos posicionales en exceso (o una tupla vacía si no hay argumentos posicionales en exceso).

Si cualquier argumento de palabra clave no corresponde a un nombre de parámetro formal, un TypeError se genera la excepción, a menos que esté presente un parámetro formal usando la sintaxis "**identifier"; en este caso, ese parámetro formal recibe un diccionario que contiene los argumentos de palabras clave en exceso (usando las palabras clave como claves y los valores de los argumentos como valores correspondientes), o un diccionario vacío (nuevo) si no había argumentos de palabras clave en exceso.

 11
Author: Chris Upchurch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-31 15:07:48

Mientras que los usos para los operadores star/splat han sido expandidos en Python 3, me gusta la siguiente tabla ya que se relaciona con el uso de estos operadores con funciones. Los operadores splat se pueden usar tanto dentro de la construcción de function como en la función call :

            In function *construction*      In function *call*
=======================================================================
          |  def f(*args):                 |  def f(a, b):
*args     |      for arg in args:          |      return a + b
          |          print(arg)            |  args = (1, 2)
          |  f(1, 2)                       |  f(*args)
----------|--------------------------------|---------------------------
          |  def f(a, b):                  |  def f(a, b):
**kwargs  |      return a + b              |      return a + b
          |  def g(**kwargs):              |  kwargs = dict(a=1, b=2)
          |      return f(**kwargs)        |  f(**kwargs)
          |  g(a=1, b=2)                   |
-----------------------------------------------------------------------

Esto realmente solo sirve para resumir la respuesta de Lorin Hochstein pero me parece útil.

 8
Author: Brad Solomon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-02 01:15:43

Quiero dar un ejemplo que otros no han mencionado

* también puede desempaquetar un generador

Un ejemplo del documento Python3

x = [1, 2, 3]
y = [4, 5, 6]

unzip_x, unzip_y = zip(*zip(x, y))

Unzip_x será [1, 2, 3], unzip_y será [4, 5, 6]

El zip() recibe múltiples args iretables, y devuelve un generador.

zip(*zip(x,y)) -> zip((1, 4), (2, 5), (3, 6))
 7
Author: Lochu'an Chang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-08 16:50:20

En Python 3.5, también puede usar esta sintaxis en list, dict, tuple, y set muestra (también a veces llamados literales). Ver PEP 488: Generalizaciones Adicionales de Desembalaje.

>>> (0, *range(1, 4), 5, *range(6, 8))
(0, 1, 2, 3, 5, 6, 7)
>>> [0, *range(1, 4), 5, *range(6, 8)]
[0, 1, 2, 3, 5, 6, 7]
>>> {0, *range(1, 4), 5, *range(6, 8)}
{0, 1, 2, 3, 5, 6, 7}
>>> d = {'one': 1, 'two': 2, 'three': 3}
>>> e = {'six': 6, 'seven': 7}
>>> {'zero': 0, **d, 'five': 5, **e}
{'five': 5, 'seven': 7, 'two': 2, 'one': 1, 'three': 3, 'six': 6, 'zero': 0}

También permite descomprimir múltiples iterables en una sola llamada a función.

>>> range(*[1, 10], *[2])
range(1, 10, 2)

(Gracias a mgilson por el enlace del PEP.)

 6
Author: leewz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-08 22:29:06

¡Para aquellos de ustedes que aprenden con ejemplos!

  1. El propósito de * es darle la capacidad de definir una función que puede tomar un número arbitrario de argumentos proporcionados como una lista (por ejemplo, f(*myList)).
  2. El propósito de ** es darle la capacidad de alimentar los argumentos de una función proporcionando un diccionario (por ejemplo, f(**{'x' : 1, 'y' : 2})).

Vamos a mostrar esto definiendo una función que toma dos variables normalesx, y, y puede aceptar más argumentos como myArgs, y puede aceptar aún más argumentos como myKW. Más adelante, mostraremos cómo alimentar y usando myArgDict.

def f(x, y, *myArgs, **myKW):
    print("# x      = {}".format(x))
    print("# y      = {}".format(y))
    print("# myArgs = {}".format(myArgs))
    print("# myKW   = {}".format(myKW))
    print("# ----------------------------------------------------------------------")

# Define a list for demonstration purposes
myList    = ["Left", "Right", "Up", "Down"]
# Define a dictionary for demonstration purposes
myDict    = {"Wubba": "lubba", "Dub": "dub"}
# Define a dictionary to feed y
myArgDict = {'y': "Why?", 'y0': "Why not?", "q": "Here is a cue!"}

# The 1st elem of myList feeds y
f("myEx", *myList, **myDict)
# x      = myEx
# y      = Left
# myArgs = ('Right', 'Up', 'Down')
# myKW   = {'Wubba': 'lubba', 'Dub': 'dub'}
# ----------------------------------------------------------------------

# y is matched and fed first
# The rest of myArgDict becomes additional arguments feeding myKW
f("myEx", **myArgDict)
# x      = myEx
# y      = Why?
# myArgs = ()
# myKW   = {'y0': 'Why not?', 'q': 'Here is a cue!'}
# ----------------------------------------------------------------------

# The rest of myArgDict becomes additional arguments feeding myArgs
f("myEx", *myArgDict)
# x      = myEx
# y      = y
# myArgs = ('y0', 'q')
# myKW   = {}
# ----------------------------------------------------------------------

# Feed extra arguments manually and append even more from my list
f("myEx", 4, 42, 420, *myList, *myDict, **myDict)
# x      = myEx
# y      = 4
# myArgs = (42, 420, 'Left', 'Right', 'Up', 'Down', 'Wubba', 'Dub')
# myKW   = {'Wubba': 'lubba', 'Dub': 'dub'}
# ----------------------------------------------------------------------

# Without the stars, the entire provided list and dict become x, and y:
f(myList, myDict)
# x      = ['Left', 'Right', 'Up', 'Down']
# y      = {'Wubba': 'lubba', 'Dub': 'dub'}
# myArgs = ()
# myKW   = {}
# ----------------------------------------------------------------------

Advertencias

  1. ** está reservado exclusivamente para diccionarios.
  2. La asignación de argumentos no opcional ocurre primero.
  3. No se puede usar un argumento no opcional dos veces.
  4. Si es aplicable, ** debe venir después de *, siempre.
 5
Author: Miladiouss,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-13 19:43:14

Además de las llamadas a funciones, *args y **kwargs son útiles en las jerarquías de clases y también evitan tener que escribir el método __init__ en Python. Se puede ver un uso similar en frameworks como Django code.

Por ejemplo,

def __init__(self, *args, **kwargs):
    for attribute_name, value in zip(self._expected_attributes, args):
        setattr(self, attribute_name, value)
        if kwargs.has_key(attribute_name):
            kwargs.pop(attribute_name)

    for attribute_name in kwargs.viewkeys():
        setattr(self, attribute_name, kwargs[attribute_name])

Una subclase puede entonces ser

class RetailItem(Item):
    _expected_attributes = Item._expected_attributes + ['name', 'price', 'category', 'country_of_origin']

class FoodItem(RetailItem):
    _expected_attributes = RetailItem._expected_attributes +  ['expiry_date']

La subclase se instanciará como

food_item = FoodItem(name = 'Jam', 
                     price = 12.0, 
                     category = 'Foods', 
                     country_of_origin = 'US', 
                     expiry_date = datetime.datetime.now())

Además, una subclase con un nuevo atributo que solo tiene sentido para esa instancia de subclase puede llamar a la clase Base __init__ para descargar la configuración de atributos. Esto es hecho a través de * args y * * kwargs. kwargs se utiliza principalmente para que el código sea legible usando argumentos con nombre. Por ejemplo,

class ElectronicAccessories(RetailItem):
    _expected_attributes = RetailItem._expected_attributes +  ['specifications']
    # Depend on args and kwargs to populate the data as needed.
    def __init__(self, specifications = None, *args, **kwargs):
        self.specifications = specifications  # Rest of attributes will make sense to parent class.
        super(ElectronicAccessories, self).__init__(*args, **kwargs)

Que se puede instalar como

usb_key = ElectronicAccessories(name = 'Sandisk', 
                                price = '$6.00', 
                                category = 'Electronics',
                                country_of_origin = 'CN',
                                specifications = '4GB USB 2.0/USB 3.0')

El código completo es aquí

 4
Author: Harisankar Krishna Swamy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-21 09:02:49

Un buen ejemplo de usar ambos en una función es:

>>> def foo(*arg,**kwargs):
...     print arg
...     print kwargs
>>>
>>> a = (1, 2, 3)
>>> b = {'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(*a,**b)
(1, 2, 3)
{'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(a,**b) 
((1, 2, 3),)
{'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(a,b) 
((1, 2, 3), {'aa': 11, 'bb': 22})
{}
>>>
>>>
>>> foo(a,*b)
((1, 2, 3), 'aa', 'bb')
{}
 1
Author: amir jj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-26 12:48:05

Este ejemplo te ayudaría a recordar *args, **kwargs e incluso super y la herencia en Python a la vez.

class base(object):
    def __init__(self, base_param):
        self.base_param = base_param


class child1(base): # inherited from base class
    def __init__(self, child_param, *args) # *args for non-keyword args
        self.child_param = child_param
        super(child1, self).__init__(*args) # call __init__ of the base class and initialize it with a NON-KEYWORD arg

class child2(base):
    def __init__(self, child_param, **kwargs):
        self.child_param = child_param
        super(child2, self).__init__(**kwargs) # call __init__ of the base class and initialize it with a KEYWORD arg

c1 = child1(1,0)
c2 = child2(1,base_param=0)
print c1.base_param # 0
print c1.child_param # 1
print c2.base_param # 0
print c2.child_param # 1
 1
Author: thanhtang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-26 21:09:43

*args y **kwargs: le permiten pasar un número variable de argumentos a una función.

*args: se utiliza para enviar una lista de argumentos de longitud variable sin palabras clave a la función:

def args(normal_arg, *argv):
    print ("normal argument:",normal_arg)

    for arg in argv:
        print("Argument in list of arguments from *argv:", arg)

args('animals','fish','duck','bird')

Producirá:

normal argument: animals
Argument in list of arguments from *argv: fish
Argument in list of arguments from *argv: duck
Argument in list of arguments from *argv: bird

**kwargs*

**kwargs permite pasar longitud variable de argumentos con palabras clave a una función. Debe usar **kwargs si desea manejar argumentos con nombre en una función.

def who(**kwargs):
    if kwargs is not None:
        for key, value in kwargs.items():
            print ("Your %s is %s." %(key,value))

who (name="Nikola", last_name="Tesla", birthday = "7.10.1856", birthplace = "Croatia")  

Producirá:

Your name is Nikola.
Your last_name is Tesla.
Your birthday is 7.10.1856.
Your birthplace is Croatia.
 0
Author: Harvey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-01 13:29:58

* means receive variable arguments as list

** means receive variable arguments as dictionary

Se usa de la siguiente manera:

1) sencillo *

def foo(*args):
    for arg in args:
        print(arg)

foo("two", 3)

Salida:

two
3

2) Ahora **

def bar(**kwargs):
    for key in kwargs:
        print(key, kwargs[key])

bar(dic1="two", dic2=3)

Salida:

dic1 two
dic2 3
 0
Author: ishandutta2007,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-07 18:36:20
  • def foo(param1, *param2): es un método que puede aceptar un número arbitrario de valores para *param2,
  • def bar(param1, **param2): es un método que puede aceptar un número arbitrario de valores con claves para *param2
  • param1 es un parámetro simple.

Por ejemplo, la sintaxis para implementar varargs en Java es la siguiente:

accessModifier methodName(datatype… arg) {
    // method body
}
 0
Author: Premraj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-02 05:14:05

* args = * aList = todos los elementos de una lista

* * args = * * aDict = todos los elementos en un dict

 -1
Author: JawSaw,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-08 01:43:44