domingo, 14 de agosto de 2022

En este gist alojado en github vemos un notebook sobre como se puede usar python con el paradigma orientado a objetos, incluye diagramas de clases con plant uml y ejemplos ejecutables de código, ademas de un enlace para que hagas tus pruebas en colab

Open In Colab

Python orientado a objetos

Hola, El dia de hoy vamos a estar aprendiendo a programar en python usando jupyter notebook, e instalaremos python en nuestras maquinas, de momento no nos preocuparemos por entornos virtuales y nos apoyaremos en la instalación que tenga nuestro sistema operativo

El objetivo del dia de hoy es aprender sobre la creación de objetos en python

Instalación de python en windows

Colocar captura de como instale python en mi pc

Python en VS code

Visual studio code es un editor creado por Microsoft el cual permite el uso de extensiones para facilitar el desarrollo. Entre las extensiones que podemos instalar en VS Code están las extensiones de python y jupyter

Python: https://marketplace.visualstudio.com/items?itemName=ms-python.python Jupyter: https://marketplace.visualstudio.com/items?itemName=ms-toolsai.jupyter

Recomiendo la instalación de ambas incluyendo el paquete de extensiones de jupyter que trae los renderers para la salida de los notebooks https://marketplace.visualstudio.com/items?itemName=ms-toolsai.jupyter-renderers

image.png

Si descargamos python desde microsoft store debemos adicionar la ruta donde se instala python al path, en mi caso es C:\Users\sergio.orozcot\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\Scripts

image.png

Para esta sesión nos apoyaremos en plant uml entonces por favor ejecutar la siguiente linea

!pip install iplantuml
Looking in indexes: https://pypi.org/simple, https://us-python.pkg.dev/colab-wheels/public/simple/
Collecting iplantuml
  Downloading IPlantUML-0.1.1.tar.gz (5.5 kB)
Collecting plantweb
  Downloading plantweb-1.2.1-py3-none-any.whl (20 kB)
Requirement already satisfied: six in /usr/local/lib/python3.7/dist-packages (from plantweb->iplantuml) (1.15.0)
Requirement already satisfied: docutils in /usr/local/lib/python3.7/dist-packages (from plantweb->iplantuml) (0.17.1)
Requirement already satisfied: requests in /usr/local/lib/python3.7/dist-packages (from plantweb->iplantuml) (2.23.0)
Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.7/dist-packages (from requests->plantweb->iplantuml) (2022.6.15)
Requirement already satisfied: idna<3,>=2.5 in /usr/local/lib/python3.7/dist-packages (from requests->plantweb->iplantuml) (2.10)
Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /usr/local/lib/python3.7/dist-packages (from requests->plantweb->iplantuml) (1.24.3)
Requirement already satisfied: chardet<4,>=3.0.2 in /usr/local/lib/python3.7/dist-packages (from requests->plantweb->iplantuml) (3.0.4)
Building wheels for collected packages: iplantuml
  Building wheel for iplantuml (setup.py) ... [?25l[?25hdone
  Created wheel for iplantuml: filename=IPlantUML-0.1.1-py2.py3-none-any.whl size=4910 sha256=976a41688f4de34923b643fe30cd57437ba613724d7e52558dc2ea135b53eef0
  Stored in directory: /root/.cache/pip/wheels/cf/64/08/5bac65794ab011a60f7ef62413d3c430cf715345028f4b3914
Successfully built iplantuml
Installing collected packages: plantweb, iplantuml
Successfully installed iplantuml-0.1.1 plantweb-1.2.1
import iplantuml

Que la programación orientada a objetos

Es un paradigma de programación que parte del concepto de “objetos” como base, los cuales contienen información en forma de campos (a veces también referidos como atributos o propiedades) y código en forma de métodos.

%%plantuml

@startuml
Perro : ladrar()
@enduml

svg

class Perro:
    def ladrar(self):
        print("guau guau!")

perro = Perro()
perro.ladrar()
guau guau!

Python es un lenguaje donde toca ser explicitos, y en cada metodo de clase es necesario agregar la referencia al objeto que por convención en python llamamos self, lo que en algunos lenguajes de progamación llamariamos this

class Perro1:
    def ladrar():
        print("guau guau!")

perro = Perro1()
perro.ladrar()
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

d:\intro python\poo_en_python_with_plant.ipynb Cell 10' in <cell line: 6>()
      <a href='vscode-notebook-cell:/d%3A/intro%20python/poo_en_python_with_plant.ipynb#ch0000009?line=2'>3</a>         print("guau guau!")
      <a href='vscode-notebook-cell:/d%3A/intro%20python/poo_en_python_with_plant.ipynb#ch0000009?line=4'>5</a> perro = Perro1()
----> <a href='vscode-notebook-cell:/d%3A/intro%20python/poo_en_python_with_plant.ipynb#ch0000009?line=5'>6</a> perro.ladrar()


TypeError: Perro1.ladrar() takes 0 positional arguments but 1 was given

Metodos estaticos

Python soporta metodos estaticos. En python como tal para los utilitarios no necesitamos encapsularlo dentro de clases, ya que de por si las funciones son objetos pero si queremos lo podemos hacer.

class Util:
    @staticmethod
    def hacer_algo():
        print("algo")

Util.hacer_algo()
algo

Metodos magicos

Son metodos especiales definidos por python y estan prefijados con __

class Specialstring:
    def __len__(self):
        return 25

normal_string = "Sergio"
print(len(normal_string))

string = Specialstring()
print(len(string))
6
25

Atributos de clases

Los atributos de clase en python normalmente se definen en el constructor __init__ y en dicho metodo se coloca el tipo de datos en caso de usar type hints

%%plantuml

@startuml
Persona : nombre
Persona : apellido

Persona : __str__(self)
Persona : __repr__(self)
@enduml

svg

class Persona:
    def __init__(self, nombre, apellido):
        self.nombre = nombre
        self.apellido = apellido
    
    def __str__(self):
        return "{} {}".format(self.nombre ,self.apellido)

    def __repr__(self):
        return "Persona('{}', '{}')".format(self.nombre, self.apellido)

sergio = Persona("Sergio", "Orozco")

print(sergio)
Sergio Orozco

Sobrecarga de operadores

La sobrecarga, en el contexto de la programación, se refiere a la capacidad de una función o de un operador de comportarse de diferentes maneras dependiendo de los parámetros que se pasan a la función o de los operandos sobre los que actúa el operador. Por ejemplo podemos definir la suma de 2 Puntos

%%plantuml

@startuml
Punto : x
Punto : y
Punto : __add__(self)
Punto : __str__(self)
Punto : __repr__(self)
@enduml

svg

class Punto:
  def __init__(self, x, y):
    self.x = x
    self.y = y

p1 = Punto(1, 2)
p2 = Punto(3, 4)

print(p1+p2) 
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

d:\intro python\poo-en-python.ipynb Cell 16' in <cell line: 9>()
      <a href='vscode-notebook-cell:/d%3A/intro%20python/poo-en-python.ipynb#ch0000015?line=5'>6</a> p1 = Punto(1, 2)
      <a href='vscode-notebook-cell:/d%3A/intro%20python/poo-en-python.ipynb#ch0000015?line=6'>7</a> p2 = Punto(3, 4)
----> <a href='vscode-notebook-cell:/d%3A/intro%20python/poo-en-python.ipynb#ch0000015?line=8'>9</a> print(p1+p2)


TypeError: unsupported operand type(s) for +: 'Punto' and 'Punto'
class Punto:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def __add__(self, other):
        return Punto(self.x + other.x, self.y + other.y)
    def __sub__(self, other):
        return Punto(self.x - other.x, self.y - other.y)
    def __repr__(self):
        return "Punto({},{})".format(self.x, self.y)

p1 = Punto(5, 2)
p2 = Punto(3, 4)

print(p1 + p2)
print(p1 - p2)
Punto(8,6)
Punto(2,-2)

Sobrecarga del operador + en colecciones

En las colecciónes el operador + se usa para crear una nueva lista uniendo los elementos de ambas listas

(3,4)+(2,6)
(3, 4, 2, 6)
[1, 2] + [3, 4]
[1, 2, 3, 4]
{"nombre": "Sergio"} + {"apellido": "Orozco"}
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

d:\intro python\poo-en-python.ipynb Cell 5' in <cell line: 1>()
----> <a href='vscode-notebook-cell:/d%3A/intro%20python/poo-en-python.ipynb#ch0000004?line=0'>1</a> {"nombre": "Sergio"} + {"apellido": "Orozco"}


TypeError: unsupported operand type(s) for +: 'dict' and 'dict'

Herencia y polimorfismo

La herencia es un mecanismo de relación entre clases donde decimos que una clase es un subtipo de otra, por ejemplo como decir que “Un gato es un Animal”

La herencia nos permite para heredar (tomar del padre): campos de datos, métodos de acceso de otra clase, ademas de poder añadir nuestros propios métodos y campos. Por lo tanto la herencia nos proporciona una manera de organizar el código para no tener que volver a repetir código.

%%plantuml

@startuml
AnimalTerrestre <|-- Gato
AnimalTerrestre <|-- Perro

AnimalTerrestre : caminar()
@enduml

svg

class AnimalTerrestre:
    def caminar(self):
        print("Animal Caminando")

class Perro(AnimalTerrestre):
    pass

class Gato(AnimalTerrestre):
    def caminar(self):
        print("Gato Caminando")

    
perro = Perro()
perro.caminar()
gato = Gato()
gato.caminar()

Animal Caminando
Gato Caminando

Herencia multiple

Python soporta la herencia multiple, lo cual nos permite reutilizar código de todas las clases de las cuales se herede

%%plantuml

@startuml
MiSuperClase1 <|-- MiClase
MiSuperClase2 <|-- MiClase
@enduml

svg

class MiSuperClase1():
 
    def metodo_1(self):
        print("metodo_1 metodo llamado")
 
class MiSuperClase2():
 
    def metodo_2(self):
        print("metodo_2 metodo llamado")

# Clase que hereda las 2 clases anteriormente definidas
class MiClase(MiSuperClase1, MiSuperClase2):
 
    def metodo_3(self):
        print("metodo_3 metodo llamado")

# Se crea el objeto "c" y luego se llama al metodo_1 y metodo_2 heredados de las 2 primeras clases
c = MiClase()
c.metodo_1()
c.metodo_2()

El problema del diamante

Cuando tenemos herencia multiple puede suceder que heredemos de una clase la cual extiende de una base común, esto es lo que se llamaria el problema del diamante, y en python se resuelve escogiendo bien el orden en el cual heredamos los elementos

%%plantuml

@startuml
A <|-- B
A <|-- C
C <|-- D
B <|-- D
@enduml

svg

class A:
    def display(self):
        print("I am the display of Class A")
 
 
class B(A):
    def display(self):
        print("I am the display of Class B")
 
 
class C(A):
    def display(self):
        print("I am the display of Class C")
 
 
class D(B, C):
    pass
 
 
o = D()
o.display()
 
I am the display of Class B

Duck typing

Algo muy interesante de python es la filosofia de duck typing, si camina como pato, parece un pato, entonces es un pato

%%plantuml

@startuml
Bird : fly()
Airplane : fly()
Fish : swim()
@enduml

svg

class Bird:
    def fly(self):
        print("fly with wings")
  
class Airplane:
    def fly(self):
        print("fly with fuel")
  
class Fish:
    def swim(self):
        print("fish swim in sea")

for obj in Bird(), Airplane(), Fish():
    obj.fly()
fly with wings
fly with fuel



---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

d:\intro python\poo_en_python_with_plant.ipynb Cell 39' in <cell line: 13>()
     <a href='vscode-notebook-cell:/d%3A/intro%20python/poo_en_python_with_plant.ipynb#ch0000034?line=10'>11</a>         print("fish swim in sea")
     <a href='vscode-notebook-cell:/d%3A/intro%20python/poo_en_python_with_plant.ipynb#ch0000034?line=12'>13</a> for obj in Bird(), Airplane(), Fish():
---> <a href='vscode-notebook-cell:/d%3A/intro%20python/poo_en_python_with_plant.ipynb#ch0000034?line=13'>14</a>     obj.fly()


AttributeError: 'Fish' object has no attribute 'fly'

Como importamos dependencias externas

No se pierdan la sesión 3 y la ultima de esta serie de tutoriales

Vamos a hablar de como creamos un proyecto trabajando con ficheros individuales mostrando como consumir un API en python usando requests

Conclusión

Python es un lenguaje bastante potente en el cual puedes realizar entre otras cosas automatizaciones de tareas repetitivas, o bien practicar tu lógica en programación, de hecho seria interesante si en este ultimo bloque escribes una funcion que te diga si una palabra es palidroma o no, (se lee igual si escribes los caracteres al reves), y un conversor de temperaturas

DataCamp es una plataforma que sirve para aprender a programar (está en ingles)echa https://www.datacamp.com/courses/intro-to-python-for-data-science

Refactoring guru es un sitio donde se pueden encontrar ejemplos de como implementar patrones de código en distintos lenguajes de programación https://refactoring.guru/es/design-patterns/python

Curso de python para principiantes de microsoft https://docs.microsoft.com/es-es/shows/intro-to-python-development/

Magic methods in python https://www.netjstech.com/2019/06/operator-overloading-in-python.html

Clases en python https://pythondiario.com/2016/10/herencia-y-polimorfismo-en-python.html#:~:text=La%20herencia%20en%20Python%20nos%20permite%20a%20los,permite%20escribir%20un%20c%C3%B3digo%20m%C3%A1s%20limpio%20y%20legible.

Sobrecargada de operadores https://pharos.sh/sobrecargar-funciones-y-operadores-en-python/#:~:text=Sobrecarga%20del%20operador%20Python%20nos%20permite%20cambiar%20el,operadores%20de%20Python%20depende%20de%20las%20clases%20integradas.