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

2792

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

def foo(param1, *param2):
def bar(param1, **param2):
3
  • 9
    ver también stackoverflow.com/questions/6967632/…
    Aaron Hall
    1/03/18 a las 20:53
  • 81
    Esta pregunta es un objetivo duplicado muy popular, pero desafortunadamente a menudo se usa incorrectamente. Tenga en cuenta que esta pregunta se refiere a la definición de funciones con varargs ( def func(*args)). Para una pregunta que pregunte qué significa en las llamadas a funciones ( func(*[1,2])), consulte aquí . Para obtener una pregunta sobre cómo descomprimir las listas de argumentos, consulte aquí . Para obtener una pregunta sobre los *significados en literales ( [*[1, 2]]), consulte aquí . 22/03/19 a las 20:40
  • 1
    @ Aran-Fey: Creo que un mejor objetivo para "qué significa en las llamadas de función" es ¿Qué significa el operador estrella en una llamada de función? . Su enlace realmente no aborda el uso de **, y es una pregunta mucho más específica. 10 de diciembre de 2020 a las 5:55
2690

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

Le *argsdará todos los parámetros de función como una tupla :

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

foo(1)
# 1

foo(1,2,3)
# 1
# 2
# 3

El **kwargsle dará todos los argumentos de palabras clave excepto los correspondientes a un parámetro formal como un diccionario.

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

bar(name='one', age=27)
# name one
# age 27

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

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

También es posible usar esto al revés:

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

obj = {'b':10, 'c':'lee'}

foo(100,**obj)
# 100 10 lee

Otro uso del *lmodismo es descomprimir listas de argumentos cuando se llama a una función.

def foo(bar, lee):
    print(bar, lee)

l = [1,2]

foo(*l)
# 1 2

En Python 3 es posible usar *len el lado izquierdo de una tarea ( Desempaquetado iterable extendido ), 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]

Además, Python 3 agrega una nueva semántica (consulte PEP 3102 ):

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

Dicha función acepta solo 3 argumentos posicionales, y todo lo que sigue *solo se puede pasar como argumentos de palabra clave.

Nota:

  • Un Python dict, usado semánticamente para pasar argumentos de palabras clave, se ordena arbitrariamente. Sin embargo, en Python 3.6, se garantiza que los argumentos de palabras clave recordarán el orden de inserción.
  • "El orden de los elementos en **kwargsahora corresponde al orden en el que se pasaron los argumentos de palabras clave a la función". - Novedades de Python 3.6
  • De hecho, todos los dictados en CPython 3.6 recordarán el orden de inserción como un detalle de implementación, esto se convierte en estándar en Python 3.7.
0
712

También vale la pena señalar que también puede usar *y **al llamar a funciones. Este es un atajo que le permite pasar múltiples 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 teclas mydictdeben tener el mismo nombre que los parámetros de función foo. De lo contrario, arrojará 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'
0
192

El único * 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 hay una secuencia que contiene 2-5.

El doble ** significa que puede haber cualquier número de parámetros con nombre adicionales. bar()se puede invocar como bar(1, a=2, b=3). En el cuerpo de bar () param2 hay 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}
0
172

What does ** (double star) and * (star) do for parameters?

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

Definición de funciones

*argspermite cualquier número de argumentos posicionales opcionales (parámetros), que serán asignados a una tupla nombrada args.

**kwargspermite cualquier número de argumentos de palabras clave opcionales (parámetros), que estarán en un dictado 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 argsy kwargssean nombres estándar.

Expansión, pasando cualquier número de argumentos

También puede usar *argsy **kwargspara pasar parámetros de listas (o cualquier iterable) y dictados (o cualquier mapeo), respectivamente.

La función que recibe los parámetros no tiene por qué saber que se están expandiendo.

Por ejemplo, el rango x 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: Definición de funciones con argumentos de solo palabras clave

Puede tener argumentos de solo palabras clave después de *args, por ejemplo, aquí, kwarg2debe 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'})

Además, *se puede usar por sí mismo para indicar que siguen solo argumentos de palabras clave, sin permitir argumentos posicionales ilimitados.

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

Aquí, kwarg2nuevamente debe haber un argumento de palabra clave con nombre explícito:

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

Nuevamente, de manera más simple, aquí requerimos kwargque se nos dé por nombre, no posicionalmente:

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

En este ejemplo, vemos que si intentamos pasar kwargposicionalmente, 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 kwargparámetro como un argumento de palabra clave.

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

Demostraciones compatibles con Python 2

*args(normalmente se dice "star-args") y **kwargs(las estrellas pueden estar implícitas diciendo "kwargs", pero sea explícito con "kwargs de doble estrella") son modismos comunes de Python para usar la notación *y **. Estos nombres de variables específicos no son obligatorios (por ejemplo, podría usar *foosy **bars), pero es probable que una desviación de la convención enfurezca a sus compañeros programadores de Python.

Por lo general, los usamos 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 vuelve muy complicado y redundante (pero este es un caso en el que generalmente es explícito mejor que implícito).

Ejemplo 1

La siguiente función describe cómo se pueden utilizar y demuestra su comportamiento. Tenga en cuenta que el bargumento con nombre será consumido por el segundo argumento posicional antes:

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) huellas dactilares:

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

Bien, quizás todavía no estemos viendo la utilidad. Así que imagina que tienes varias funciones con código redundante antes y / o después del código diferenciador. Las siguientes funciones con nombre son solo pseudocódigo con 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

Es posible que podamos manejar esto de manera diferente, pero ciertamente podemos extraer la redundancia con un decorador, por lo que nuestro ejemplo a continuación demuestra cómo *argsy **kwargspuede ser muy útil:

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 de manera mucho más sucinta, 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 *argsy **kwargsnos permite hacer, reducimos las líneas de código, mejoramos la legibilidad y la capacidad de mantenimiento, y tenemos ubicaciones canónicas únicas para la lógica en nuestro programa. Si necesitamos cambiar alguna parte de esta estructura, tenemos un lugar en el que realizar cada cambio.

0
55

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

Entonces esta es una definición de función con argumentos posicionales. También puede llamarlo con palabras clave / argumentos con 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 palabras 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
-------------------------

También puede llamar a esta función con argumentos posicionales:

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 conocemos las 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 utilizar en 2 áreas:

a) llamada de función

b) definición de función

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

Vayamos directamente a un ejemplo y luego lo comentemos.

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.

Así que recuerda

cuando el operador '*' o '**' se usa en una llamada de función -

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

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

Ahora estudiemos el uso del operador '*' en la definición de 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 la definición de función, el operador '*' empaqueta los argumentos recibidos en una tupla.

Ahora veamos un ejemplo de '**' usado en la definición de 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 la definición de función El operador '**' empaqueta los argumentos recibidos en un diccionario.

Así que recuerda:

En una llamada de 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 de función, '**' 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 los argumentos posicionales en una tupla.

En una definición de función, '**' empaqueta argumentos de palabras clave en un diccionario.

0
39

Esta tabla es útil para usar *y **en la construcción de funciones y llamadas a funciones :

            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 lo encuentro útil.

De manera relacionada: los usos de los operadores estrella / splat se han ampliado en Python 3

0
23

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

20

¡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 brindarle la capacidad de alimentar los argumentos de una función al proporcionar un diccionario (por ejemplo f(**{'x' : 1, 'y' : 2})).

Vamos a mostrar esto definiendo una función que toma dos variables normales x, yy puede aceptar más argumentos myArgs, y puede aceptar aún más argumentos myKW. Más adelante, mostraremos cómo alimentar yusando 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 opcionales ocurre primero.
  3. No puede usar un argumento no opcional dos veces.
  4. Si aplica, **debe venir después *, siempre.
dieciséis

TL; DR

A continuación se muestran 6 casos de uso diferentes para *y **en la programación de Python:

  1. Para aceptar cualquier número de argumentos posicionales usando *args:, def foo(*args): pass aquí fooacepta cualquier número de argumentos posicionales, es decir, las siguientes llamadas son válidas foo(1),foo(1, 'bar')
  2. Para aceptar cualquier número de argumentos de palabra clave usando **kwargs:, def foo(**kwargs): pass aquí 'foo' acepta cualquier número de argumentos de palabra clave, es decir, las siguientes llamadas son válidas foo(name='Tom'),foo(name='Tom', age=33)
  3. Para aceptar cualquier número de argumentos posicionales y de palabras clave usando *args, **kwargs:, def foo(*args, **kwargs): pass aquí fooacepta cualquier número de argumentos posicionales y de palabras clave, es decir, las siguientes llamadas son válidas foo(1,name='Tom'),foo(1, 'bar', name='Tom', age=33)
  4. Para hacer cumplir los argumentos de solo palabras clave usando *:, def foo(pos1, pos2, *, kwarg1): pass aquí *significa que foo solo acepta argumentos de palabras clave después de pos2, por lo tanto, foo(1, 2, 3)genera TypeError pero foo(1, 2, kwarg1=3)está bien.
  5. Para no expresar más interés en más argumentos posicionales usando *_(Nota: esto es solo una convención): def foo(bar, baz, *_): pass significa (por convención) foosolo usa bary bazargumentos en su funcionamiento e ignorará otros.
  6. Para no expresar más interés en más argumentos de palabras clave usando \**_(Nota: esto es solo una convención): def foo(bar, baz, **_): pass significa (por convención) foosolo usa bary bazargumentos en su funcionamiento e ignorará otros.

BONIFICACIÓN: Desde Python 3.8 en adelante, se puede usar /en la definición de funciones para hacer cumplir los parámetros posicionales solamente. En el siguiente ejemplo, los parámetros ayb son solo posicionales , mientras que c o d pueden ser posicionales o palabras clave, yeof deben ser palabras clave:

def f(a, b, /, c, d, *, e, f):
    pass
15

De la documentación de Python:

If there are more positional arguments than there are formal parameter slots, a TypeError exception is raised, unless a formal parameter using the syntax "*identifier" is present; in this case, that formal parameter receives a tuple containing the excess positional arguments (or an empty tuple if there were no excess positional arguments).

If any keyword argument does not correspond to a formal parameter name, a TypeError exception is raised, unless a formal parameter using the syntax "**identifier" is present; in this case, that formal parameter receives a dictionary containing the excess keyword arguments (using the keywords as keys and the argument values as corresponding values), or a (new) empty dictionary if there were no excess keyword arguments.

14

* significa recibir argumentos variables como tupla

** significa recibir argumentos variables como diccionario

Usado como el siguiente:

1) soltero *

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

foo("two", 3)

Producción:

two
3

2) ahora **

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

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

Producción:

dic1 two
dic2 3
11

En Python 3.5, también se puede utilizar esta sintaxis en list, dict, tuple, y setmuestra (también llamado a veces literales). Consulte PEP 488: Generalizaciones adicionales de desempaquetado .

>>> (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 de función.

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

(Gracias a mgilson por el enlace PEP).

1
  • 1
    No estoy seguro de que esto sea una violación de "solo hay una forma de hacerlo". No hay otra forma de inicializar una lista / tupla a partir de múltiples iterables: actualmente necesita encadenarlos en un solo iterable, lo que no siempre es conveniente. Puede leer sobre lo racional en PEP-0448 . Además, esta no es una característica de python3.x, es una característica de python3.5 + :-).
    mgilson
    8 dic 2015 a las 21:41
9

Quiero dar un ejemplo que otros no hayan mencionado.

* también puede desembalar 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 argumentos iretables y devuelve un generador.

zip(*zip(x,y)) -> zip((1, 4), (2, 5), (3, 6))
1
  • 1
    unzip_x será (1, 2, 3)no [1, 2, 3]. Lo mismo ocurre con unzip_y 24 nov.20 a las 10:09
7

Sobre la base de la respuesta de Nickd ...

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


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


def three_params(param1, *param2, **param3):
    print(param1)
    print(param2)
    print(param3)


foo(1, 2, 3, 4, 5)
print("\n")
bar(1, a=2, b=3)
print("\n")
three_params(1, 2, 3, 4, s=5)

Producción:

1
(2, 3, 4, 5)

1
{'a': 2, 'b': 3}

1
(2, 3, 4)
{'s': 5}

Básicamente, cualquier número de argumentos posicionales puede usar * args y cualquier argumento con nombre (o kwargs, también conocido como argumentos de palabra clave) puede usar ** kwargs.

7

TL; DR

Empaqueta los argumentos pasados ​​a la función dentro listy, dictrespectivamente, dentro del cuerpo de la función. Cuando define una firma de función como esta:

def func(*args, **kwds):
    # do stuff

se puede llamar con cualquier número de argumentos y argumentos de palabra clave. Los argumentos que no son palabras clave se empaquetan en una lista llamada argsdentro del cuerpo de la función y los argumentos de la palabra clave se empaquetan en un diccionario llamado kwdsdentro del cuerpo de la función.

func("this", "is a list of", "non-keyowrd", "arguments", keyword="ligma", options=[1,2,3])

ahora dentro del cuerpo de la función, cuando se llama a la función, hay dos variables locales, argsque es una lista que tiene un valor ["this", "is a list of", "non-keyword", "arguments"]y kwdsque es un dictvalor que tiene{"keyword" : "ligma", "options" : [1,2,3]}


Esto también funciona a la inversa, es decir, desde el lado de la persona que llama. por ejemplo, si tiene una función definida como:

def f(a, b, c, d=1, e=10):
    # do stuff

puede llamarlo desempaquetando iterables o asignaciones que tiene en el alcance de la llamada:

iterable = [1, 20, 500]
mapping = {"d" : 100, "e": 3}
f(*iterable, **mapping)
# That call is equivalent to
f(1, 20, 500, d=100, e=3)
6

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 __init__métodos en Python. Se puede ver un uso similar en marcos como el código Django.

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])

Entonces, una subclase puede 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 luego se instancia 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 tiene sentido solo para esa instancia de subclase puede llamar a la clase Base __init__para descargar la configuración de atributos. Esto se hace mediante * args y ** kwargs. kwargs se usa 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 está aquí

0
3

*argsy **kwargs: le permite 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*

**kwargsle permite pasar argumentos de longitud variable con palabras clave a una función. Debe usar **kwargssi 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.
3

Dada una función que tiene 3 elementos como argumento

sum = lambda x, y, z: x + y + z
sum(1,2,3) # sum 3 items

sum([1,2,3]) # error, needs 3 items, not 1 list

x = [1,2,3][0]
y = [1,2,3][1]
z = [1,2,3][2]
sum(x,y,z) # ok

sum(*[1,2,3]) # ok, 1 list becomes 3 items

Imagina este juguete con una bolsa de un triángulo, un círculo y un rectángulo. Esa bolsa no encaja directamente. Necesita desempacar la bolsa para tomar esos 3 artículos y ahora encajan. El operador de Python * realiza este proceso de descompresión.

ingrese la descripción de la imagen aquí

2

Un buen ejemplo del uso de 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')
{}
2

Este ejemplo podría ayudarle a recordar *args, **kwargse incluso supery 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

Contexto

  • Python 3.x
  • desembalar con **
  • usar con formato de cadena

Usar con formato de cadena

Además de las respuestas en este hilo, aquí hay otro detalle que no se mencionó en otra parte. Esto amplía la respuesta de Brad Solomon.

Desembalar con **también es útil cuando se usa Python str.format.

Esto es algo similar a lo que puede hacer con python f-strings f-string pero con la sobrecarga adicional de declarar un dict para contener las variables (f-string no requiere un dict).

Ejemplo rápido

  ## init vars
  ddvars = dict()
  ddcalc = dict()
  pass
  ddvars['fname']     = 'Huomer'
  ddvars['lname']     = 'Huimpson'
  ddvars['motto']     = 'I love donuts!'
  ddvars['age']       = 33
  pass
  ddcalc['ydiff']     = 5
  ddcalc['ycalc']     = ddvars['age'] + ddcalc['ydiff']
  pass
  vdemo = []

  ## ********************
  ## single unpack supported in py 2.7
  vdemo.append('''
  Hello {fname} {lname}!

  Today you are {age} years old!

  We love your motto "{motto}" and we agree with you!
  '''.format(**ddvars)) 
  pass

  ## ********************
  ## multiple unpack supported in py 3.x
  vdemo.append('''
  Hello {fname} {lname}!

  In {ydiff} years you will be {ycalc} years old!
  '''.format(**ddvars,**ddcalc)) 
  pass

  ## ********************
  print(vdemo[-1])

0

* args (o * cualquiera) significa todos los parámetros

def any_param(*param):
    pass

any_param(1)
any_param(1,1)
any_param(1,1,1)
any_param(1,...)

AVISO : no puede pasar parámetros a * args

def any_param(*param):
    pass

any_param() # will work correct

El * args está en tipo tupla

def any_param(*param):
    return type(param)

any_param(1) #tuple
any_param() # tuple

para acceder a los elementos, no utilice *

def any(*param):
    param[0] # correct

def any(*param):
    *param[0] # incorrect

El ** kwd

** kwd o ** any Este es un tipo de dictado

def func(**any):
    return type(any) # dict

def func(**any):
    return any

func(width="10",height="20") # {width="10",height="20")


-1
  • 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
}