precedencia operadores operador logicos python syntax parameter-passing identifier kwargs

python - operadores - ¿Qué significa el operador estrella?



operadores python (5)

En una llamada de función, la estrella única convierte una lista en argumentos separados (por ejemplo, zip(*x) es lo mismo que zip(x1,x2,x3) si x=[x1,x2,x3] ) y la estrella doble convierte un diccionario en argumentos de palabras clave separadas (por ejemplo, f(**k) es lo mismo que f(x=my_x, y=my_y) si k = {''x'':my_x, ''y'':my_y} .

En la definición de una función, es al revés: la estrella simple convierte un número arbitrario de argumentos en una lista, y el doble inicio convierte un número arbitrario de argumentos de palabras clave en un diccionario. Por ejemplo, def foo(*x) significa "foo toma un número arbitrario de argumentos y serán accesibles a través de la lista x (es decir, si el usuario llama a foo(1,2,3) , x será [1,2,3] ) "y la def bar(**k) significa" la barra toma un número arbitrario de argumentos de palabras clave y serán accesibles a través del diccionario k (es decir, si el usuario llama a la bar(x=42, y=23) , k será {''x'': 42, ''y'': 23} ) ".

¿Qué significa el operador * en Python, como en el código como zip(*x) o f(**k) ?

  1. ¿Cómo se maneja internamente en el intérprete?
  2. ¿Afecta en absoluto al rendimiento? ¿Es rápido o lento?
  3. ¿Cuándo es útil y cuándo no?
  4. ¿Debería usarse en una declaración de función o en una llamada?

Encuentro esto particularmente útil cuando quiere "almacenar" una llamada de función.

Por ejemplo, supongamos que tengo algunas pruebas unitarias para una función ''agregar'':

def add(a, b): return a + b tests = { (1,4):5, (0, 0):0, (-1, 3):3 } for test, result in tests.items(): print ''test: adding'', test, ''=='', result, ''---'', add(*test) == result

No hay otra manera de llamar a agregar, aparte de hacer manualmente algo como agregar (prueba [0], prueba [1]), que es feo. Además, si hay un número variable de variables, el código podría ser bastante feo con todas las sentencias if que necesitarías.

Otro lugar en el que es útil es para definir objetos de Factory (objetos que crean objetos para usted). Supongamos que tienes alguna clase de Factory, que hace objetos de Car y los devuelve. Podría hacerlo para que myFactory.make_car (''red'', ''bmw'', ''335ix'') cree Car (''red'', ''bmw'', ''335ix''), y luego lo devuelva.

def make_car(*args): return Car(*args)

Esto también es útil cuando desea llamar al constructor de una superclase.


La estrella única * desempaqueta la secuencia / colección en argumentos posicionales, por lo que puede hacer esto:

def sum(a, b): return a + b values = (1, 2) s = sum(*values)

Esto desempaquetará la tupla para que realmente se ejecute como:

s = sum(1, 2)

La estrella doble ** hace lo mismo, solo usa un diccionario y, por lo tanto, los argumentos con nombre:

values = { ''a'': 1, ''b'': 2 } s = sum(**values)

También puedes combinar:

def sum(a, b, c, d): return a + b + c + d values1 = (1, 2) values2 = { ''c'': 10, ''d'': 15 } s = sum(*values1, **values2)

se ejecutará como:

s = sum(1, 2, c=10, d=15)

Consulte también la sección 4.7.4 - Desembalaje de listas de argumentos de la documentación de Python.

Además, puede definir funciones para tomar los argumentos *x y **y , esto permite que una función acepte cualquier número de argumentos posicionales y / o nombrados que no estén específicamente nombrados en la declaración.

Ejemplo:

def sum(*values): s = 0 for v in values: s = s + v return s s = sum(1, 2, 3, 4, 5)

o con ** :

def get_a(**values): return values[''a''] s = get_a(a=1, b=2) # returns 1

Esto puede permitirle especificar un gran número de parámetros opcionales sin tener que declararlos.

Y de nuevo, puedes combinar:

def sum(*values, **options): s = 0 for i in values: s = s + i if "neg" in options: if options["neg"]: s = -s return s s = sum(1, 2, 3, 4, 5) # returns 15 s = sum(1, 2, 3, 4, 5, neg=True) # returns -15 s = sum(1, 2, 3, 4, 5, neg=False) # returns 15


Se llama la sintaxis de llamada extendida. De la documentation :

Si la sintaxis * expresión aparece en la llamada de función, la expresión debe evaluar una secuencia. Los elementos de esta secuencia se tratan como si fueran argumentos posicionales adicionales; si hay argumentos posicionales x1, ..., xN, y la expresión se evalúa como una secuencia y1, ..., yM, esto es equivalente a una llamada con M + N argumentos posicionales x1, ..., xN, y1,. .., yM.

y:

Si la expresión de la sintaxis ** aparece en la llamada a la función, la expresión debe evaluar una asignación, cuyo contenido se trata como argumentos de palabras clave adicionales. En el caso de que aparezca una palabra clave en ambas expresiones y como un argumento de palabra clave explícito, se genera una excepción TypeError.


Un pequeño punto: estos no son operadores. Los operadores se usan en expresiones para crear nuevos valores a partir de valores existentes (1 + 2 se convierte en 3, por ejemplo. Los * y ** aquí son parte de la sintaxis de las declaraciones de funciones y las llamadas.