Path: blob/master/material/Intro_clases.ipynb
934 views
Clases
En Python, todo es un objeto, es decir, una instancia o realización de un clase. Cada objeto tiene unos métodos:
que son variables internas dentro del objeto: self.atributo=....
.
Algunos objetos en Python también pueden recibir parámetros de entrada a modo de claves de un diccionario interno del objeto
entro otras muchas propiedades
Ejemplos de objetos son:
int
: Enterosfloat
: Números punto flotante (floating point numbers)str
: Cadenas de caractereslist
: Listasdict
: Diccionarios.
Si el tipo de objeto es conocido, uno pude comprobar si un objeto determinado corresponde a ese tipo con isinstance
:
Dentro del paradigma de objetos es posible agrupar diferentes conjuntos de variables de modo que el nombre de un atributo a método adquiere dos partes, una parte principal, que en el análogo con el nombre completo de una persona podríamos asimilar a su apellido, y el método o atributo, que sería como el primer nombre, separados por un punto:
Método:
last_name.first_name()
Atributo:
last_name.first_name
.
Esto nos permite tener objetos dentro de un programa con igual nombre, pero diferente appellido. Como por ejemplo, los diferentes que vienen en los diferentes módulos matématicos implementados en Python. Por eso es recomendado cargar los módulos manteniendo el espacio de nombres (que en nuestra analogía sería el espacio de apellidos). Cuando el modulo tenga un nombre muy largo (más de cuatro caracteres), se puede usar una abreviatura lo suficientemente original para evitar que pueda ser sobreescrita por un nuevo objeto:
Note que import math as m
entraría en conflicto con la definición de m
en m=2
Para programación de Python en general se recomienda el estándar PEP 8 de Python
Antes de comenzar con las clases, es conveniente resumir el paradigma de programación funcional:
Programación funcional
En cálculo científico el paradigma funcional, en el cual el programa se escribe en términos de funciones, suele ser suficiente.
El esqueleto de un programa funcional es típicamente del siguiente tipo
Para su diseño, el programa se debe separar sus partes independientes y para cada una de ellas se debe definir una función.
La función ideal es una que se pueda reutilizar facilamente en otro contexto.
La última función, main(...)
combina todas las anteriores para entregar el resultado final del programa.
La instrucción
permite que el programa pueda ser usado también como un módulo de Python, es decir que se pueda cargar desde otro programa con el import
. En tal caso, la variable interna de Python __name__
es diferente a la cadena de caracteres '__main__'
y esa parte del programa no se ejecuta. Dentro de Jupyter:
Ejemplo módulo
ls
funciona
-rwxr-xr-x 1 restrepo restrepo 171 Mar 31 14:11 example.py*
cat
funciona
Cambia los permisos a ejecución
-rwxr-xr-x 1 restrepo restrepo 171 Mar 31 14:11 example.py*
Corre el programa desde la consola
Uso como módulo
Ejecutarlo desde una celda de Jupyter es equivalente a ejecutarlo desde la consola
Clases
Aunque en Python se puede trabajar directamente con objetos, en general un objeto es una instancia de un clase. Es decir, debe incializarse a partir de una Clase. Esto típicamente involucra ejecutar varios métodos e inicializar varios atributos bajo el espacio de nombres del objeto incializado. Por ejemplo, para inicializar las clases 'int', 'float', 'str', 'list','dict'
int
es la claseint()
es la instancia de la clasen=int()
es el objeto asociado a la clase:n.→
contiene todos los atributos y los métodos de la claseint
La principal motivación para escribir una clase en lugar de una función, es que la clase puede ser la base para generar nuevas clases que hereden los métodos y atributos de la clase original.
Por ejemplo el DataFrame de Pandas es una clase que puede ser inicializada de múltiples formas. Además, está diseñada para que pueda ser extendida facilmente: https://pandas.pydata.org/pandas-docs/stable/development/extending.html
Como puede verse, un DataFrame
es una subclase (es decir, un caso especial) de NDFrame
.
Una instancia u objeto de la clase DataFrame
, df
a continuación, se puede inicializar de diferentes maneras
Programación por clases
Una clase se puede pensar como un conjuto de funciones y atributos que comparten algo en común. Por ejemplo, los miembros de una familia
Algunas veces, cuando la complejidad del problema se puede descomponer en una estructura de capas, donde la capa interna es la mas simple y las capas más externas van aumentando la complejidad, pude ser conveniente pensar en una estructura de clases.
De hecho, la clase básica puede heredar todas sus propiedades a subclases basadas en ella.
El espacio de nombres asociado a la clase se define con el nombre génerico de self
el cual toma el nombre de las instancia (objeto) asociada a la inicialización de la clase. Las variables globales de la clase pasán a ser automáticamente atributos del objeto, y nuevo atributos de pueden definir dentro del espacio de nombres self
dentro de cada función de la clase.
Esqueleto:
Cada una de las funciones pasan a ser métodos de la clase, mientras que cada una de la variables globales y con espacio de nombre self
pasan a ser atributos de la clase.
Ejemplo:
Creación del objeto c
, de manera que self
→ c
. c
es una instancia de la clase clasenueva
a continuación:
main
es un método de la clase
var
es un atributo de la clase
Para la creación de clases disponemos de métodos especiales, constructores, que podemos definir para adicionar "magia" a nuestras clases. Estas están simpre rodeadas de un doble guión bajo, por ejemplo: __init__
o __lt__
. Una lista completa de ellos con su explicación de uso se puede encontrar en 1.
Resaltamos a continuación algunos de ellos
__init__
: Se ejecuta automáticamente al inicializar la clase__add__
: Sobrecarga el operador suma,+
→ self + other
For example, with __init__
, the previous class is
Herencia
Los métodos especiales se pueden heredar automáticamente desde la clase inicial, que llamaremos superclass
. Para ello inicializamos la clase con la superclass
como argumento, es decir, en forma genérica como:
Cree una clase mamal
o una clase fish
Reescribir método de superclass
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Cell In [169], line 2
1 butterfly=insect(stage='adult',wings=2,legs=6,anntenaes=2,eyes=1700)
----> 2 butterfly.live
AttributeError: 'insect' object has no attribute 'live'
Use un método de la superclass
con super
Si lo que queremos es modificar el comportomiento de un método de una superclase entonces debemos usar la función super
.
Para mantener la herencia el comportamiento de los métodos de una clase inicial, ls super clase, se usa la función super
que mantiene la herencia. Ver:
super()
gives you access to methods in a superclass from the subclass that inherits from it.
super()
is the same assuper(__class__, <first argument>)
: the first is the subclass, and the second parameter is an object that is an instance of that subclass.
La estructura general es como la siguiente, basada en Inherited class variable modification in Python:
Modificar la clase animal
con un __init__
y generar las subclases apropiadamente
Clase vector
Comenzaremos definiendo un alias de clase list
que llameremos vector y que funcione exactamente igual que la clase lista. Todas los métodos especiales se heredan automáticamente
Vamos a inicializar dos instancias de la clase vector
y comprobar que suman como listas
Ahora reemplazaremos el método mágico __add__
de la lista para que el operador +
realice la suma vectorial:
Init signature: map(self, /, *args, **kwargs)
Docstring:
map(func, *iterables) --> map object
Make an iterator that computes the function using arguments from
each of the iterables. Stops when the shortest iterable is exhausted.
Type: type
Subclasses:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In [182], line 1
----> 1 v1-v2
TypeError: unsupported operand type(s) for -: 'vector' and 'vector'
Reiniciando el kernel de jupyter
Como ejemplo, vamos a implemetar el atributo modulus
a la clase vector
dentro del método especial __init__
:
Una implementación completa de la clase vector, adapta de vector: a list based vector class supporting elementwise operations (python recipe), se puede encontrar aquí
Otro ejemplo
Cundo se inicializa la clase la función llamada
__init__
, se ejecuta automáticamente.La función
__call__
permite usar el objeto directamente como función, sin hacer referencia al método, que por supuesto es__call__
Hay muchos otros métodos especiales, que comienzan con un __
.... Usar <TAB>
a continuación para ver algunos
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
/tmp/ipykernel_664677/3273899342.py in <module>
----> 1 veterinaria.__
AttributeError: type object 'veterinaria' has no attribute '__'
Para utilizar la clase, primero se debe incializar como un objeto. Crear la instancia de la clase.
Ejemplo: Crea la instancia mascotafeliz
Herencia
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/tmp/ipykernel_664677/2358335894.py in <module>
----> 1 f([{'A':1}])
TypeError: 'finanzas' object is not callable
Para realmente heradar hay que inicializarlo de forma especial con la función super
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
/tmp/ipykernel_664677/1012315857.py in <module>
----> 1 d.has_key('gato')
AttributeError: 'dict' object has no attribute 'has_key'
Implementation of arXiv:1905.13729
See also: DOI: 10.1103/PhysRevD.101.095032
Repo: https://github.com/restrepo/anomalies
General solution to the U(1) anomaly equations
Let a vector with integer entries such that We like to build this set of of from two subsets and with sizes
even: Consider the following two examples of with vector-like solutions, i.e, with opposite integeres which automatically satisfy the equations
odd: Consider the two vector-like solutions ParseError: KaTeX parse error: Unexpected end of input in a macro argument, expected '}' at position 29: … \begin{array} \̲b̲o̲l̲d̲s̲y̲m̲b̲o̲l̲{x}=&\left(0, k…
From any of this, we can build a final which can includes chiral solutions, i.e, non vector-like solutions
Analysis
solutions
class → Initialize the object to obtain anomaly free solutions for any set of N
integers
Chiral solutions for l and k in the range [-2,2]
solutions for integers
To filter solutions with duplicate or triplicate integers, let us create a class dark
that inherits from solutions
. Therefore, in the argument of the new class is the old class instead of just object
Chiral solutions with repeated integers
Example: Force solutions with triplicate integers
Example
Simple csv to json converter
Decorating classes
From https://realpython.com/primer-on-python-decorators/#decorating-classes
Some commonly used decorators that are even built-ins in Python are
@classmethod
,@staticmethod
, and@property
. The@classmethod
and@staticmethod
decorators are used to define methods inside a class namespace that are not connected to a particular instance of that class. The@property
decorator is used to customize getters and setters for class attributes.
References
[1] A Guide to Python's Magic Methods
[2] https://realpython.com/python3-object-oriented-programming/
[3] Building Skills in Object-Oriented Design
[4] Ver también: https://gist.github.com/mcleonard/5351452
[5] Bhasin, Harsh. Python Basics: A Self-teaching Introduction. Stylus Publishing, LLC, 2018. [PDF] [Google Scholar]