IntroPython s2
IntroPython s2
programación en Python
Pedro Corcuera
Dpto. Matemática Aplicada y
Ciencias de la Computación
Universidad de Cantabria
[email protected]
Objetivos
Python 2
Índice
Python 3
Limitaciones de la programación
estructurada
• La descomposición de programas en funciones no es
suficiente para conseguir la reusabilidad de código.
• Es difícil entender, mantener y actualizar un
programa que consiste de una gran colección de
funciones.
• Con la programación orientada a objeto se supera las
limitaciones de la programación estructurada
mediante un estilo de programación en el que las
tareas se resuelven mediante la colaboración de
objetos.
Python 4
Programación orientada a objetos (OOP)
en Python
• Una clase es una plantilla de entidades del mismo
tipo. Una instancia es una realización particular de
una clase. Python soporta instancias de clases y
objetos.
• Un objeto contiene atributos: atributos de datos (o
variables) y comportamiento (llamados métodos).
Para acceder un atributo se usa el operador punto,
ejemplo: nombre_instancia.nombre_atributo
• Para crear una instancia de una clase se invoca el
constructor: nombre_instancia = nombre_clase(args)
Python 5
Objetos de clase vs Objetos de instancia
Python 6
Clases – representación UML
Python 7
Sintaxis de la definición de clase
• La sintaxis es:
class Class_name(superclass1, ...):
"""Class doc-string"""
class_var1 = value1 # Class variables
......
def __init__(self, arg1, ...):
"""Constructor"""
self.instance_var1 = arg1 # inst var by assignment
......
def __str__(self):
"""For printf() and str()"""
......
def __repr__(self):
"""For repr() and interactive prompt"""
......
def method_name(self, *args, **kwargs):
"""Method doc-string"""
......
Python 8
Contructores
Python 9
Contructor: Self
Python 11
Ejemplo – circle.py
• circle.py:
from math import pi
class Circle:
"""A Circle instance models a circle with a radius"""
def __init__(self, radius=1.0):
"""Constructor with default radius of 1.0"""
self.radius = radius # Create an inst var radius
def __str__(self):
"""Return string, invoked by print() and str()"""
return 'circle with radius of %.2f' % self.radius
def __repr__(self):
"""Return string used to re-create this instance"""
return 'Circle(radius=%f)' % self.radius
def get_area(self):
"""Return the area of this Circle instance"""
return self.radius * self.radius * pi
Python 12
Ejemplo – circle.py
• circle.py (cont.):
# if run under Python interpreter, __name__ is '__main__'.
# if imported into another module, __name__ is 'Circle'
if __name__ == '__main__':
c1 = Circle(2.1) # Construct an instance
print(c1) # Invoke __str__()
print(c1.get_area())
c2 = Circle() # Default radius
print(c2)
print(c2.get_area()) # Invoke member method
c2.color = 'red' # Create new attribute via assignment
print(c2.color)
#print(c1.color) # Error - c1 has no attribute color
# Test doc-strings
print(__doc__) # This module
print(Circle.__doc__) # Circle class
print(Circle.get_area.__doc__) # get_area() method
print(isinstance(c1, Circle)) # True
Python 13
Construcción de clase
Python 17
Clase Point y sobrecarga de operadores
Python 18
Clase Point y sobrecarga de operadores
def __mul__(self, factor):
"""Override the '*' operator"""
self.x *= factor
self.y *= factor
return self
# Test
if __name__ == '__main__':
p1 = Point()
print(p1) # (0.00, 0.00)
p1.x = 5 # direct access to property, bad idea
p1.y = 6
print(p1) # (5.00, 6.00)
p2 = Point(3, 4)
print(p2) # (3.00, 4.00)
print(p1 + p2) # (8.00, 10.00) Same as p1.__add__(p2)
print(p1) # (5.00, 6.00) No change
print(p2 * 3) # (9.00, 12.00) Same as p2.__mul__(3)
print(p2) # (9.00, 12.00) Changed
Python 19
Métodos especiales (mágicos)
Magic Method Invoked Via Invocation Syntax
__lt__(self, right) Comparison Operators self < right
__gt__(self, right) self > right
__le__(self, right) self <= right
__ge__(self, right) self >= right
__eq__(self, right) self == right
__ne__(self, right) self != right
Python 20
Métodos especiales (mágicos)
Python 21
Métodos especiales (mágicos)
Magic Method Invoked Via Invocation Syntax
__int__(self) Type Conversion Function int(self)
__float__(self) call float(self)
__bool__(self) bool(self)
__oct__(self) oct(self)
__hex__(self) hex(self)
__init__(self, *args) Constructor x = ClassName(*args)
__new__(cls, *args)
__del__(self) Operator del del x
__index__(self) Convert this object to an x[self]
index
__radd__(self, left) RHS (Reflected) addition, left + self
__rsub__(self, left) subtraction, etc. left - self
... ...
__iadd__(self, right) In-place addition, self += right
__isub__(self, right) subtraction, etc self -= right
... ...
Python 22
Métodos especiales (mágicos)
Python 23
Variables de clase
Python 25
Métodos de acceso (get) y
asignación (set)
• Mejora de la clase Circle con métodos get y set para
acceder las variables de instancia (circle1.py)
Python 26
Métodos de acceso (get) y
asignación (set)
"""circle.py: The circle module, which defines the Circle class"""
from math import pi
class Circle:
"""A Circle instance models a circle with a radius"""
def __init__(self, _radius = 1.0):
"""Initializer with default radius of 1.0"""
# Change from radius to _radius (meant for internal use)
# You should access through the getter and setter.
self.set_radius(_radius) # Call setter
def set_radius(self, _radius):
"""Setter for instance variable radius with input validation"""
if _radius < 0:
raise ValueError('Radius shall be non-negative')
self._radius = _radius
def get_radius(self):
"""Getter for instance variable radius"""
return self._radius
def get_area(self):
"""Return the area of this Circle instance"""
return self.get_radius() * self.get_radius() * pi # Call getter
Python 27
Métodos de acceso (get) y
asignación (set)
...
def __repr__(self):
"""Return a command string to recreate this instance"""
# Used by str() too as __str__() is not defined
return 'Circle(radius={})'.format(self.get_radius()) # Call getter
if __name__ == '__main__':
c1 = Circle(1.2) # Constructor and Initializer
print(c1) # Invoke __repr__(). Output:
Circle(radius=1.200000)
print(vars(c1)) # Output: {'_radius': 1.2}
print(c1.get_area()) # Output: 4.52389342117
print(c1.get_radius()) # Run Getter. Output: 1.2
c1.set_radius(3.4) # Test Setter
print(c1) # Output: Circle(radius=3.400000)
c1._radius = 5.6 # Access instance variable directly (NOT
# recommended but permitted)
print(c1) # Output: Circle(radius=5.600000)
c2 = Circle() # Default radius
print(c2) # Output: Circle(radius=1.000000)
Python 28
Herencia - Jerarquía
Python 29
Jerarquía de la clase Vehicle
• General
• Especializado
• Más específico
Python 30
La superclase object
Python 31
Herencia y polimorfismo
Python 32
Herencia
Python 33
Herencia
• cylinder.py (cont.)
if __name__ == '__main__':
cy1 = Cylinder(1.1, 2.2)
print(cy1)
print(cy1.get_area()) # inherited superclass' method
print(cy1.get_volume()) # Invoke its method
cy2 = Cylinder() # Default radius and height
print(cy2)
print(cy2.get_area())
print(cy2.get_volume())
print(dir(cy1))
print(Cylinder.get_area)
print(Circle.get_area)
c1 = Circle(3.3)
print(c1) # Output: circle with radius of 3.30
print(issubclass(Cylinder, Circle)) # True
print(issubclass(Circle, Cylinder)) # False
print(isinstance(cy1, Cylinder)) # True
Python 34
Sobreescritura (overriding) de métodos
Python 35
Ejemplo shape y subclases
• shape.py
Python 36
Herencia múltiple
• minh.py
• minh1.py
• minh2.py
• minh3.py
Python 37
Tipo de dato definido por el usuario –
Clase Charge
• Se define un tipo Charge para partículas cargadas.
• Se usa la ley de Coulomb para el cálculo del
potencial de un punto debido a una carga V=kq/r ,
donde q es el valor de la carga, r es la distancia del
punto a la carga y k=8.99 × 109 N m2/C2.
Constructor
Python 38
Convenciones sobre ficheros
Python 39
Elementos básicos de un tipo de dato
• API
Python 41
Creación de objetos, llamada de métodos
y representación de String
#-----------------
# chargeclient.py
#-----------------
import sys
from charge import Charge
# Acepta floats x e y como argumentos en la línea de comandos. Crea dos objetos
# Charge con posición y carga. Imprime el potencial en (x, y) en la salida estandard
x = float(sys.argv[1])
y = float(sys.argv[2])
c1 = Charge(.51, .63, 21.3)
c2 = Charge(.13, .94, 81.9)
v1 = c1.potentialAt(x, y)
v2 = c2.potentialAt(x, y)
print('potential at (%.2f, %.2f) due to\n', x, y)
print(' ' + str(c1) + ' and')
print(' ' + str(c2))
print('is %.2e\n', v1+v2)
#-----------------------------------------------------------------------
# python chargeclient.py .2 .5
# potential at (0.20, 0.50) due to
# 21.3 at (0.51, 0.63) and
# 81.9 at (0.13, 0.94)
# is 2.22e+12
Python 42
Clase Complex
Python 43
Sobrecarga de operadores
Python 44
Algoritmos de búsqueda
• Secuencial O(n)
• Búsqueda binaria O(logn)
Python 45
Algoritmos de ordenación
• Burbuja O(n2)
• Inserción O(n2)
• Selección O(n2)
• Mezcla O(n logn)
• Quicksort O(n logn)
Python 46
Estructuras de datos
Python 47