Imagen cortesía de www..com
Cambiar el comportamiento incorporado mediante métodos mágicos
Los métodos mágicos son métodos especiales que puede definir para agregar ‘magia’ a sus clases. Siempre están rodeados de guiones bajos dobles, por ejemplo, los métodos mágicos _ _ init _ _ y _ _ str__. Los métodos mágicos pueden enriquecer nuestro diseño de clases al darnos acceso a las funciones de sintaxis integradas de Python.
Python permite que nuestras clases hereden de clases integradas. Una clase secundaria hereditaria de un elemento integrado comparte todos los mismos atributos, incluidos los métodos que el elemento integrado. Podemos aprovechar la funcionalidad básica incorporada, pero personalizar las operaciones seleccionadas mediante el uso de métodos mágicos.
En este tutorial, uniré estas dos ideas para mostrar cómo podemos heredar de la clase lista incorporada y hacer uso de métodos mágicos en el diseño de nuestra clase. Modificaré los tres métodos mágicos que controlan la indexación de listas. Al combinar ambas características, se puede construir una clase que es muy simple de usar y podemos agregar comportamiento a los métodos que deseamos. El comportamiento incorporado es familiar para todos los desarrolladores de Python; a su vez, esto hace que el uso de nuestra clase de herencia sea fácil de aprender.
Finalmente, se demostrarán otros dos ejemplos más amplios que ilustran cómo se pueden usar los métodos mágicos en las operaciones de transmisión y cómo cambiar el estado de una instancia. Todo el código que lo acompaña está disponible a través de GitHub.
Ejemplo 1: Indexación de listas
Los métodos mágicos se pueden manipular para modificar la indexación de listas. La clase MyCustomList, hereda del tipo de lista integrado. Esto significa que cualquier objeto que se cree a través de la clase MyCustomList se comportará como una lista, excepto en los lugares donde elegimos personalizar selectivamente los métodos.
getitem, setitem y delitem son métodos mágicos que se invocan cuando accedemos al índice de la lista. El comportamiento de estos métodos mágicos se puede modificar.
En el ejemplo que se muestra a continuación, descartamos la idea de indexar listas comenzando por el índice cero. Si el usuario intenta acceder a un elemento de nuestra lista utilizando el índice cero, un ValueError excepción y el programa terminará. Si el usuario ingresa un índice de lista mayor que uno, los métodos reducirán el índice en uno y, a continuación, llamarán a la lista de clases principales con el índice.
Para mostrar cómo se utilizan estos métodos definidos en la clase MyCustomList, consulte a continuación en el indicador interactivo de Python.
en El ejemplo se muestra cómo getitem, setitem y delitem puede ser llamado. Los métodos mágicos se pueden llamar implícitamente. Para _ _ getitem__, para acceder al primer índice, simplemente escriba el nombre del objeto seguido de la posición del índice entre corchetes.
Lo que es más interesante, es que cuando pedimos el elemento en la posición de índice 1, se devuelve el valor entero 1, aunque 1 es el elemento cero. Lo que tenemos aquí es una lista que comienza su indexación a partir de 1. De hecho, está compensando la confusión que todos hemos tenido cuando aprendimos por primera vez la indexación de listas.
Ahora, cambiemos el valor entero 1 de la lista a 100. Para hacer esto, necesitamos invocar setitem. Para hacer esto, simplemente escribimos el nombre del objeto, seguido de corchetes y una asignación. De nuevo, para cambiar el primer elemento de la lista usamos la posición de índice 1. Cuando volvemos a generar la lista, podemos ver claramente que el primer elemento ha cambiado de 1 a 100.
Finalmente, para eliminar un elemento de la lista se puede definir _ _ delitem__. Se invoca el método__ delitem _ _ magic, cuando usamos la palabra clave del python que resuelve la llamada al método __delitem__. Para seguir trabajando en nuestro ejemplo de indexación de listas, eliminemos el primer elemento del índice, el valor entero 100. Cuando llamamos a del, seguido por el objeto y la posición de índice del elemento que queremos eliminar, en este ejemplo, el primer elemento de la lista 100, ahora podemos ver que 100 de hecho se ha eliminado!
Los métodos mágicos ofrecen la posibilidad de modificar el comportamiento predeterminado. Lo mejor de todo es que no es necesario aprender nuevos nombres de métodos o una nueva interfaz, por lo que los métodos se pueden implementar de forma intuitiva. En la siguiente tabla se especifica una guía para usar estos métodos mágicos implementados en MyCustomList.
Example 2: El método__ mul _ _ magic
También podemos hacer uso del operador de multiplicación en nuestro diseño de clase. Dado que heredamos de la clase list integrada, podemos comprimir dos objetos MyCustomList juntos (porque actúan como objetos de lista) e iterar a través del objeto zip. Durante las iteraciones, podemos multiplicar los elementos de cada lista por su elemento correspondiente en la otra lista de una manera de difusión(ver__ mul _ _ fragmento de código del método mágico a continuación). Este comportamiento de transmisión es similar al encontrado en paquetes de análisis de datos como Pandas y Numpy.
El ejemplo muestra que podemos multiplicar dos objetos MyCustomList juntos usando el signo*. Si capturamos el valor devuelto en una variable llamada list_three, e imprimimos list_three, se genera una nueva lista. Esta lista es el producto de multiplicar los elementos entre sí de las otras 2 listas.
El código fuente completo de la clase que se usa en este ejemplo, MyCustomList se muestra a continuación:
Ejemplo de Bonificación: El método__ call _ _ magic
Para terminar, ilustraré cómo se puede invocar el método__ call _ _ magic en Python. __call__
puede ser particularmente útil en clases con instancias que necesitan cambiar a menudo su estado. «Llamar» a la instancia puede ser una forma intuitiva y elegante de cambiar el estado del objeto.
Considere el ejemplo que se muestra. Aquí, la clase MyClass tiene un constructor de inicio que espera que se pasen tres argumentos. Estos tres argumentos se pueden pasar en la firma del método init y asignarse como atributos en el objeto.
El método call magic es útil cuando queremos cambiar el estado de una instancia, sin crear realmente una nueva instancia.
Cuando la instancia se inicializa por primera vez, paso los enteros 1, 2 y 3, que se asignan como atributos var_1, var_2 y var_3 en la instancia, respectivamente. Cuando uso la instrucción print para mostrar la salida de la instancia, obj, mediante el atributo _ _ dict__, puedo ver que a var_1 se le asigna el valor 1, a var_2 se le asigna el valor 2 y a var_3 se le asigna el valor 3.
Ahora, vamos a proponer que me gustaría cambiar los valores de los atributos var_1 y var_2 de esta instancia, manteniendo el atributo var_3 como estaba cuando se construyó la instancia originalmente.
Hacer esto es simple. Defino un método call magic, que permite redefinir los atributos var_1 y var_2. Los métodos mágicos se pueden llamar implícitamente, lo que significa que simplemente llamo a obj(200, 300), y se invocará el método de llamada. Por supuesto, también es posible invocar el método de llamada explícitamente, por ejemplo, obj.__ call _ _ (200, 300), pero el primer método parece más intuitivo. Finalmente, para fines de demostración, he impreso el ID de la instancia para mostrar definitivamente que hemos manipulado el mismo objeto.
El método de llamada puede ser definido de dos maneras. Los argumentos se pueden pasar directamente a la firma del método de llamada. Alternativamente, se puede usar el argumento * vars, que captura todos los argumentos pasados y los almacena en una tupla, que se puede desempaquetar como se muestra arriba.
El código fuente de este ejemplo se pueden encontrar a continuación.
Los métodos mágicos pueden enriquecer nuestro diseño de clases al darnos acceso a las funciones de sintaxis principales. En los primeros ejemplos, tenemos lo mejor de ambos mundos. Podemos heredar de la clase list integrada y modificar métodos particulares de esa clase para personalizar el comportamiento. getitem, setitem y delitem fueron modificados, pero a través de la herencia, todavía pudimos hacer uso de los métodos init y repr() integrados en la lista, por ejemplo.
Podemos comunicar el uso de los objetos de forma extremadamente sencilla a otros desarrolladores. En el ejemplo proporcionado, todo lo que necesitamos decirle a nuestros compañeros desarrolladores es que nuestra clase actúa como una lista, solo un poco diferente, aquí descartamos la idea de un índice cero. No es necesario aprender el nombre de nuevos métodos o una nueva interfaz.
Además, se demostró el método call magic. Llamar a la instancia puede ser una forma intuitiva y elegante de cambiar el estado del objeto.