logicos - precedencia de operadores en python




¿Qué significa el operador estrella? (4)

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

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} ) ".


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.


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.





kwargs