Contenido#

Los siguientes contenidos serán presentados en una sesión de videoconferencia. Puedes encontrar en este enlace las slides usadas como soporte.
Clases#
Atributos y Métodos#
Algo que sí distingue a Python (y a otros) de Fortran o C es que son lenguajes orientados a objetos. El uso de objetos hace que un lenguage resulte más intuitivo para el programador amateur. Además los objetos pueden contener tener otros objetos como atributos y métodos. Esto simplifica mucho la organización de la información y hace de Python un lenguage compacto y sencillo. Debes de comenzar a apreciar la simplicidad como principio que guíe tus lineas de código, joven padawan. Ya estás preparado para instruirte en los principios Zen de python.
Ya podemos ver, por ejemplo, que los objetos presentados en secciones anteriores no son simples variables definidas como la combinación de un “nombre de variable” y “valor de variable”, sino que tienen asociados atributos (características almacenadas en forma de objetos) y métodos (funciones). Para ver qué cosas tiene un objeto podemos emplear método dir
.
palabra = 'otorrinolaringólogo'
dir(palabra)
['__add__',
'__class__',
'__contains__',
'__delattr__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__getitem__',
'__getnewargs__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__iter__',
'__le__',
'__len__',
'__lt__',
'__mod__',
'__mul__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__rmod__',
'__rmul__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'capitalize',
'casefold',
'center',
'count',
'encode',
'endswith',
'expandtabs',
'find',
'format',
'format_map',
'index',
'isalnum',
'isalpha',
'isascii',
'isdecimal',
'isdigit',
'isidentifier',
'islower',
'isnumeric',
'isprintable',
'isspace',
'istitle',
'isupper',
'join',
'ljust',
'lower',
'lstrip',
'maketrans',
'partition',
'removeprefix',
'removesuffix',
'replace',
'rfind',
'rindex',
'rjust',
'rpartition',
'rsplit',
'rstrip',
'split',
'splitlines',
'startswith',
'strip',
'swapcase',
'title',
'translate',
'upper',
'zfill']
Esa lista que arroja el método dir
es el conjunto de métodos y atributos que la variable palabra, como objeto de clase “cadena de caracteres (str)”, contiene. Aquellos elementos de la lista que comienzan y terminan con dos guiones bajos, “__”, son elementos de utilidad interna y privada para Python (no fueron implementados apriori como funcionalidad para el usuario). Si, pero te estarás diciendo: «qué son esos elementos???». Todos estos elementos almacenan información (atributos) o funciones (métodos) que cuelgan del objeto “palabra” y a los cuales puedes acceder mediante el uso de un punto “.”:
# El atributo __class__ está presente en todos los objetos y almacena el nombre del tipo de la variable:
palabra.__class__
str
# El método __sizeof__() está también presente en todos los objetos y calcula su tamaño en memoria
palabra.__sizeof__()
92
Habrás adivinado gracias a estas dos últimas celdas cúal es la diferencia invocando atributos o métodos. Un método necesita invocarse con paréntesis ya que es una función que podría tener argumentos de entrada -veremos esto más adelante-.
También en este punto te preguntarás, pero y cómo sabes qué hace y es cada cosa? Fácilmente:
La documentación de Python y sus librerías siempre es muy útil: web oficial de Python 3 en su sección sobre tipos str
La comunidad de usuarios y el número de foros es enorme. Segúramente alguien ya se preguntó lo mismo que tu y otro le contestó: búsqueda en google
El método
help
resulta de mucha ayuda
Para ilustrar como funciona help
y sin salir del notebook puedes ver qué documentación se esconde por ejemplo detrás de los siguientes elementos de la lista anterior de atributos y métodos: __sizeof__
, endswith
y capitalize
.
help(palabra.__sizeof__)
Help on built-in function __sizeof__:
__sizeof__() method of builtins.str instance
Return the size of the string in memory, in bytes.
help(palabra.endswith)
Help on built-in function endswith:
endswith(...) method of builtins.str instance
S.endswith(suffix[, start[, end]]) -> bool
Return True if S ends with the specified suffix, False otherwise.
With optional start, test S beginning at that position.
With optional end, stop comparing S at that position.
suffix can also be a tuple of strings to try.
help(palabra.capitalize)
Help on built-in function capitalize:
capitalize() method of builtins.str instance
Return a capitalized version of the string.
More specifically, make the first character have upper case and the rest lower
case.
Vemos por ejemplo que endswith
es un método que tiene argumentos de entrada, un sufijo en este caso, y devuelve el valor Verdadero (True) si el valor de la variable cadena de caracteres termina con ese sufijo y Falso (False) si no.
palabra.endswith('logo')
True
palabra.endswith('ble')
False
O que el método capitalize
no tiene argumentos de entrada y devuelve la cadena con el primer caracter en mayúscula y el resto en minúsculas.
print(palabra)
print(palabra.capitalize())
otorrinolaringólogo
Otorrinolaringólogo
Por último podemos añadir que en este punto del notebook ya hemos visto que existen métodos propios de Python y ajenos a cualquier objeto como dir
, print
, help
o len
:
print(palabra.capitalize(),'tiene',len(palabra),'letras')
Otorrinolaringólogo tiene 19 letras
Las listas, las tuplas, los diccionarios… también tienen sus propios atributos y métodos. Por ejemplo, tomando el objeto de la sección anterior un_diccionario
:
un_diccionario = {'hello': 'hola', 'apple': 'manzana', 'house': 'casa'}
un_diccionario.keys() # Este método da la lista de claves
dict_keys(['hello', 'apple', 'house'])
un_diccionario.keys() # Este método da la lista de claves
dict_keys(['hello', 'apple', 'house'])
un_diccionario.pop('house') # Este método saca un item del diccionario
'casa'
un_diccionario
{'hello': 'hola', 'apple': 'manzana'}
¿Podemos definir nuestra propia clase de objetos con métodos y atributos?#
Para consolidar la comprensión en la diferencia entre métodos y atributos, y entender la trascendencia de poder definir «clases de objetos» veamos cómo podemos definir nuestra propia clase.
Una clase es la plantilla de un objeto. Las clases se definen con métodos y atributos, propios de esa clase (valga la redundancia). Y son realmente útiles.
Supongamos que defino la clase átomo
. Átomos puede haber de muchos: de naturaleza distinta, con distinta carga, radio de Van der Waals, peso atómico… pero todos tienen esas propiedades que puedo definir como atributos comunes en la plantilla que representa la clase átomo
.
class átomo():
def __init__(self):
self.tipo = None
self.radio = None
self.carga = None
Hemos comenzado definiendo los tres atributos de átomo
(tipo, radio y carga) con valor None
. Algo todavía poco útil, pero ya podemos crear átomos haciendo uso de átomo
como plantilla:
at1 = átomo()
at2 = átomo()
at3 = átomo()
type(at1)
__main__.átomo
print(at1.tipo)
print(at2.radio)
print(at3.carga)
None
None
None
Hagamos ahora algo más útil. Vamos a generar la clase átomo
con un argumento de entrada que será el tipo
de átomo. Y el resto de atributos, radio
y carga
, serán adjudicados al inicializar un objeto de clase átomo
dependiendo de su tipo:
class átomo():
def __init__(self, tipo = None):
self.tipo = tipo
self.radio = None
self.carga = None
if tipo == 'A':
self.radio = 2.5
self.carga = 1
if tipo == 'B':
self.radio = 4.0
self.carga = -2
at1 = átomo(tipo='A')
at2 = átomo('B')
at1.radio
2.5
at2.radio
4.0
Por último y para que átomo
no sea únicamente un conjunto de atributos, incluyamos un método. Un método que sea el cálculo del volumen del átomo según su radio.
class átomo():
def __init__(self, tipo = None):
self.tipo = tipo
self.radio = None
self.carga = None
if tipo == 'A':
self.radio = 2.5
self.carga = 1
if tipo == 'B':
self.radio = 4.0
self.carga = -2
def volumen(self):
pi = 3.14159265359
return (4.0/3.0)*pi*self.radio**3
at1 = átomo('A')
at1.radio
2.5
at1.volumen()
65.44984694979166
at1.radio = 3.0
at1.volumen()
113.09733552924
En las líneas de código empleadas para definir la clase átomo
habrás identificado varias cosas desconocidas para ti, aunque su significado puede ser intuitivo. Es el caso de las órdenes def
o if
, o los términos class
o self
. Cómo se define una clase, en profundidad, es materia de un nivel un poco más avanzado y escapa al propósito de este notebook. Pero de la orden if
si vamos a hablar en la sección siguiente ya que es un elemento básico y común de todo lenguaje de programación.
Módulos y librerías#
Por último y para concluir esta introducción a Python, es importante que comprendas qué es un módulo, qué es una librería y cómo se usan.
Un módulo es una pieza de código que encapsulamos en un fichero aislado porque la vamos a usar con frecuencia de manera independiente o como elemento incluido en otros programas. Para comprender esto vamos a crear y a usar nuestro propio módulo.
Vamos a poner la clase átomo
, definida anteriormente, en un fichero de texto que llamaremos atomizador.py
.
mi_módulo = open('atomizador.py','w')
mi_código = "\
class átomo():\n \
\t \"\"\"Clase que representa un átomo con su tipo, radio, carga y volumen.\"\"\"\n \
\n \
\t def __init__(self, tipo = None):\n \
\n \
\t \t self.tipo = tipo\n \
\t \t self.radio = None\n \
\t \t self.carga = None\n \
\n \
\t \t if tipo == 'A':\n \
\t \t \t self.radio = 2.5\n \
\t \t \t self.carga = 1\n \
\n \
\t \t if tipo == 'B':\n \
\t \t \t self.radio = 4.0\n \
\t \t \t self.carga = -2\n \
\n \
\t def volumen(self):\n \
\t \t \"\"\"Función de la clase átomo que calcula el volumen a partir del atributo radio.\"\"\"\n \
\t \t pi = 3.14159265359\n \
\t \t return (4.0/3.0)*pi*self.radio**3\n \
"
print(mi_código)
class átomo():
"""Clase que representa un átomo con su tipo, radio, carga y volumen."""
def __init__(self, tipo = None):
self.tipo = tipo
self.radio = None
self.carga = None
if tipo == 'A':
self.radio = 2.5
self.carga = 1
if tipo == 'B':
self.radio = 4.0
self.carga = -2
def volumen(self):
"""Función de la clase átomo que calcula el volumen a partir del atributo radio."""
pi = 3.14159265359
return (4.0/3.0)*pi*self.radio**3
mi_módulo.write(mi_código)
516
mi_módulo.close()
del(mi_módulo, mi_código)
Puedes ver en el navegador de ficheros que existe “atomizador.py”. Puedes abrirlo en Jupyter Lab, o salir a una terminal o a tu navegador de ficheros del sistema operativo, y ver su contenido. En este punto debes estar pensando que quizá hubiera sido más facil crear este fichero fuera del notebook, haciendo uso de tu editor de texto habitual. Estás en lo cierto, lo hemos creado en el notebook únicamente como ejemplo adicional de escritura de ficheros.
Bien, ya tenemos el fichero “atomizador.py” con un bloque de código. Lo podemos llamar módulo porque la estrategia de trabajo que estamos adoptando es modular. Ponemos código perfectamente funcional y documentado en módulos que podrán ser usados como bloques de construcción reusables, como si fueran los ladrillos de un muro que pudieras emplear para hacer estructuras más grandes. Cuando además un conjunto de módulos, están organizados en una misma carpeta con una cierta estructura que les da entidad de grupo, hablamos de librería.
Un módulo, o librería, se puede “cargar” en cualquier momento con la orden import
.
import atomizador
dir(atomizador)
['__builtins__',
'__cached__',
'__doc__',
'__file__',
'__loader__',
'__name__',
'__package__',
'__spec__',
'átomo']
Probablemente hayas advertido que en la definición de la clase átomo
hemos incluido un par de lineas con texto entre triples comillas dobles. Así: """texto"""
. Mira para lo que sirvieron:
help(atomizador.átomo)
Help on class átomo in module atomizador:
class átomo(builtins.object)
| átomo(tipo=None)
|
| Clase que representa un átomo con su tipo, radio, carga y volumen.
|
| Methods defined here:
|
| __init__(self, tipo=None)
| Initialize self. See help(type(self)) for accurate signature.
|
| volumen(self)
| Función de la clase átomo que calcula el volumen a partir del atributo radio.
|
| ----------------------------------------------------------------------
| Data descriptors defined here:
|
| __dict__
| dictionary for instance variables (if defined)
|
| __weakref__
| list of weak references to the object (if defined)
help(atomizador.átomo.volumen)
Help on function volumen in module atomizador:
volumen(self)
Función de la clase átomo que calcula el volumen a partir del atributo radio.
Ahora vamos a usar el módulo atomizador
para concluir el ejemplo:
átomo1 = atomizador.átomo('A')
print(átomo1.volumen())
65.44984694979166
del(atomizador, átomo1)
Acabamos de borrar los objetos atomizador
y átomo
para poder continuar de manera limpia.
Veamos ahora que podemos también importar un módulo, o librería, “cargándolo” con un alias.
import atomizador as creador_de_átomos_marca_ACME
átomo1 = creador_de_átomos_marca_ACME.átomo('A')
print(átomo1.volumen())
65.44984694979166
del(átomo1, creador_de_átomos_marca_ACME)
O podemos importar clases, métodos u otros objetos específicos de un módulo o de una librería:
from atomizador import átomo as átomo_marca_ACME
átomo1 = átomo_marca_ACME('A')
print(átomo1.volumen())
65.44984694979166
del(átomo)
Borremos por último el fichero “atomizador.py” haciendo uso de la librería os
como vimos anteriormente:
from os import remove as borro_fichero
borro_fichero('atomizador.py')
Dudas, problemas técnicos y soluciones. #
Para centralizar esas dudas técnicas sobre el tema de este notebook o proponer soluciones o sugerencias más técnicas que queremos encontrar en el futuro comentadas y visibles para todos, haz uso del siguiente canal:
Más recursos útiles #
El propósito de este notebook es ser un documento únicamente introductorio. Puedes encontrar -o contribuir añadiendo- más información útil en el siguiente listado:
Documentación #
https://www.python.org/
https://realpython.com/
https://docs.python-guide.org/
https://wiki.python.org/moin/SpanishLanguage
http://www.scipy-lectures.org/intro/intro.html
https://fabienmaussion.info/acinn_python_workshop/
Tutoriales, Webinars y cursos gratuitos #
https://realpython.com/start-here/
https://www.programiz.com/python-programming
http://www.openbookproject.net/books/bpp4awd/
http://www.openbookproject.net/books/pythonds/
http://www.openbookproject.net/books/pp4awdds/
http://openbookproject.net/thinkcs/python/english3e/
https://www.w3schools.com/python/
https://www.python.org/about/gettingstarted/
https://docs.python.org/3/tutorial/
http://docs.python.org.ar/tutorial/
http://swcarpentry.github.io/python-novice-inflammation/
https://www.datacamp.com/community/open-courses?tag=python
https://www.datacamp.com/community/tutorials?tag=python
https://realpython.com/tutorials/python/
https://www.learnpython.org/
https://www.datacamp.com/courses/intro-to-python-for-data-science
https://docs.python-guide.org/intro/learning/
https://www.codecademy.com/learn/learn-python
https://pythonprogramming.net/
http://www.scipy-lectures.org/
https://geekytheory.com/curso/python-3
https://www.learnpython.org/es/
https://www.learnpython.org/
http://www.iac.es/sieinvens/python-course/index.html
https://github.com/damianavila/Python-Cientifico-HCC/blob/master/1_Python_Cientifico_Intro.ipynb