Estoy viendo un código de Python que usó el @
símbolo, pero no tengo idea de lo que hace. Tampoco sé qué buscar, ya que buscar documentos de Python o Google no devuelve resultados relevantes cuando @
se incluye el símbolo.
python
syntax
python-decorators
AJ00200
fuente
fuente
Ejemplo
Esto muestra que el
function
/method
/class
que estás definiendo después de un decorador se pasa básicamente como /argument
alfunction
/method
inmediatamente después del@
signo.Primer avistamiento
El matraz de microframework introduce decoradores desde el principio en el siguiente formato:
Esto a su vez se traduce en:
Darme cuenta de esto finalmente me permitió sentirme en paz con Flask.
fuente
app.route("/")
: esta función devuelve una función, la cualhello()
app.route("/", hello)
inmediatamente después de definirhello
, o incluso definirhello
como lambda en los argumentosapp.route
? (El último ejemplo es común con lashttp.Server
rutas Node.js y Express.)Este fragmento de código:
Es equivalente a este código:
En la definición de un decorador, puede agregar algunas cosas modificadas que una función no devolvería normalmente.
fuente
En Python 3.5 puede sobrecargarse
@
como operador. Se llama así__matmul__
porque está diseñado para multiplicar matrices, pero puede ser lo que quieras. Ver PEP465 para más detalles.Esta es una implementación simple de la multiplicación de matrices.
Este código produce:
fuente
@=
operador (en el lugar), que es__imatmul__
.__add__
y estoy__sub__
vinculado a + y - respectivamente, pero nunca antes había oído hablar del@
signo. ¿Hay otros al acecho por ahí?¿Qué hace el símbolo "at" (@) en Python?
En resumen, se usa en la sintaxis del decorador y para la multiplicación de matrices.
En el contexto de los decoradores, esta sintaxis:
es equivalente a esto:
En el contexto de la multiplicación de matrices,
a @ b
invocaa.__matmul__(b)
, haciendo esta sintaxis:equivalente a
y
equivalente a
donde
dot
es, por ejemplo, la función de multiplicación de matrices numpy ya
yb
son matrices.¿Cómo puedes descubrir esto por tu cuenta?
Si desea tener una vista bastante completa de lo que hace una parte de la sintaxis de Python en particular, mire directamente el archivo de gramática. Para la rama Python 3:
Podemos ver aquí que
@
se usa en tres contextos:Sintaxis del decorador:
Una búsqueda en Google de "decorator python docs" da como uno de los mejores resultados, la sección "Declaraciones compuestas" de la "Referencia del lenguaje Python". Desplazándonos hacia la sección de definiciones de funciones , que podemos encontrar buscando la palabra "decorador", vemos que ... hay mucho para leer. Pero la palabra "decorador" es un enlace al glosario , que nos dice:
Entonces, vemos que
es semánticamente lo mismo que:
No son exactamente iguales porque Python evalúa la expresión foo (que podría ser una búsqueda punteada y una llamada a función) antes de la barra con la
@
sintaxis decorator ( ), pero evalúa la expresión foo después de la barra en el otro caso.(Si esta diferencia hace una diferencia en el significado de su código, debe reconsiderar lo que está haciendo con su vida, porque eso sería patológico).
Decoradores apilados
Si volvemos a la documentación de sintaxis de definición de función, vemos:
Esta es una demostración de que podemos llamar a una función que es primero un decorador, así como a los decoradores de pila. Las funciones, en Python, son objetos de primera clase, lo que significa que puede pasar una función como argumento a otra función y devolver funciones. Los decoradores hacen ambas cosas.
Si apilamos los decoradores, la función, tal como se define, se pasa primero al decorador inmediatamente por encima, luego al siguiente, y así sucesivamente.
Eso resume el uso
@
en el contexto de los decoradores.El operador,
@
En la sección de análisis léxico de la referencia del lenguaje, tenemos una sección sobre operadores , que incluye
@
, que también la convierte en un operador:y en la página siguiente, el Modelo de datos, tenemos la sección Emulación de tipos numéricos ,
Y vemos que
__matmul__
corresponde a@
. Si buscamos en la documentación "matmul", obtenemos un enlace a Novedades en Python 3.5 con "matmul" bajo el título "PEP 465 - Un operador infijo dedicado para la multiplicación de matrices".(Así que ahora aprendemos que
@=
es la versión in situ). Explica además:Si bien este operador se puede sobrecargar para hacer casi cualquier cosa, en
numpy
, por ejemplo, usaríamos esta sintaxis para calcular el producto interno y externo de matrices y matrices:Multiplicación de matriz in situ:
@=
Mientras investigamos el uso anterior, aprendemos que también existe la multiplicación de matriz in situ. Si intentamos usarlo, podemos encontrar que aún no está implementado para numpy:
Cuando se implemente, esperaría que el resultado se vea así:
fuente
El símbolo @ es un azúcar sintáctico que Python proporciona para utilizar
decorator
,parafraseando la pregunta, ¿Se trata exactamente de qué hace el decorador en Python?
En pocas palabras, le
decorator
permite modificar la definición de una función determinada sin tocar su parte más interna (su cierre).Es el caso más importante cuando importa un paquete maravilloso de un tercero. Puedes visualizarlo, puedes usarlo, pero no puedes tocar su interior y su corazón.
Aquí hay un ejemplo rápido,
supongamos que defino una
read_a_book
función en IpythonVerás, olvidé agregarle un nombre.
¿Cómo resolver tal problema? Por supuesto, podría redefinir la función como:
Sin embargo, ¿qué pasa si no se me permite manipular la función original, o si hay miles de tales funciones para manejar?
Resuelva el problema pensando diferente y defina una nueva_función
Entonces úsalo.
Tada, ya ves, modifiqué
read_a_book
sin tocarlo cierre interno. Nada me detiene equipado condecorator
.De que se trata
@
@add_a_book
es una manera elegante y práctica de decirread_a_book = add_a_book(read_a_book)
, es un azúcar sintáctico, no hay nada más elegante al respecto.fuente
Si se está refiriendo a algún código en un cuaderno de Python que está usando la biblioteca Numpy , entonces
@ operator
significa Multiplicación matricial . Por ejemplo:fuente
Comenzando con Python 3.5, la '@' se usa como un símbolo infijo dedicado para MULTIPLICACIÓN DE MATRIZ (PEP 0465 - ver https://www.python.org/dev/peps/pep-0465/ )
fuente
Se agregaron decoradores en Python para que el ajuste de funciones y métodos (una función que recibe una función y devuelve una mejorada) sea más fácil de leer y comprender. El caso de uso original era poder definir los métodos como métodos de clase o métodos estáticos en la cabeza de su definición. Sin la sintaxis del decorador, requeriría una definición bastante escasa y repetitiva:
Si la sintaxis del decorador se usa para el mismo propósito, el código es más corto y más fácil de entender:
Sintaxis general y posibles implementaciones
El decorador es generalmente un objeto con nombre ( no se permiten expresiones lambda ) que acepta un solo argumento cuando se lo llama (será la función decorada) y devuelve otro objeto invocable. "Callable" se usa aquí en lugar de "función" con premeditación. Si bien los decoradores a menudo se discuten en el alcance de los métodos y funciones, no se limitan a ellos. De hecho, cualquier cosa que sea invocable (cualquier objeto que implemente el método _call__ se considera invocable), puede usarse como decorador y, a menudo, los objetos devueltos por ellos no son funciones simples sino más instancias de clases más complejas que implementan su propio método __call_.
La sintaxis decoradora es simplemente un azúcar sintáctico . Considere el siguiente uso de decorador:
Esto siempre se puede reemplazar por una llamada explícita del decorador y la reasignación de funciones:
Sin embargo, este último es menos legible y también muy difícil de entender si se utilizan múltiples decoradores en una sola función. Los decoradores se pueden usar de varias maneras diferentes como se muestra a continuación:
Como una función
Hay muchas formas de escribir decoradores personalizados, pero la forma más simple es escribir una función que devuelva una subfunción que envuelva la llamada a la función original.
Los patrones genéricos son los siguientes:
Como una clase
Si bien los decoradores casi siempre se pueden implementar usando funciones, hay algunas situaciones en las que usar clases definidas por el usuario es una mejor opción. Esto suele ser cierto cuando el decorador necesita una parametrización compleja o depende de un estado específico.
El patrón genérico para un decorador no parametrizado como clase es el siguiente:
Decoradores paramétricos
En el código real, a menudo es necesario usar decoradores que se puedan parametrizar. Cuando la función se usa como decorador, la solución es simple: se debe usar un segundo nivel de envoltura. Aquí hay un ejemplo simple del decorador que repite la ejecución de una función decorada el número especificado de veces cada vez que se llama:
El decorador definido de esta manera puede aceptar parámetros:
Tenga en cuenta que incluso si el decorador parametrizado tiene valores predeterminados para sus argumentos, los paréntesis después de su nombre son obligatorios. La forma correcta de usar el decorador anterior con argumentos predeterminados es la siguiente:
Finalmente veamos decoradores con Propiedades.
Propiedades
Las propiedades proporcionan un tipo de descriptor incorporado que sabe cómo vincular un atributo a un conjunto de métodos. Una propiedad toma cuatro argumentos opcionales: fget, fset, fdel y doc. El último se puede proporcionar para definir una cadena de documentos que está vinculada al atributo como si fuera un método. Aquí hay un ejemplo de una clase Rectángulo que se puede controlar mediante el acceso directo a los atributos que almacenan dos puntos de esquina o mediante el uso de las propiedades de ancho y alto:
La mejor sintaxis para crear propiedades es usar la propiedad como decorador. Esto reducirá la cantidad de firmas de métodos dentro de la clase y hará que el código sea más legible y mantenible . Con decoradores, la clase anterior se convierte en:
fuente
Para decir lo que otros tienen de una manera diferente: sí, es un decorador.
En Python, es como:
Esto se puede usar para todo tipo de cosas útiles, hecho posible porque las funciones son objetos y solo son necesarias instrucciones.
fuente
@ Símbolo también se utiliza para las variables de acceso dentro de un plydata / pandas trama de datos de consulta,
pandas.DataFrame.query
. Ejemplo:fuente
Indica que está utilizando un decorador. Aquí está el ejemplo de Bruce Eckel de 2008.
fuente