Pregunta

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

def foo(param1, *param2):
def bar(param1, **param2):
¿Fue útil?

Solución

El *args y **kwargs es un modismo común para permitir un número arbitrario de argumentos para 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é todoargumentos de palabras clave excepto los correspondientes a un parámetro formal como 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 de la *l modismo es descomprimir listas de argumentos al llamar 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 utilizar *l en el lado izquierdo de una tarea (Desembalaje iterable extendido), aunque proporciona 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 nueva semántica (consulte PEP 3102):

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

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

Otros consejos

También vale la pena señalar que puedes usar * y ** al llamar funciones también.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 llaves en mydict tienen que ser nombrados exactamente como los parámetros de la 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'

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}

Que hace ** (doble estrella) y * (estrella) hacer para los parámetros

Ellos permiten funciones por definir para aceptar y para usuarios para pasar cualquier número de argumentos, posicionales (*) y palabra clave (**).

Definición de funciones

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

**kwargs permite 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, args y kwargs son nombres estándar.

Expansión, pasando cualquier número de argumentos.

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

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

Por ejemplo, xrange de Python 2 no espera explícitamente *args, pero como toma 3 números 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 de palabras clave

Tu puedes tener argumentos solo de palabras clave después de la *args - por ejemplo, aquí, kwarg2 debe darse como 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 utilizar por sí solo para indicar que solo siguen argumentos de palabras clave, sin permitir argumentos posicionales ilimitados.

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

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

>>> 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 kwarg debe darse por nombre, no por posición:

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 kwarg parámetro como argumento de palabra clave.

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

Demostraciones compatibles con Python 2

*args (normalmente dicho "star-args") y **kwargs (Las estrellas pueden estar implícitas al decir "kwargs", pero sea explícito con "kwargs de doble estrella") son modismos comunes de Python para usar el * y ** notación.Estos nombres de variables específicos no son obligatorios (p. ej.podrías usar *foos y **bars), pero una desviación de la convención probablemente enfurezca a sus compañeros programadores de Python.

Normalmente los usamos cuando no sabemos qué va a recibir nuestra función o cuántos argumentos podemos pasar y, a veces, incluso cuando nombrar cada variable por separado sería muy complicado y redundante (pero este es un caso en el que normalmente es explícito). mejor que implícito).

Ejemplo 1

La siguiente función describe cómo se pueden utilizar y demuestra el comportamiento.Tenga en cuenta el nombre b El argumento 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 online 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 simplemente 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, tal vez aún no estemos viendo la utilidad.Entonces imagine que tiene varias funciones con código redundante antes y/o después del código diferenciador.Las siguientes funciones nombradas 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 siguiente ejemplo demuestra cómo *args y **kwargs puede 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 empaquetada se puede escribir de manera mucho más concisa, ya que hemos eliminado 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, que *args y **kwargs nos permite hacer, reducimos líneas de código, mejoramos la legibilidad y el 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 para realizar cada cambio.

Primero comprendamos 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 puedes 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 puedes 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
---------------------------------

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 el operador '**' en Llamada de función.

Vayamos directamente a un ejemplo y luego analicé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.

Así que recuerda

cuando el operador '*' o '**' se utiliza en un Llamada de 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 los argumentos necesarios para la definición de la función.

Ahora estudiemos el uso del operador '*' en 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 función definició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 función definición El operador '**' empaqueta los argumentos recibidos en un diccionario.

Así que recuerda:

en un Llamada de función el '*' desempaqueta Estructura de datos de tupla o lista en argumentos posicionales o de palabras clave que se recibirán mediante la definición de función.

en un Llamada de función el '**' desempaqueta estructura de datos del diccionario en argumentos posicionales o de palabras clave que se recibirán mediante la definición de la función.

en un definición de función el '*' paquetes argumentos posicionales en una tupla.

en un definición de función el '**' paquetes argumentos de palabras clave en un diccionario.

* 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

Si bien los usos de los operadores star/splat han sido expandido en Python 3, me gusta la siguiente tabla en lo que se refiere al uso de estos operadores con funciones.Los operadores splat se pueden usar tanto dentro de la función construcción y en la función llamar:

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

En realidad esto sólo sirve para resumir la visión de Lorin Hochstein. respuesta pero lo encuentro útil.

¡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 (p. ej. f(*myList) ).
  2. El propósito de ** es darle la posibilidad de alimentar los argumentos de una función proporcionando un diccionario (p. ej. f(**{'x' : 1, 'y' : 2}) ).

Demostremos esto definiendo una función que toma dos variables normales. x, 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 opcionales ocurre primero.
  3. No se puede utilizar un argumento no opcional dos veces.
  4. Si es aplicable, ** debe venir después *, siempre.

De la documentación de Python:

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

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

En Python 3.5, también puedes usar esta sintaxis en list, dict, tuple, y set pantallas (también llamadas a veces literales).Ver PEP 488:Generalizaciones de desembalaje adicionales.

>>> (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 varios iterables en una sola llamada de función.

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

(Gracias a mgilson por el enlace PEP).

Quiero dar un ejemplo que otros no han mencionado.

* también puede desempacar 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]

zip() recibe múltiples argumentos irtables y devuelve un generador.

zip(*zip(x,y)) -> zip((1, 4), (2, 5), (3, 6))

Además de las llamadas a funciones, *args y **kwargs son útiles en jerarquías de clases y también evitan tener que escribir __init__ método en Python.Se puede observar 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 será instanciada 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 sólo tiene sentido 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 utiliza principalmente para que el código sea legible utilizando 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 puede ser instalado 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í

* significa recibir argumentos variables como lista

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

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')
{}

Este ejemplo te ayudará a recordar *args, **kwargs e incluso super y 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

TL;DR

Empaqueta los argumentos pasados ​​a la función en list y dict respectivamente dentro del cuerpo de la función.Cuando defines 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 palabras clave.Los argumentos que no son palabras clave se empaquetan en una lista llamada args dentro del cuerpo de la función y los argumentos de las palabras clave se empaquetan en un dict llamado kwds dentro 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, args que es una lista que tiene valor ["this", "is a list of", "non-keyword", "arguments"] y kwds el cual es un dict teniendo valor {"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

puedes llamarlo descomprimiendo iterables o asignaciones que tengas 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)

*args y **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*

**kwargs le permite pasar argumentos de longitud variable con palabras clave a una función.Deberías 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.
  • 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 de la siguiente manera:

accessModifier methodName(datatype… arg) {
    // method body
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top