¿Asterisco desnudo en los parámetros de la función?

5 minutos de lectura

Avatar de usuario de Eric
eric

¿Qué hace un asterisco desnudo en los parámetros de una función?

Cuando miré a la módulo de salmueraVeo esto:

pickle.dump(obj, file, protocol=None, *, fix_imports=True)

Conozco asteriscos simples y dobles que preceden a los parámetros (para un número variable de parámetros), pero esto no precede a nada. Y estoy bastante seguro de que esto no tiene nada que ver con el pepinillo. Eso es probablemente sólo un ejemplo de que esto suceda. Solo aprendí su nombre cuando le envié esto al intérprete:

>>> def func(*):
...     pass
...
  File "<stdin>", line 1
SyntaxError: named arguments must follow bare *

Si importa, estoy en python 3.3.0.

  • Relacionado: ¿Barra diagonal desnuda en la definición de función de Python?

    – Tom Hale

    9 de junio de 2019 a las 13:07

  • para obtener una explicación con un ejemplo de código, consulte: stackoverflow.com/a/14298976/1601580

    –Charlie Parker

    29 oct 2021 a las 18:31

Avatar de usuario de Kimvais
kimvais

Desnudo * se usa para obligar a la persona que llama a usar argumentos con nombre, por lo que no puede definir una función con * como argumento cuando no tiene argumentos de palabras clave siguientes.

Ver esta respuesta o Documentación de Python 3 para más detalles.

  • para obtener una explicación con un ejemplo de código, consulte: stackoverflow.com/a/14298976/1601580

    –Charlie Parker

    29 oct 2021 a las 18:31

Avatar de usuario de Anshul Goyal
anshul goyal

Si bien la respuesta original responde la pregunta por completo, solo agrega un poco de información relacionada. El comportamiento del asterisco simple se deriva de PEP-3102. Citando la sección relacionada:

The second syntactical change is to allow the argument name to
be omitted for a varargs argument. The meaning of this is to
allow for keyword-only arguments for functions that would not
otherwise take a varargs argument:

    def compare(a, b, *, key=None):
        ...

En inglés simple, significa que para pasar el valor de la clave, deberá pasarlo explícitamente como key="value".

  • Oh, eso hace las cosas mucho más claras. Entonces, en realidad, tener un argumento * es como tener un argumento args *, pero como no lo ha nombrado, su único efecto probablemente sea engullir silenciosamente todos los argumentos posicionales restantes, para obligar a los argumentos restantes a ser palabra clave -solo.

    – Esteban

    25 de abril de 2018 a las 17:19

  • @Stephen Yo también pensé originalmente, el efecto de desnudo * es engullir los argumentos posicionales restantes, pero ese no es el caso. Pasar argumentos posicionales adicionales a los esperados por la función da un error de este tipo: foo() takes exactly 1 positional argument (2 given)

    – Ajay M

    27 de mayo de 2018 a las 1:49

  • Agregaría el ejemplo de PEP antes de “Como un atajo conveniente, podemos simplemente omitir el nombre ‘ignorar’, que significa ‘no permitir ningún argumento posicional más allá de este punto'”. Ese ejemplo equivalente dejó claro y concreto lo que hace.

    – Horror Vacui

    31 de agosto de 2020 a las 3:32

avatar de usuario de laycat
laico

def func(*, a, b):
    print(a)
    print(b)

func("gg") # TypeError: func() takes 0 positional arguments but 1 was given
func(a="gg") # TypeError: func() missing 1 required keyword-only argument: 'b'
func(a="aa", b="bb", c="cc") # TypeError: func() got an unexpected keyword argument 'c'
func(a="aa", b="bb", "cc") # SyntaxError: positional argument follows keyword argument
func(a="aa", b="bb") # aa, bb

el ejemplo anterior con **kwargs

def func(*, a, b, **kwargs):
    print(a)
    print(b)
    print(kwargs)

func(a="aa",b="bb", c="cc") # aa, bb, {'c': 'cc'}

Semánticamente, significa que los argumentos que le siguen son solo palabras clave, por lo que obtendrá un error si intenta proporcionar un argumento sin especificar su nombre. Por ejemplo:

>>> def f(a, *, b):
...     return a + b
...
>>> f(1, 2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f() takes 1 positional argument but 2 were given
>>> f(1, b=2)
3

Pragmáticamente, significa que debe llamar a la función con un argumento de palabra clave. Por lo general, se hace cuando sería difícil comprender el propósito del argumento sin la pista dada por el nombre del argumento.

Comparar por ejemplo sorted(nums, reverse=True) vs. si escribiste sorted(nums, True). Este último sería mucho menos legible, por lo que los desarrolladores de Python optaron por hacer que lo escribieras de la forma anterior.

Supongamos que tiene la función:

def sum(a,key=5):
    return a + key 

Puede llamar a esta función de 2 maneras:

sum(1,2) o sum(1,key=2)

Supongamos que desea la función sum para ser llamado solo usando argumentos de palabras clave.

Añades * a la lista de parámetros de función para marcar el final de los argumentos posicionales.

Entonces función definida como:

def sum(a,*,key=5):
    return a + key 

solo se puede llamar usando sum(1,key=2)

Avatar de usuario de Adrian W
Adrián W.

He encontrado que el siguiente enlace es muy útil para explicar *, *args y **kwargs:

https://pythontips.com/2013/08/04/args-and-kwargs-in-python-explained/

Esencialmente, además de las respuestas anteriores, aprendí del sitio anterior (crédito: https://pythontips.com/author/yasoob008/) el seguimiento:

Con la función de demostración definida primero a continuación, hay dos ejemplos, uno con *args y uno con **kwargs

def test_args_kwargs(arg1, arg2, arg3):
    print "arg1:", arg1
    print "arg2:", arg2
    print "arg3:", arg3

# first with *args
>>> args = ("two", 3,5)
>>> test_args_kwargs(*args)
arg1: two
arg2: 3
arg3: 5

# now with **kwargs:
>>> kwargs = {"arg3": 3, "arg2": "two","arg1":5}
>>> test_args_kwargs(**kwargs)
arg1: 5
arg2: two
arg3: 3

Asi que *args le permite construir dinámicamente una lista de argumentos que se tomarán en el orden en que se alimentan, mientras que **kwargs puede habilitar el paso de argumentos NOMBRADOS, y NOMBRE puede procesarlos en consecuencia (independientemente del orden en que se introduzcan).

El sitio continúa, señalando que el orden correcto de los argumentos debe ser:

some_func(fargs,*args,**kwargs)

¿Ha sido útil esta solución?