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




modulo (16)

También vale la pena señalar que puede usar * y ** al llamar a 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 teclas en mydict deben nombrarse 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'

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

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

Para aquellos de ustedes que aprenden con ejemplos!

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

Mostremos esto definiendo una función que toma dos variables normales x , y , y puede aceptar más argumentos como myArgs , y puede aceptar incluso más argumentos como myKW . Más adelante, le 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 los diccionarios.
  2. La asignación de argumentos no opcionales ocurre primero.
  3. No puede utilizar un argumento no opcional dos veces.
  4. Si corresponde, ** debe venir después de * , siempre.

El *args y **kwargs es un lenguaje común que permite que un número arbitrario de argumentos funcione como se describe en la sección sobre la definición de funciones en la documentación de Python.

Los *args te darán todos los parámetros de la 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

Los **kwargs le darán todos los argumentos de palabras clave, excepto los correspondientes 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 idiomas pueden combinarse con argumentos normales para permitir un conjunto de argumentos fijos y algunos variables:

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

Otro uso del lenguaje *l es desempaquetar 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 usar *l en el lado izquierdo de una asignación ( Desempaquetado 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]

También Python 3 agrega nueva semántica (refiérase a PEP 3102 ):

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

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


El solo * 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 adicionales nombrados. 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}

* y ** tienen un uso especial en la lista de argumentos de 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.


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

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

Así que ahora sabemos las definiciones de funciones con posicionales, así como los argumentos 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 la función

El uso del operador '*' y el operador '**' en la llamada de 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.

Así que recuerda

cuando se utiliza el operador '*' o '**' en una llamada a función -

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

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

Así que recuerda:

En una llamada de función, el '*' desempaqueta la estructura de datos de la tupla o lista en los argumentos posicionales o de palabras clave que debe recibir la definición de la función.

En una función, el '**' desempaqueta la estructura de datos del diccionario en los argumentos posicionales o de palabras clave que debe recibir 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, el '**' empaqueta argumentos de palabras clave en un diccionario.


* significa recibir argumentos variables como lista

** significa recibir argumentos variables como diccionario

Utilizado como el siguiente:

1) soltero *

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

Este ejemplo le ayudaría 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

¿Qué hacen los parámetros ** (estrella doble) 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 ( ** ).

Definiendo funciones

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

**kwargs permite cualquier número de argumentos de palabras clave opcionales (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 una 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 desde listas (o cualquier iterable) y dicts (o cualquier mapeo), respectivamente.

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

Por ejemplo, el rango de Python 2 no espera explícitamente *args , pero ya que 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 palabra clave solamente

Puede tener argumentos de palabra clave solo después de *args ; por ejemplo, aquí, kwarg2 debe proporcionar como un argumento de palabra clave, no de forma posicional:

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 solo para indicar que solo siguen los 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 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

Nuevamente, de manera más simple, aquí requerimos que kwarg se dé por nombre, no por posición:

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

En este ejemplo, vemos que si intentamos pasar kwarg posicional, 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 un argumento de palabra clave.

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

Demos compatibles con Python 2

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

Por lo general, usamos esto cuando no sabemos qué va a recibir nuestra función o cuántos argumentos podemos pasar, y en ocasiones, incluso al nombrar cada variable por separado, se volvería 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 usar y demuestra el comportamiento. Tenga en cuenta que el argumento b nombrado será consumido por el segundo argumento posicional anterior:

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 indica

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) 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, tal vez no estemos viendo la utilidad todavía. 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 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 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 *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 ajustada 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, que *args y **kwargs nos permiten hacer, reducimos las líneas de código, mejoramos la legibilidad y el mantenimiento, y tenemos ubicaciones canónicas únicas para la lógica de nuestro programa. Si necesitamos cambiar alguna parte de esta estructura, tenemos un lugar donde hacer cada cambio.


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

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


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. Uso similar puede verse 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])

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 tiene sentido solo para esa instancia de la subclase puede llamar a la clase Base __init__ para descargar la configuración de atributos. Esto se hace a través de * args y ** kwargs. Kwargs se usa principalmente para que el código sea legible usando argumentos nombrados. 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 insinuado 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á here


En Python 3.5, también puedes usar esta sintaxis en las pantallas list , dict , tuple y set (también a veces llamadas literales). Ver PEP 488: Generalizaciones de desempaque 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 desempaquetar 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).


Quiero dar un ejemplo que otros no han mencionado.

* También puede desempaquetar un generador.

Un ejemplo del documento de 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 archivo zip () recibe múltiples argumentos irritables y devuelve un generador.

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

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

La respuesta más corta probablemente sería "la definición es la ejecución", por lo tanto, todo el argumento no tiene sentido estricto. Como un ejemplo más artificial, puedes citar esto:

def a(): return []

def b(x=a()):
    print x

Esperemos que sea suficiente para demostrar que no ejecutar las expresiones de argumento predeterminadas en el momento de la ejecución de la defdeclaración no es fácil o no tiene sentido, o ambos.

Sin embargo, estoy de acuerdo en que es un problema cuando intentas usar constructores predeterminados.





python syntax parameter-passing identifier kwargs