You are on page 1of 322

Programacin Orientada a Objetos

(POO) en Python

Classes y Tipos de Datos Abstractos


Tema 2

Petia Ivanova Radeva

ndice

Clases y objetos

Clases y atributos
Datos
Mtodos
Constructor

Objetos encrustados

Clases mutables y copias

Tema 2

POO en Python

Petia Ivanova Radeva

Casi todo en Python es objeto

Cada variable en Python es de hecho un objeto.


Hemos visto ejemplos de objetos ya ...
>>>hello.upper()
>>>list3.append(a)
>>>dict2.keys()
Estos comandos parecen a llamadas a mtodos en Java o C ++ .
Adems de estos tipos de datos incorporados, podemos tambin disear
nuestros propios objetos ...?

De hecho, la programacin en Python se realiza normalmente de


forma orientada a objetos.
Petia Ivanova Radeva

Clases y objetos: definicin de nuevos tipos


Consideremos que hemos de representar un punto:

x,y=1,0
Cmo representamos muchos puntos?

, , , = , , ,
xy= [[ , ],[ , ]]
Creamos un nuevo tipo: Punto

# Fichero Point.py:
class Point:
represents a point in 2-D space
.

Cmo comprobamos si entre dos puntos cul es el que est ms lejos del centro de
coordenadas?

Df: Los tipos definidos por el usuario se llaman clases.


Tema 2

POO en Python

Petia Ivanova Radeva

Definicin de una clase

Una clase es un tipo de datos especial que define cmo


construir un cierto tipo de objeto.

La "clase" tambin almacena parte de los datos que son


compartidos por todas las instancias de esta clase.

"Instancias" son objetos que se crean que siguen la definicin


dada en el interior de la clase.

Python no utiliza definiciones de interfaz de clases separadas.


Directamente definimos la clase y ya la podemos usar.
Petia Ivanova Radeva

Clases y objetos: Instanciacin


class Point:
represents a point in 2-D space
.
>>>pnt=Point() #creamos un objeto de tipo Point

Df: Una instancia de una clase se llama objeto. El proceso se llama


instanciacin.
Ejemplo: Lassy vs. perro, class Point, pnt=Point()
>>> pnt2=Point()
>>>pnt3=Point() # creamos tantos objetos como necesitamos

Los objetos estn referenciados por variables de tipo igual al nombre de la classe.
Tema 2

POO en Python

Petia Ivanova Radeva

Clases y objetos:
La varia le a contiene
referencia que apunta a:
Objeto de tipo Point e.d.
instancia de la clase Point en
direccin 0x0F45

La varia le contiene
referencia que apunta a:

Definicin de la clase:
b=Point()

Objeto de tipo Point e.d.


instancia de la clase Point en
direccin 0x6F48

class Point:
#cdigo...
La varia le contiene
referencia que apunta a:
Objeto de tipo Point e.d.
instancia de la clase Point en
direccin 0xFF25

Tema 2

POO en Python

Petia Ivanova Radeva

Clases y objetos: Tipo de Datos Abstracto (clase)

Tipo de Datos Abstracto (TDA) descripcin lgica sobre:


El estado del objeto (sus datos)
Los mtodos del objeto (qu puede hacer).
Se implementa a travs de las clases.
Definimos la clase como:
class <class-name>:
<method-definitions>

Una clase es un tipo de datos abstracto que contiene algo y define qu se


puede operar con este algo .
1. Una coleccin de informacin relevante.
2. Un conjunto de operaciones para manipular esta informacin.

La informacin est guardada en variables objetos (instancias de las clases).


Petia Ivanova Radeva

ndice

Clases y objetos

Clases y atributos
Datos
Mtodos
Constructor

Objetos encrustados

Clases mutables y copias

Tema 2

POO en Python

Petia Ivanova Radeva

Clases y atributos: Datos

Python permite asignar valores y crear atributos usando el operador . :

>>>blank=Point() # crea objeto de tipo Point


>>> blank.x = 3.0 # crea los datos del objeto,
>>> blank.y = 4.0

Df. Diagrama del objeto diagrama del estado que indica los
valores de los atributos del objeto:

Tema 2

POO en Python

Petia Ivanova Radeva

10

Clases y atributos: Datos y su acceso

Leemos los valores de los datos usando la misma sintaxis:

>>>blank=Point()
>>>print blank.y
4.0
>>> x = blank.x
>>> print x
3.0
>>> print ( + str(blank.x) + , + str(blank.y) + )
>>> distanceSquared = blank.x * blank.x + blank.y * blank.y

Tema 2

POO en Python

Petia Ivanova Radeva

11

ndice

Clases y objetos

Clases y atributos
Datos
Mtodos
Constructor

Objetos incrustados

Clases mutables y copias


Tema 2

POO en Python

Petia Ivanova Radeva

12

Clases y atributos: mtodos (funciones)

Vamos a definir la clase Tiempo:

class Time(object):
"""represents the time of day.
attributes: hour, minute, second""
>>>time = Time()
>>>time.hour = 11
>>>time.minute = 59
>>>time.second = 30

Tema 2

POO en Python

Petia Ivanova Radeva

13

Clases y atributos: mtodos (funciones)


Definir un mtodo que imprime los valores del objeto de la clase:
class Time:
"""represents the time of day.
attributes: hour, minute, second"""
def print_time(time): # funcin global
print '%.2d:%.2d:%.2d' % (time.hour, time.minute,
time.second)
>>>
>>>
>>>
>>>

start = Time() # creamos el objeto


start.hour = 9
start.minute = 45
start.second = 00

>>> print_time(start)
09:45:00
Tema 2 POO
en Python
Petia
Ivanova
Radeva
Ha de ser una funcin
global?
Cmo definir una funcin de
una
clase?

14

Clases y atributos: mtodos (funciones)


Cmo definir una funcin de una clase?:

Podemos definir un mtodo en una clase mediante la inclusin de la definicin de


funciones dentro del mbito del bloque de clases.

class Time(object):
def print_time(self): #mtodo de la clase
print '%.2d:%.2d:%.2d % (self.hour, self.minute, self.second)

Definimos el mtodo de la clase como una funcin (usando def) dentro de la


clase

Cul es el primer argumento de los mtodos de una clase?

self permite distinguir los atributos de la clase de los datos globales.


Por qu es importante?

Tema 2

POO en Python

Petia Ivanova Radeva

15

Clases y atributos: mtodos (funciones)


class Time:
def print_time(self): #mtodo de la clase
print '%.2d:%.2d:%.2d % (self.hour, self.minute, self.second)

>>> start=Time()
>>>start.hour=9
>>>start.minute=45
>>>start.second=00
>>> print start.hour # imprimimos el dato hour de
9
>>>start.print_time() #llamamos el mtodo de la clase con el objeto (start)
09:45:00
>>>start2=Time()
.

Llamamos los mtodos y los datos desde fuera de la clase:


con el nombre del objeto de la clase. Por qu?
Tema 2

POO en Python

Petia Ivanova Radeva

16

Clases y atributos: mtodos (funciones)


class Time(object):
def print_time(self):
def increment(self, seconds): #mtodo de la clase
seconds += self.time_to_int() #llamamos los mtodos de la clase con
self
return self.int_to_time(seconds)
def time_to_int(self):
self.minutes = self.hour * 60 + self.minute
self.seconds = self.minutes * 60 + self.second # recuperamos los datos del
objeto con self
return self.seconds
def int_to_time(self,seconds):
>>> start=Time()
>>>start.print_time() #llamamos el mtodo de la clase con el objeto (start)
09:45:00
>>> end = start.increment(1337)
>>> end.print_time()
10:07:17

Llamamos los mtodos y los datos desde dentro de la clase:


Con la lave self !

Dnde se declaran los datos? Pueden declararse en cualquier mtodo?


Tema 2

POO en Python

Petia Ivanova Radeva

17

Clases y atributos: mtodos (funciones)


Usando dos objetos:
class Time (object):
# inside class Time:
def is_after(self, other):
return self.time_to_int() > other.time_to_int()
>>> start.print_time()
09:15:00
>>> end.print_time()
09:45:00
>>>end.is_after(start)
True

Por qu la llamada de la funcin tiene slo un argumento?


Tema 2

POO en Python

Petia Ivanova Radeva

18

Clases y atributos: mtodos puros


def add_time(t1, t2): #t1, t2 objetos de tipo Time
sum = Time()
sum.hour = t1.hour + t2.hour
sum.minute = t1.minute + t2.minute
sum.second = t1.second + t2.second
if sum.second >= 60:
sum.second -= 60
sum.minute += 1

if sum.minute >= 60:


sum.minute -= 60
sum.hour += 1

return sum

Df: Las funciones puras no modifican los valores de los objetos.


Tema 2

POO en Python

Petia Ivanova Radeva

19

Clases y atributos: mtodos puros


class Time(object):
def getHour(self):
return self.hour
def setHour(self,hour):
self.hour=hour
def add_time(t1, t2): #t1, t2 objetos de tipo Time
sum = Time()
sum.setHour(t1.getHour() + t2.getHour())
sum.setMinute(t1.getMinute() + t2.getMinute())
sum.setSecond(t1.getSecond() + t2.getSecond())
if sum.getSecond() >= 60:
sum.setSecond(sum.getSecond() 60)
sum.setMinute(sum.getMinute + 1)
if sum.getMinute() >= 60:
sum.setMinute(sum.getMinute() 60)
sum.setHour(sum.getHour() + 1)
return sum
La forma correcta para acceder a los valores de las clases es a travs de los mtodos getValor().
Tema 2

POO en Python

Petia Ivanova Radeva

20

Clases y atributos: mtodos modificadores


Df. Funciones modificadoras modifican los valores de sus parmetros
def increment(time, seconds):
time.setSecond(time.getSecond() + seconds)
if time.getSecond() >= 60:
time.setSecond(time.getSecond() 60)
time.setMinute(time.getMinute() + 1)
if time.getMinute() >= 60: #sustituir el if con while!
time.setMinute(time.getMinute() 60)
time.setHour(time.getHour() + 1)

La forma correcta para modificar a los valores de las clases es a travs de los mtodos setValor().

Estilo de programacin funcional: siempre que se pueda, utilizar funciones puras.


Hace ejecutar ms rpido los programas.
Se obtienen menos errores de la ejecucin.
Tema 2

POO en Python

Petia Ivanova Radeva

21

Clases y atributos: mtodos modificadores


Df. Funciones modificadores modifican los valores de sus parmetros
def increment(self, seconds):
self.setSecond(self.getSecond() + seconds)
if self.getSecond() >= 60:
self.setSecond(self.getSecond() 60)
self.setMinute(self.getMinute() + 1)
if self.getMinute() >= 60: #sustituir el if con while!
self.setMinute(self.getMinute() 60)
self.setHour(self.getHour() + 1)

Las funciones modificadores definirlas como mtodos de la clase.

Tema 2

POO en Python

Petia Ivanova Radeva

22

Clases y atributos

Python lenguaje de Programacin orientada a objetos


Programas compuestos por definiciones de clases y funciones donde la parte ms
importante de computacin -> las operaciones de los objetos.
Cada definicin de clase corresponde a un concepto del mundo real y las funciones de las
clases corresponden a la interaccin de los objetos.

Df. Un mtodo es una funcin asociada con una clase (p.e. concatenacin de
cadenas).

Diferencia entre funciones globales y mtodos:


Estn definidos dentro de una clase para explicitar la relacin entre la clase y el mtodo.
Tiene sintaxis diferente de las funciones globales.

Tema 2

POO en Python

Petia Ivanova Radeva

23

Clases y atributos: cmo instanciamos un


objeto?

Constructor: Mtodo especial que construye e inicializa un objeto al declararlo de


una clase.

class Time(object):
def __init__(self, hour=0, minute=0, second=0):
#coincidencia de los nombres
self.hour = hour
# define los atributos de la
clase
self.minute = minute
self.second = second

>>>t1=Time(1,2,3)

Al crear un objeto, donde se llama el constructor e.d. se usa explicitamente __init__()?!


Tema 2

POO en Python

Petia Ivanova Radeva

24

Constructor: __init__

El mtodo __init__ puede tomar cualquier nmero de argumentos.


Al igual que otras funciones o mtodos, los argumentos pueden ser definidos con valores
por defecto.
Sin embargo, el primer argumento en la definicin de __init__ es especial ...

En __init__, self se refiere al objeto que se est creando actualmente;


mientras, en los otros mtodos de la clase, se refiere a la instancia cuyo
mtodo fue llamado.
De manera similar a la palabra clave this' en Java o C ++.

Petia Ivanova Radeva

Clases y atributos: mtodos (funciones)


class Time(object):
def print_time(self):
def increment(self, seconds): #mtodo de la clase
seconds += self.time_to_int()
#llamamos los mtodos de la clase con self
return self.int_to_time(seconds)
def time_to_int(self):
self.minutes = self.hour * 60 + self.minute
self.seconds = self.minutes * 60 + self.second # recuperamos los
datos del objeto con self
return self.seconds
def int_to_time(self,seconds):
>>> start=Time()
>>>start.print_time() #llamamos el mtodo de la clase con el objeto (start)
09:45:00
>>> end = start.increment(1337)
>>> end.print_time()
10:07:17

Llamamos los mtodos y los datos desde dentro de la clase:


Con la lave self !

Dnde se declaran los datos? Pueden declararse en cualquier mtodo?


Tema 2

POO en Python

Petia Ivanova Radeva

26

Self

Recordar:
Aunque se debe especificar self de forma explcita en la
definicin del mtodo, no es necesario incluirla en la llamada
al mtodo.
Python lo pasa de forma automtica.

Definicin del mtodo:

Llamada al mtodo:

(este cdigo va dentro de la definicin de la clase)

def setMinute(self, num):


self.minutes = num

>>> x.setMinute(23)

Petia Ivanova Radeva

No hace falta liberar espacio (free)

Cuando hayamos terminado con un objeto, no hace falta


eliminar o liberar explcitamente la memoria.
Python tiene el garbage collection automtico (recoleccin de basura
automtica).
Python detectar automticamente cuando todas las referencias a una
parte de memoria han sido fuera de alcance. Y liberar
automticamente la memoria.
Trabaja generalmente bien, pocas prdidas de memoria.
No hay ningn mtodo "destructor" para las clases.
Petia Ivanova Radeva

Clases y atributos: el constructor


Cmo definir los atributos datos de la clase?
class Time(object):
def __init__(self, hour=0, minute=0, second=0): #coincidencia
de los nombres
self.hour = hour
# define los atributos de la clase
self.minute = minute
self.second = second
def time_to_int(self):
self.minutes = self.hour * 60 + self.minute
self.seconds = self.minutes * 60 + self.second
# recuperamos los datos del objeto con
self
return self.seconds

>>> print t1.seconds

Al declarar un dato dentro de un mtodo con self, automticamente lo convertimos


en atributo de la clase.
Se desanconseja inicializar los datos fuera de la clase!
Tema 2

POO en Python

Petia Ivanova Radeva

29

Clases y atributos: el constructor


Df: El proceso de separar los detalles de implementacin y organizar
los atributos (datos y mtodos) dentro de las clases se llama
encapsulamiento.
class Time(object):
pass
>>>t1=Time()
>>>t1.hour=1 #evitar
>>>t1.minute=15
>>>t1.second=20

NO!!!

class Time(object):
def __init__(self, hour=0,
minute=0, second=0):
#coincidencia de los
nombres
self.hour = hour
self.minute = minute
self.second = second
def time_to_int(self).
>>>t1=Time(1,2,3)

Tema 2

POO en Python

Petia Ivanova Radeva

30

Clases y atributos: el constructor


Valores opcionales del constructor
>>> time = Time()
__init__(self,)
>>> time.print_time()
defecto/opcionales
00:00:00
>>> time = Time (9)
>>> time.print_time()
09:00:00
los valores opcionales
>>> time = Time(9, 45)
>>> time.print_time()
09:45:00
Tema 2

POO en Python

# se llama el constructor
# con los valores por

# no se aplican

# van por orden

Petia Ivanova Radeva

31

Acceso a los atributos y los


mtodos

Definimos la clase student


class student:
A class representing a student.
def __init__(self,n,a):
self.full_name = n
self.age = a
def get_age(self):
return self.age

Petia Ivanova Radeva

Sintxis tradicional de acceso


>>> f = student (Bob Smith, 23)
>>> f.full_name
Bob Smith
>>> f.get_age()
23

# Access an attribute.

# Access a method.

Petia Ivanova Radeva

Accediendo atributos desconocidos

Qu pasa si no sabemos el nombre del atributo o mtodo de


una clase que deseamos acceder hasta el tiempo de
ejecucin ...

Hay una manera de tomar una cadena que contiene el


nombre de un atributo o mtodo de una clase y obtener una
referencia a l (para que pueda usarlo)?

Petia Ivanova Radeva

getattr(object_instance, string)
>>> f = student(Bob Smith, 23)
>>> getattr(f, full_name)
Bob Smith
>>> getattr(f, get_age)
<method get_age of class studentClass at 010B3C2>
>>> getattr(f, get_age)()
23

# We can call this.

>>> getattr(f, get_birthday)


# Raises AttributeError No method exists.
Petia Ivanova Radeva

hasattr(object_instance,string)
>>> f = student(Bob Smith, 23)
>>> hasattr(f, full_name)
True
>>> hasattr(f, get_age)
True
>>> hasattr(f, get_birthday)
False

Petia Ivanova Radeva

Atributos

Dos tipos de atributos

Los datos (que no son mtodos) almacenado por objetos se


denominan atributos. Hay dos tipos:

Atributo de datos: Variable propiedad de un caso particular


de una clase
Cada instancia puede tener su propio valor diferente para ella Estos
son el tipo ms comn de atributo.

Los atributos de clase: Propiedad de la clase en su conjunto.


Todas las instancias de la clase comparten el mismo valor para l.
Llamado variables "estticas" en algunos lenguajes?
til para constantes en toda la clase o para la construccin de contador
de cuntas instancias de una clase se han hecho.
Petia Ivanova Radeva

Atributos de datos

Se crean e inicializan los atributo de datos dentro del mtodo


__init __ ().
Recuerde la asignacin se utiliza para crear las variables en Python;
as, la asignacin de un nombre crea el atributo.

Dentro de la clase, los atributos de datos se obtienen via self:


p.e., self.full_name

class teacher:
A class representing teachers.
def __init__(self,n):
self.full_name = n
def print_name(self):
print self.full_name
Petia Ivanova Radeva

Atributos de la clase

Todas las instancias de una clase comparten una copia de un atributo


de clase, por lo que cuando cualquiera de las instancias lo cambia,
entonces el valor se cambia para todos ellos.

Definimos los atributos de clase fuera de cualquier mtodo.

Puesto que no es uno de estos atributos por clase y no una por


ejemplo, utilizamos una notacin diferente: accedemos a travs del
nomber de la clase: self.__class__.name.

class sample:
x = 23
def increment(self):
self.__class__.x += 1

>>> a = sample()
>>> a.increment()
>>> a.__class__.x
24
Petia Ivanova Radeva

Datos vs. atributos de la clase


class counter:
overall_total = 0
# class attribute
def __init__(self):
self.my_total = 0
# data attribute
def increment(self):
counter.overall_total = \
counter.overall_total + 1
self.my_total = \
self.my_total + 1

>>>
>>>
>>>
>>>
>>>
>>>
1
>>>

a = counter()
b = counter()
a.increment()
b.increment()
b.increment()
a.my_total
a.__class__.overall_total

3
>>> b.my_total
2
>>> b.__class__.overall_total
3

Petia Ivanova Radeva

ndice

Clases y objetos

Clases y atributos
Datos
Mtodos
Constructor

Objetos encrustados

Clases mutables y copias


Tema 2

POO en Python

Petia Ivanova Radeva

43

Objetos encrustados

Cmo definir la clase Rectngulo?


A travs de un punto, anchura y altura
class Point(object):
def __init__(self,x,y):
self.x, self,y=x, y
class Rectangle(object):
"""represent a rectangle. attr: width, height, corner"
def __init__(self, width, height, cornerx, cornery):
self.width, self.height=width, height
self.corner=Point(cornerx,cornery)

Df. Un objeto que es un atributo de otro objeto se llama encrustado (embedded).


Tema 2

POO en Python

Petia Ivanova Radeva

44

Objetos incrustados:
Instancias de objetos como valores de retorno
# En la clase Rectangle:
def find_center(self):
return Point(self.corner.x + self.width/2.0,
self.corner.y +
self.height/2.0)
>>> mibox = Rectangle(100,200,0,0)
>>> center=mibox.find_center()
>>> print center
(50.0, 100.0)
Qu sucede con el objeto que retorna la funcin find_center()?

>>>a=[]
>>>a.append(Point(10,4))
Tema 2

POO en Python

Petia Ivanova Radeva

45

ndice

Clases y objetos

Clases y atributos
Datos
Mtodos
Constructor

Objetos encrustados

Clases mutables y copias


Tema 2

POO en Python

Petia Ivanova Radeva

46

Clases mutables y copias: los objetos son mutables!


class Rectangle(object):
.

def grow_rectangle(self, dwidth, dheight) :


self.width += dwidth
self.height += dheight

>>> print mibox


100 200
>>>mibox2=mibox
>>> mibox2.grow_rectangle(50, 100)
>>> print mibox

Habrn cambiado los valores de los atributos?

Tema 2

POO en Python

Petia Ivanova Radeva

47

Clases mutables y copias: los objetos son mutables!

Utilizar el aliasing puede ser confuso, no darnos cuenta de los


cambios de valores de los objetos.
Cul sera la alternativa?

>>> mibox2 = mibox


>>> print mibox2 is mibox
True
>>> print mibox2==mibox
True
Comprueba la identidad o la equivalencia?

Tema 2

POO en Python

>>> mibox2 =
copy.copy(mibox)
>>> print mibox2 is mibox
False
>>> print mibox2==mibox
False
Petia Ivanova Radeva

48

Clases mutables y copias: los objetos son


mutables!
>>> mibox2 = copy.copy(mibox)
>>> mibox2 is mibox
False
>>> mibox2.corner is mibox.corner
True

copy.copy copia los valores simples pero no los atributos


encrustados! Copia dbil (shallow copy)
Tema 2

POO en Python

Petia Ivanova Radeva

49

Clases mutables y copias: los objetos son


mutables!
>>> mibox2 = copy.deepcopy(mibox)
>>> mibox2 is mibox
False
>>> mibox2.corner is mibox.corner
False
Se puede decir que mibox2 y mibox son completamente objetos
diferentes?
Df. La copia profunda (deep copy) copia recursivamente todos los atributos
encrustados.

Tema 2

POO en Python

Petia Ivanova Radeva

50

Conclusiones

Python es un lenguaje orientado a objetos, potente y fcil de programar.

Las classes permiten implementar tipos de datos abstractos.

El encapsulamiento de los datos y los mtodos es un proceso de organizarlos en clases


donde se separa la interfaz de la clase de la implementacin de sus mtodos.

Los constructores son mtodos de las clases que tienen el objetivo de crear los objetos e
inicializar sus valores.
Se ha de evitar inicializar los datos de la clase fuera de los constructores.

La forma correcta para acceder a los valores de las clases es a travs de funciones getValor()
y setValor().
Por defecto, intentar definir los mtodos como mtodos puros.

Se pueden incrustar objetos dentro de objetos.

Las clases son tipos de datos mutables


Una solucin es copiar los objetos usando la copia simple o la copia profunda.
Tema 2

POO en Python

Petia Ivanova Radeva

51

Programacin Orientada a Objetos


(POO) en Python
Polimorfismo, encapsulamiento y
herencia
Tema 3

Pictures and some slides from:


Matt Huenerfauth
University of Pennsylvania

Petia Ivanova Radeva


ltima correccin: 19/02/2015
1

ndice

Acceso a los atributos y los mtodos

Tipos de atributos

Objetos incrustados

Clases mutables y copias

Encapsulamiento

Polimorfismo y sobrecarga

Herencia
Tema 2

POO en Python

Petia Ivanova Radeva

Consideremos la siguiente lista de estudiantes


students=[[ Bob Smith , 23],[Anna
Kournikova, 25], [Andy Roddick, 28]]

Cmo convertirla en una lista de objetos?


class Student:
A class representing
a student.
def __init__(self,n,a):
self.full_name = n
self.age = a

>>>f = Student( Bob Smith , 23)


# Crea el objeto
>>>print f.full_name
# Acceso a un atributo.
Bob Smith
# No recomendable! ?

Petia Ivanova Radeva

Consideremos la siguiente lista de estudiantes


class Student:
A class representing a
student.
def __init__(self,n,a):
self.full_name = n
self.age = a
def get_name(self):
return self.full_name
def get_age(self):
return self.age

>>>f = Student( Bob Smith , 23)


# Crea el objeto
>>>print f.full_name
# Acceso a un atributo.

Bob Smith

>>>f.get_name() # Acceso a mtodo.


Bob Smith
>>>f.get_age() # Acceso a mtodo.
23

>>> lista=[]
>>> lista.append(Student( Bob Smith , 23))
>>> lista.append(Student(Anna Kournikova, 25))

Petia Ivanova Radeva

Accediendo atributos desconocidos

Qu pasa si no sabemos el nombre del atributo o mtodo de


una clase que deseamos acceder hasta el tiempo de
ejecucin ?...

Hay una manera de tomar una cadena que contiene el


nombre de un atributo o mtodo de una clase y obtener una
referencia a l (para que pueda usarlo)?

Petia Ivanova Radeva

getattr(object_instance, string)
>>> f = Student( Bob Smith , 23)
>>> getattr(f,
Bob Smith

full_name )

>>> getattr(f, get_age )


<method get_age of class studentClass at 010B3C2>
>>> getattr(f,
23

get_age )()

# We can call this.

>>> getattr(f, get_birthday )


# Raises AttributeError No method exists.
Petia Ivanova Radeva

hasattr(object_instance,string)
>>> f = Student( Bob Smith , 23)
>>> hasattr(f,
True

full_name )

>>> hasattr(f,
True

get_age )

>>> hasattr(f,
False

get_birthday )

Petia Ivanova Radeva

ndice

Acceso a los atributos y los mtodos

Tipos de atributos

Objetos incrustados

Clases mutables y copias

Encapsulamiento

Polimorfismo y sobrecarga

Herencia
Tema 2

POO en Python

Petia Ivanova Radeva

Dos tipos de atributos

Los datos (que no son mtodos) almacenados en los objetos se


denominan atributos. Hay dos tipos:

Atributos de objetos: Variable propiedad de un objeto particular de una


clase
Cada instancia puede tener su propio valor diferente para ella, el tipo ms
comn de atributo.
Ejemplo: Student name -> Ba y Bo ds

Atributos de clases: Propiedad de la clase en su conjunto.


Todas las instancias de la clase comparten el mismo valor para l.
Llamado variables "estticas" en algunos lenguajes.
til para constantes en toda la clase o para la construccin de contador de
cuntas instancias de una clase se han hecho.
Ejemplo: Student edad de selectividad -> 18
Petia Ivanova Radeva

Atributos de datos

Se crean e inicializan los atributo de objetos dentro del


mtodo __init __ ().
Recuerde la asignacin se utiliza para crear las variables en Python;
as, la asignacin de un nombre crea el atributo. (p=Student(..))

Dentro de la clase, los atributos de objetos se obtienen via


self: p.e., self.full_name

class Teacher:
A class representing teachers.
def __init__(self,n):
self.full_name = n
def print_name(self):
print self.full_name
Petia Ivanova Radeva

Atributos de la clase

Todas las instancias de una clase comparten una copia de un atributo


de clase, por lo que cuando cualquiera de las instancias lo cambia,
entonces el valor se cambia para todos ellos.

Definimos los atributos de clase fuera de cualquier mtodo.

Puesto que es un atributo para toda la clase y no de un objeto:


accedemos a travs de: self.__class__.name o a travs del
nombre de la clase.

class Sample:
x = 23
def increment(self):
self.__class__.x += 1
Sample.x+=1

>>> a = Sample()
>>> a.increment()
>>> print a.__class__.x
24
>>> print Sample.x
24
Petia Ivanova Radeva

Atributos de objetos vs de la clase


class Counter:
overall_total = 0
# class attribute
def __init__(self):
self.my_total = 0
# data attribute
def increment(self):
Counter.overall_total = \
Counter.overall_total + 1
self.my_total = \
self.my_total + 1

>>> a = Counter()
>>> b = Counter()
>>> Counter.overall_total
0

>>>
>>>
>>>
>>>
1
>>>

a.increment()
b.increment()
b.increment()
a.my_total
a.__class__.overall_total

3
>>> b.my_total
2
>>> b.__class__.overall_total
3

til para constantes en toda la clase o para la construccin de contador de


cuntas instancias de una clase se han hecho.
Petia Ivanova Radeva

ndice

Acceso a los atributos y los mtodos

Tipos de atributos

Objetos incrustados

Clases mutables y copias

Encapsulamiento

Polimorfismo y sobrecarga

Herencia
Tema 2

POO en Python

Petia Ivanova Radeva

13

Objetos incrustados

Cmo definir la clase Rectngulo?


A travs de un punto, anchura y altura
class Point:
"""represents a point in a plane"
def __init__(self,x,y):
self.x, self.y=x, y

class Rectangle:
"""represents a rectangle. attr: width, height, corner"
def __init__(self, width, height, cornerx, cornery):
self.width, self.height=width, height
self.corner=Point(cornerx,cornery)

Df. Un objeto que es un atributo de otro objeto se llama incrustado (embedded).


Tema 2

POO en Python

Petia Ivanova Radeva

14

Objetos incrustados:
Instancias de objetos como valores de retorno
# En la clase Rectangle:
def find_center(self):
return Point(self.corner.x + self.width/2.0,
self.corner.y + self.height/2.0)

>>> box = Rectangle(100,200,0,0)


>>> center=box.find_center()
>>> print center
(50.0, 100.0)
Tema 2

POO en Python

Petia Ivanova Radeva

15

Objetos incrustados:
Instancias de objetos como valores de retorno
# En la clase Rectangle:
def find_center(self):
return Point(self.corner.x + self.width/2.0,
self.corner.y + self.height/2.0)

Qu sucede con el objeto que retorna la funcin find_center()?

>>>a=[]
>>>a.append(Point(10,4))
>>>a.append(center)

Tema 2

POO en Python

Petia Ivanova Radeva

16

ndice

Acceso a los atributos y los mtodos

Tipos de atributos

Objetos incrustados

Clases mutables y copias

Encapsulamiento

Polimorfismo y sobrecarga

Herencia
Tema 2

POO en Python

Petia Ivanova Radeva

17

Clases mutables y copias: los objetos son mutables!


Qu significa que un objeto es mutable?
Ejemplos?!
class Rectangle:
def grow_rectangle(self, width, height):
#funcin pura o modificadora?
self.width += width
self.height += height
>>> print box
100 200
>>> box2=box
>>> box2.grow_rectangle(50, 100)
>>> print box

Habrn cambiado los valores de los atributos del objeto box?


Tema 2

POO en Python

Petia Ivanova Radeva

18

Clases mutables y copias: los objetos son mutables!

Utilizar el aliasing puede ser confuso, no darnos cuenta de los cambios de


valores de los objetos.
Cul sera la alternativa?

>>> box2 = box


>>> print box2 is box
True
>>> print box2==box
True
Comprueba la identidad o la equivalencia?

Tema 2

POO en Python

>>> import copy


>>> box2 = copy.copy(box)
>>> print box2 is box
False
>>> print box2==box
False
Petia Ivanova Radeva

19

Clases mutables y copias: los objetos son


mutables!
>>> box2 = copy.copy(box)
>>> box2 is box
False
>>> box2.corner is box.corner
True

copy.copy copia los valores simples, pero no los atributos


incrustados! Copia dbil (shallow copy)
Tema 2

POO en Python

Petia Ivanova Radeva

20

Qu ocurre cuando hacemos box2=copy.copy(box)?

Tema 2

POO en Python

Petia Ivanova Radeva

21

Clases mutables y copias: los objetos son


mutables!
>>> box2 = copy.deepcopy(box)
>>> box2 is box
False
>>> box2.corner is box.corner
False

Se puede decir que box2 y box son completamente objetos diferentes?


Df. La copia profunda (deep copy) copia recursivamente todos los atributos
incrustados.

Tema 2

POO en Python

Petia Ivanova Radeva

22

ndice

Acceso a los atributos y los mtodos

Tipos de atributos

Objetos incrustados

Clases mutables y copias

Encapsulamiento

Polimorfismo y sobrecarga

Herencia
Tema 2

POO en Python

Petia Ivanova Radeva

23

Datos pblicos y privados


class Fraction:

.
Construimos el objeto:
>>>myfraction=Fraction(3,5)
>>>print myfraction.den
# llamamos un dato de la clase
No recomendable! La forma correcta ser:
>>>myfraction.imprimir()
# llamamos un mtodo de la clase
Y o pode os p ohi i el a eso a los at i utos?
Tema 2

POO en Python

Petia Ivanova Radeva

24

Datos pblicos y privados


class Fraction:
def __init__(self,top,bottom): # el constructor
self.__num = top # self.__num dato del objeto
self.__den = bottom
Datos privados: de uso slo por los atributos de la clase (empiezan con el
p efijo: __ .

Al llamar desde fuera:


>>> f=Fraction(3,4)
>>> f.__init__(2,2)

Tema 2

#se llama al constructor de la clase.


#llamada equivalente

POO en Python

Petia Ivanova Radeva

25

Datos pblicos y privados


class Fraction:
.
def imprimir(self): #mtodo de la clase
print self.__num # datos de la clase
print self.__den
self.__auxiliar() # Its OK
def __auxiliar(self):
print This is an auxiliar function
>> f=Fraction(1,2)
>>print f.__num -> Error!
>>f.__auxiliar() -> Error!
Tema 2

POO en Python

Petia Ivanova Radeva

26

Datos pblicos y privados


class Fraction:
def __show(self):
print self.__num # self.num
# dato del objeto
print self.__den
def test(self):
self.__num=0 #variable de la clase
x=100 #variable local
self.__show()
Qu lneas darn error?
>>>f=Fraction()
>>>f.test()
>>>print f.__den
>>>print x
Tema 2

POO en Python

Petia Ivanova Radeva

27

Encapsulamiento

Significa tratar los datos que pertenecen a un objeto de


forma prediseada.
Podemos ir ms all y ocultar los datos de un objeto a
cualquier otro objeto o cdigo que trate de hacer uso de
ellos.

Seran slo accesibles al propio objeto y, en algunos


casos, a objetos de sus clases descendientes.

Tema 2

POO en Python

Petia Ivanova Radeva

28

Encapsulamiento
Hay muchos datos que no tiene porque conocerlo aquel que est
usando la clase; ya que son inherentes al objeto y slo controlan
su funcionamiento interno

cuando alguien nos ve puede saber inmediatamente si eres hombre o mujer


(propiedad) o puede hablarte y obtener una respuesta procesada (metodo);
tambien puede conocer el color de tu cabello y ojos.
pero jams sabra qu cantidad de energa exacta tienes, o cuntas neuronas
te quedan, ni siquiera preguntndote ya que ninguna de tus propiedades
externas visibles o funciones de comunicacin al publico tienen acceso a esos
datos.

El encapsulamiento u ocultacin: hacer privadas (ocultas) las


variables que son innecesarias para el tratamiento del objeto pero
necesarias para su funcionamiento privado

asi como las funciones que no necesitan interaccin del usuario o


que slo pueden ser llamadas por otras funciones del mismo objeto.
Tema 2

POO en Python

Petia Ivanova Radeva

29

Encapsulamiento

Para proteger a las variables de modificaciones no deseadas se introduce


el concepto del encapsulamiento.

Los miembros de una clase se pueden dividir en pblicos y privados.


Los miembros pblicos se pueden acceder libremente desde fuera de la clase.
Los miembros privados solamente pueden ser accedidos por los mtodos de la
propia clase.

El acceso a un atributo o a los mtodos viene determinado por su


nombre.
Si el nombre comienza con dos guiones bajos p.e. self.__denum (y no termina
con dos guiones bajos, p.e. __init__) es un atributo o mtodo privado.
En cualquier otro caso, es pblico.
Tema 2

POO en Python

Petia Ivanova Radeva

30

Encapsulamiento
El encapsulamiento es muy conveniente y nos permite colocar nuestro objeto
en funcionamiento en cualquier tipo de sistema, de una manera modular y
escalable (algunas de las reglas de la ingenieria del software).

Formas de encapsular definiendo los atributos como:

1. Pblicos: Hace que el miembro de la clase pueda ser accedido desde el


exterior de la Clase y cualquier parte del programa.
2. Privados: Slo es accesible desde los mtodos de la misma Clase.

En el encapsulamiento hay analizadores que pueden ser semnticos y


sintcticos.

Tema 2

POO en Python

Petia Ivanova Radeva

31

Encapsulamiento
Porcin visible: interfaz (protocolo)
Contrato pblico de comportamiento.

Descripcin de operaciones: informacin de entrada y de salida.


Porcin oculta: implementacin

Estructura de datos para almacenar la informacin.


Cdigo que se ejecuta para realizar las operaciones.

Tema 2

POO en Python

Petia Ivanova Radeva

32

ndice

Acceso a los atributos y los mtodos

Tipos de atributos

Objetos incrustados

Clases mutables y copias

Encapsulamiento

Polimorfismo y sobrecarga

Herencia
Tema 2

POO en Python

Petia Ivanova Radeva

33

Implementacin del
comportamiento de la clase
>>myf=Fraction(3,5)
>>print myf # print espera una cadena para imprimir
<__main__.Fraction instance at 0x409b1acc>

Solucin a):
class Fraction:
.
def show(self):
print self.__num,"/",
self.__den
Tema 2

POO en Python

>>myf=Fraction(3,5)
>>print myf
<__main__.Fraction
instance at
0x409b1acc>
>>myf.show()
3/5

Petia Ivanova Radeva

34

Sobrecarga al imprimir objetos

Cuando se hace un print <algo>, no queremos imprimir la


referencia del objeto, sino su contenido.

Esto se puede hacer redifiendo el mtodo str dentro de la


nueva clase.

Recordamos que str convierte a una representacin el forma


de cadena cualquier tipo de objeto.

Si una clase ofrece un mtodo llamado __str__, ste se


impone al comportamiento de la funcin interna str de
Python.
Tema 2

POO en Python

Petia Ivanova Radeva

35

Mtodos estandard en Python


class Fraction:
def __str__(self): # por defecto convierte en
string el objeto
return str(self.__num)+"/"+str(self.__den)
>>myf=Fraction(3,5)
>>print myf
3/5
>>print I ate , myf, of the pizza
I ate 3/5 of the pizza
>>myf.__str__()
3/5
>>str(myf)
3/5

Tema 2

POO en Python

Petia Ivanova Radeva

36

Polimorfismo

Definicin: El concepto de polimorfismo (del griego muchas formas) implica que


si en una porcin de cdigo se invoca un determinado mtodo de un objeto,
podrn obtenerse distintos resultados segn la clase del objeto.
Esto se debe a que distintos objetos pueden tener un mtodo con un mismo nombre,
pero que realice distintas operaciones segn el tipo del objeto (p.e. la suma de los
flotantes vs. la suma de las fracciones).

Llamamos redefinicin a la accin de definir un mtodo con el mismo nombre en


distintas clases, de forma tal que provea una interfaz.
Un bloque de cdigo ser polimrfico cuando dentro de ese cdigo se realicen
llamadas a mtodos que puedan estar redefinidos en distintas clases (p.e. __str__).

Tema 2

POO en Python

Petia Ivanova Radeva

37

Polimorfismo y sobrecarga

El trmino sobrecarga viene de un posible uso de polimorfismo:


En ciertos lenguajes de POO, existe la posibilidad de tener, dentro de una misma clase,
dos mtodos que se llamen igual pero reciban parmetros de distintos tipos.
En Python al no ser necesario especificar explcitamente el tipo de los parmetros que
recibe una funcin, las funciones son naturalmente polimrficas.
Python, al encontrar un operador, llamar a distintos mtodos segn el tipo de las
variables que se quieran manipular (sumar, restar, multiplicar, etc.).

Tema 2

POO en Python

Petia Ivanova Radeva

38

Sobrecarga de mtodos
>>f1=Fraction(1,4)
>>f2=Fraction(1,2)
>>f1+f2

Traceback(most recent call last): TypeError: unsupported


operand

def __add__(self,otherfraction):
newnum = self.__num*otherfraction.__den + \
self.__den*otherfraction.__num
newden = self.__den * otherfraction.__den
return Fraction(newnum,newden)
>>f3=f1+f2 # equivalente a: f3=f1.__add__(f2)
>>print f3
6/8
Tema 2

POO en Python

Petia Ivanova Radeva

39

Comparacin de dos objetos


>>f1=Fraction(1,2)
>>f2=Fraction(1,2)
>>f1==f2
False # the sameness problem
Es lo mismo decir?:
Mi a to favo ito y su a to favo ito so el
Mi pizza y la suya so la is a

is o

Recordatorio: Los objetos de las clases definidas por el usuario son


mutables!

Tema 2

POO en Python

Petia Ivanova Radeva

40

Comparacin de dos objetos


>>f1=Fraction(1,2)
>>f2=Fraction(1,2)
>>f3=f1
>>f3==f1
True
def __cmp__(self,otherfraction):
num1 = self.__num*otherfraction.__den
num2 = self.__den*otherfraction.__num
if num1 < num2:
return -1
else:
if num1 == num2:
return 0
else:
return 1
Tema 2

POO en Python

Petia Ivanova Radeva

41

La clase completa Fraction


class Fraction:
def __init__(self,top,bottom):
self.__num = top
self.__den = bottom
def __str__(self):
return str(self.__num)
+"/"+str(self.__den)
def show(self):
print
self.__num,"/",self.__den

def __add__(self,otherfraction):
newnum =self.__num*otherfraction.__den + \
self.__den*otherfraction.__num
newden = self.__den*otherfraction.__den
com = gcd(newnum,newden)
return Fraction(newnum/com,newden/com)
def __cmp__(self,otherfraction):
num1 = self.__num*otherfraction.__den
num2 = self.__den*otherfraction.__num
if num1 < num2:
return -1
else:
if num1 == num2:
return 0
else: return 1

En qu se expresa el polimorfismo y el encapsulamiento en esta implementacin?


Tema 2

POO en Python

Petia Ivanova Radeva

42

Sobrecarga de operadores

La sobrecarga de operadores permite redefinir ciertos


operadores, como + o - , para usarlos con las clases que
hemos definido.

Se llama sobrecarga de operadores porque estamos


reutilizando el mismo oeprador con un nmero de usos
diferentes.

El compilador decide cmo usar este operador dependiendo


sobre qu objetos opera.
Tema 2

POO en Python

Petia Ivanova Radeva

43

Qu operadores sobrecargar?

Las clases contienen muchos mtodos y atributos que se incluyen de


Python incluso si no se definen explcitamente.

La mayora de estos mtodos definen la funcionalidad automtica


provocada por los operadores o el uso de la clase especial.

Los atributos incorporados definen la informacin que deben ser


almacenados para todas las clases.

Todos los miembros integrados tienen dobles guiones bajos alrededor de


sus nombres:__init__ __doc__

Petia Ivanova Radeva

Mtodos especiales

Por ejemplo, existe el mtodo __repr__ para todas las clases, y


siempre se puede redefinir.
La definicin de este mtodo especifica cmo convertir una instancia de la clase en
una cadena.

Si escribimos f en la lnea de comandos, estamos llamando __repr__.

class Student:
...
def __repr__(self):
return Im named
+ self.__full_name
# Note: we changed the full_name to __full_name

>>> f = Student( Bob Smith , 23)


>>> f
Im named Bob Smith
Petia Ivanova Radeva

Mtodos especiales

Podemos sobrecargar:
__init__ : El constructor de la clase.
__cmp__ : Define como aplicar == para la clase.
__len__ : Define len( obj ).
__copy__ : Define cmo copiar un objeto de la clase.
__getitem__ : Define el operador [].
__doc__ : Variable que guarda la documentacin de la clase.
>>> f = Student( Bob Smith , 23)
>>> print f.__doc__
A class representing a student.
Consultar qu otros mtodos se pueden sobrecargar!
Petia Ivanova Radeva

Sobrecarga de los mtodos de los operadores

__add__(self, other) # operacin de suma


__sub__(self, other) # operacin de resta
__mul__(self, other) # operacin de multiplicacin
__floordiv__(self, other) # operacin de divisin redondeo
__mod__(self, other) # operacin de modulo
__divmod__(self, other) # operacin de divisin
__pow__(self, other) # operacin de potencia
__and__(self, other) # operacin de and
__or__(self, other) # operacin de or
__xor__(self, other) # operacin de xor
Tema 2

POO en Python

Petia Ivanova Radeva

47

ndice

Acceso a los atributos y los mtodos

Tipos de atributos

Objetos incrustados

Clases mutables y copias

Encapsulamiento

Polimorfismo y sobrecarga

Herencia
Tema 2

POO en Python

Petia Ivanova Radeva

48

Subclases

Una clase puede extender la definicin de otra clase con el fin


de utilizar (o reaprovechar) mtodos y atributos ya definidos
en la anterior.
Llamamos la nueva clase: "subclase o clase derivada .
La clase original es: clase base" o "ancestro".

Al definir una subclase, se pone el nombre de la clase base en


parntesis despus del nombre de la subclase en la primera
lnea de la definicin.
class AI_Student(Student):
Petia Ivanova Radeva

Ejercicio
class Main:
def __init__(self,p):
self._pp=p
def f(self):
print self._pp
def getpp(self):
return self._pp

class Derivative (Main):


def __init__(self,p,q):
Main.__init__(self,p)
self.__qq=q
def f2(self):
print self.__qq,self._pp
def getqq(self):
return self.__qq

Tema 2

POO en Python

Derivative
Main
_pp
f()
getpp()
__qq
f2()
getqq()

>>>o1=Main(3)
>>>o2=Derivative(5,4)
>>>print
o2.getpp(),o2.getqq()
>>>o2.f()
>>>o2.f2()
Petia Ivanova Radeva

50

Definicin de la clase Student


class Student:
A class representing a student.
def __init__(self,n,a):
self.__full_name = n
self.__age = a
def get_age(self):
print "Student age: "+str(self.__age)
return self.__age
def get_name(self):
return self.__full_name
>>>p=Student("John", 24)
>>>print p.get_name()
John
>>>p.get_age()
Student age: 24
Petia Ivanova Radeva

Definicin de la clase AI_Student


class AI_Student (Student):
A class extending student.
def __init__(self,n,a,s):
Student.__init__(self,n,a)
self.__section_num = s
def get_age(self): # es obligatoria?
print AI Student age: +str(self.__age)
return self.__age
>>>s=AI_Student("Ann", 34, 23)
>>>print s.get_name()
Ann
>>>s.get_age()
AI Student age: 34
Petia Ivanova Radeva

Redefinicin de los mtodos

Cuando creamos una clase derivada a partir de una clase base y tenemos que la
clase derivada proporciona o requiere su propio mtodo __init__, este mtodo de
la clase derivada debe llamar explcitamente el mtodo __init__ de la clase base

Lo interesante de la herencia es que las clases derivadas pueden definir mtodos


propios, y tambin redefinir mtodos que s existen en la clase base
Si quieremos que la clase derivada redefina un mtodo de la clase base (para que haga algo
diferente), podemos simplemente escribir una nueva definicin para el nombre de este mtodo en la
subclase.
El cdigo anterior no quede ejecutado.
Si deseamos que el viejo cdigo se ejecutara, adems del nuevo cdigo del mtodo, debemos
llamarlo explcitamente con el nombre de la clase base:
parentClass.methodName(self, a, b, c)
Petia Ivanova Radeva

Propiedades de la herencia

Evita repeticiones de cdigo.

Facilita el reuso de cdigo.

Cdigo compacto y claro.

A veces los datos pueden quedar demasiado escondidos.

La herencia es la posibilidad de definir una clase como


especificacin de otra (relacin is_a).
Cmo implementar la relacin has_a?
Tema 2

POO en Python

Petia Ivanova Radeva

54

Herencia

La herencia nos permite crear nuevas clases a partir de clases ya existentes,


convervando las propiedades de la clase original y aadiendo otras nuevas.

Adems, las clases derivadas pueden ser base de otras clases derivadas.
Se pueden montar jerarquas de clases.

En la herencia, las clases derivadas heredan todos los mtodos y atributos


de la clase base.
La visibilidad de los mtodos de las clases bases depende de la repeticin de los
nombres.
Tema 2

POO en Python

Petia Ivanova Radeva

55

Definimos una herencia simple


class Instrumento:
#Clase Base
pass

class Guitarra(Instrumento):
#Clase Derivada
pass
class Bajo(Instrumento):
#Clase Derivada
pass

Tema 2

POO en Python

Petia Ivanova Radeva

56

Ejemplo
class Instrumento:
def __init__(self, precio):
self.__precio = precio
def tocar (self):
print "Estamos tocando musica
def romper (self):
print "Esto lo pagas tu"
print "Son,self.__precio,
euros
class Guitarra (Instrumento):
def __init__ (self, cuerdas, precio):
Instrumento.__init__(self,
precio)
self.__cuerdas = cuerdas
def tocar(self):
print "Estamos tocando la
guitarra de ", self.__cuerdas,
" cuerdas"
Tema 2

POO en Python

def main():
instru = Instrumento(20)
guitar = Guitarra(5, 100)
instru.romper()
guitar.romper()
instru.tocar()
guitar.tocar()
main()

Petia Ivanova Radeva

57

Ejemplo redifinicin de mtodos


class Instrumento:
def __init__(self, precio):
self.__precio = precio
def tocar (self):
print "Estamos tocando musica
def romper (self):
print "Esto lo pagas tu"
print "Son,self.__precio,
euros
class Guitarra (Instrumento):
def __init__ (self, cuerdas, precio):
Instrumento.__init__(self,
precio)
self.__cuerdas = cuerdas
def tocar(self):
print "Estamos tocando la
guitarra de ", self.__cuerdas,
" cuerdas"
Tema 2

POO en Python

def main():
instru = Instrumento(20)
guitar = Guitarra(5, 100)
instru.romper()
guitar.romper()
instru.tocar()
guitar.tocar()
main()

Petia Ivanova Radeva

58

Conclusiones

La forma correcta para acceder a los valores de las clases es a travs de funciones getValor() y setValor().

Por defecto, intentar definir los mtodos como mtodos puros.

Se pueden incrustar objetos dentro de objetos.

Las clases son tipos de datos mutables

Una solucin es copiar los objetos usando la copia simple o la copia profunda.

La encapsulacin de los datos y los mtodos es un proceso de organizarlos en clases donde se separa la
interfaz de la clase de la implementacin de sus mtodos

Se pueden sobrecargar mtodos implementados.

El polimorfismo es la capacidad de definir operaciones bsicas de los tipos (mtodos de las clases) que
tiene el mismo objetivo aunque puedan tener diferente implementacin.

Las clases se pueden organizar en jerarquas. Las jerarquias permiten realizar herencia de mtodos y
datos de las clases bases por las clases derivadas

Es una forma muy eficiente de reaprovechar el cdigo, escribir de forma compacta y concisa y minimizar los errores.

Tema 2

POO en Python

Petia Ivanova Radeva

59

Material adicional

Tema 2

POO en Python

Petia Ivanova Radeva

60

Ejemplo 1: Juego de Poker


Tenemos: Suit (palo): Espadas, Corazones, Diamantes, y
Trboles,
Rank (nmero): As, 2, 3, 4, 5, 6, 7, 8, 9, 10, comod, reina, y el
rey
Consideramos :

pades
Hea ts
Dia o ds
Clu s 0

Jack 7 11
Queen 7 12
King 7 13

class Card:

"""represents a standard playing card."""


def __init__(self, suit=0, rank=2):
self._suit = suit
self._rank = rank
Tema 2

POO en Python

Petia Ivanova Radeva

61

Atributos de la clase
# inside class Card:
_suit_names = ['Clubs', 'Diamonds', 'Hearts', 'Spades']
_rank_names = [None, 'Ace', '2', '3', '4', '5', '6', ' ,' ', '9', '10', 'Jack', 'Queen', 'King']

def __str__(self):
return '%s of %s' % (Card._rank_names[self._rank],
Card._suit_names[self._suit])
>>> card1 = Card(2, 11)
>>> print card1
Jack of Hearts

Tema 2

POO en Python

Petia Ivanova Radeva

62

Comparar las cartas


Podemos sobrecargar el operador __comp__() para comparar las
cartas: toma dos parmetros self y uno ms y retorna -1, 0, o
1 si el primero es ms pequeo, igual o ms grande que el
segundo.
Consideremos un ranking de los palos (p.e. Espadas, Corazones,
Diamantes, y Trboles):
# inside class Card:
def __cmp__(self, other):
# check the suits
if self._suit > other.getSuit(): return 1
if self._suit < other.getSuit(): return -1
# suits are the same... check ranks
if self._rank > other.getRank(): return 1
if self._rank < other.getRank(): return -1
# ranks are the same... it's a tie
return 0

Tema 2

POO en Python

La clase Card y una instancia

Petia Ivanova Radeva

63

El juego de cartas
# inside class Card:
# implementacin compacta
def __cmp__(self, other):
t1 = self._suit, self._rank
t2 = other.getSuit(), other.getRank()
return cmp(t1, t2)
Utilizamos la definicin preimplementada del operador cmp!

Tema 2

POO en Python

Petia Ivanova Radeva

64

Baraja
class Deck(object):
def __init__(self):
self._cards = []
for suit in range(4):
for rank in range(1, 14):
card = Card(suit, rank)
self._cards.append(card)

Tema 2

POO en Python

Petia Ivanova Radeva

65

Imprimiendo la baraja
#inside class Deck:
def __str__(self):
res = []
for card in self._cards:
res.append(str(card))
return '\n'.join(res)

Tema 2

POO en Python

>>> deck = Deck()


>>> print deck
Ace of Clubs
2 of Clubs
3 of Clubs
...
10 of Spades
Jack of Spades
Queen of Spades
King of Spades
Petia Ivanova Radeva

66

Jugando con las cartas

Necesitamos una funcin para sacar y aadir carta a la


barraja
#inside class Deck:
def pop_card(self):
return self._cards.pop()
#inside class Deck:
def add_card(self, card):
self._cards.append(card)
# inside class Deck:
def shuffle(self):
random.shuffle(self._cards)

Tema 2

POO en Python

Petia Ivanova Radeva

67

La herencia en el caso de las cartas


Las cartas de un jugador tienen mucho en comn con la baraja entera:
basados en un conjunto de cartas que se pueden manipular: sacar,
aadir cartas.
Adems puede tener sus propias operaciones comparar, calcular la
puntuacin, etc.

La herencia es la posibilidad de definir una clase como


especificacin de otra (relacin is_a):
Clase base
Clase derivada
class Hand (Deck):
def __init__(self, label=''):
self._cards, self._label = [], label
Tema 2

POO en Python

Petia Ivanova Radeva

68

Las clases (casi)completas


class Card(object):
"""represents a standard playing card.""
def __init__(self, suit=0, rank=2):
self._suit, self._rank = suit, rank
self._suit_names = ['Clubs', 'Diamonds', Hearts', 'Spades']
self._rank_names = [None, 'Ace', ' ', ' ', ' ', ' ', ' ', ' ,' ', ' ', '
'Jack', 'Queen', 'King']

',\

def __str__(self):
return '%s of %s' %\
(self._rank_names[self._rank], self._suit_names[self._suit])
def __cmp__(self, other):
t1 = self._suit, self._rank
t2 = other.getSuit(), other.getRank()
return cmp(t1, t2)
Petia Ivanova Radeva

Las clases (casi)completas


class Deck(object):
def __init__(self):
self._cards = []
for suit in range(4):
for rank in range(1, 14):
card = Card(suit, rank)
self._cards.append(card)
def __str__(self):
res = []
for card in self._cards:
res.append(str(card))
return '\n'.join(res)
def pop_card(self):
return self._cards.pop()
def add_card(self, card):
self._cards.append(card)
def shuffle(self):
random.shuffle(self._cards)
def len(self):
return len(self._cards)

class Hand(object):
def __init__(self, label=''):
self._cards = []
self._label = label
def __str__(self):
res = []
for card in self._cards:
res.append(str(card))
return '\n'.join(res)
def pop_card(self):
return self._cards.pop()

def add_card(self, card):


self._cards.append(card)
def len(self):
return len(self._cards)

Petia Ivanova Radeva

Las clases (casi)completas


class Deck(object):
def __init__(self):
self._cards = []
for suit in range(4):
for rank in range(1, 14):
card = Card(suit, rank)
self._cards.append(card)
def __str__(self):
res = []
for card in self._cards:
res.append(str(card))
return '\n'.join(res)
def pop_card(self):
return self._cards.pop()
def add_card(self, card):
self._cards.append(card)
def shuffle(self):
random.shuffle(self._cards)
def len(self):
return len(self._cards)

class Hand(Deck):
def __init__(self, label=''):
self._cards = []
self._label = label

IS-A

HAS-A

Petia Ivanova Radeva

Las clases (casi)completas


class Card(object):
"""represents a standard playing card.""
def __init__(self, suit=0, rank=2):
self._suit = suit
self._rank = rank
def __str__(self): ...
def __cmp__(self, other):...
class Deck(object):
def __init__(self):
self._cards = ...
def __str__(self):...
def pop_card(self):....
def add_card(self, card):
def shuffle(self): ...
class Hand(Deck):
def __init__(self, label=''):
self._cards = ...
self._label = ...

...

>>>h=Hand()
>>> deck = Deck()
>>> c1=Card()
>>> card1 = Card(2, 11)
>>> print card1
Jack of Hearts
>>> hand = Hand('new hand')
>>> print hand.cards
[]
>>> print hand.label
new hand
>>> deck = Deck()
Los otros mtodos se heredan de la
clase Deck as que podemos utilizar
pop_card y add_card:
>>> card = deck.pop_card()
>>> hand.add_card(card)
>>> print hand
King of Spades
Petia Ivanova Radeva

Jugar
En qu clase pondras el siguiente
mtodo?
def move_cards(self, hand, num):
for i in range(num):
hand.add_card(self.pop_card())

HAS-A
IS-A

Tema 2

POO en Python

Petia Ivanova Radeva

73

El juego
Implementar un juego que:
Mezcla las cartas y las reparte entre 2 jugadores.
2. Se juega hasta que alguno de los jugadores se quede sin
cartas.
3. A cada iteracin, cada uno saca una carta.
1.

4.

Si la carta del primero es ms grande, el segundo se lleva las dos


cartas y viceversa.

El ganador es el que primero se quede sin cartas.

Tema 2

POO en Python

Petia Ivanova Radeva

74

El juego
# Crear la baraja y mezclar las cartas
deck=Deck()
deck.shuffle()

#Declarar los dos jugadores


hand1=Hand()
hand2=Hand()
#repartir todas las cartas
for i in range(26):
hand1.add_card(deck.pop_card())
hand2.add_card(deck.pop_card())
print deck.len()
Tema 2

POO en Python

#jugar
while(hand1.len()>0 and hand2.len()>0):
card1=hand1.pop_card()
card2=hand2.pop_card()
if card1<card2:
hand1.add_card(card1)
hand1.add_card(card2)
else:
hand2.add_card(card1)
hand2.add_card(card2)
print hand1.len()
print hand2.len()
print
#determinar el ganador
if (hand1.len()>0):
print "The winner is: Hand1"
else: print "The winner is: Hand2"
Petia Ivanova Radeva

75

Ejemplo 2: Implementar un juego para tirar dados


(Material adicional)
Implementar un juego que
consiste en tirar dos dados:
Definimos la clase MSDie:
1. Cuntas caras tiene?
2. Cul es su valor actual?
Dnde han de estar estos valores y
cundo se han de crear?
Definiremos los mtodos:
a) roll()
b) setValue(),
c) getValue().
Petia Ivanova Radeva

Ejemplo
>>> die1 = MSDie(6)
#definimos un dado de 6 puntos
>>> die1.getValue()
1
>>> die1.roll()
>>> die1.getValue()
4
>>> die2 = MSDie(13)
#definimos un dado de 13 puntos
>>> die2.getValue()
1
>>> die2.roll()
>>> die2.getValue()
12
>>> die2.setValue(8)
>>> die2.getValue()
8
Petia Ivanova Radeva

Cmo implementamos la clase MSDie?


# msdie.py
# Class definition for an n-sided die.
from random import randrange
class MSDie:
def __init__(self, sides):
self.sides = sides
self.value = 1
def roll(self):
self.value = randrange(1,self.sides+1)
def getValue(self):
return self.value
def setValue(self, value):
self.value = value
Petia Ivanova Radeva

Cmo implementamos la clase MSDie?


class MSDie:
...
def setValue(self,value):
self.value = value
def main():
die1 = MSDie(12)
die1.setValue(8)
print die1.getValue()
<self=die1; self.value=8>

Petia Ivanova Radeva

Definir los objetos grficos necesarios para


dibujar la interfaz del juego

Puntos
Rectngulos (dados, botones)
.
Cuadrados, rombos, romboides
Polgonos
Crculos
Formas ovales
Lineas

Textos
Imgenes

Tema 2

POO en Python

Petia Ivanova Radeva

80

Jerarqua de los objetos/clases grficos


Objeto
Grfico

Bounding
Box

Imagen

Punto
Forma
Oval

Lnea
Rectngulo

Texto

Crculo

Herencia la posibilidad de una clase de recibir sus mtodos y datos


Petia Ivanova Radeva
de otras clasesTema 2 POO en Python

81

La clase genrica GraphicsObject


class GraphicsObject:
"""Generic base class for all of the drawable objects"""
def __init__(self, options):
# options is a list of strings indicating which
# options are legal for this object.

def undraw(self):
"""Undraw the object (i.e. hide it). Returns silently
if the object is not currently drawn."""

def setFill(self, color):


"""Set interior color to color"""

def move(self, dx, dy):


"""move object dx units in x direction and dy
units in y direction"""

def setOutline(self, color):


"""et outli e olo to olo ""
def setWidth(self, width):
"""Set line weight to width"""

def _draw(self, canvas, options):


"""draws appropriate figure on canvas with options
provided Returns Tk id of item drawn"""
# must override in subclass
def _move(self, dx, dy):
"""updates internal state of object to move it dx,dy
units"""
# must override in subclass

def draw(self, graphwin):


"""Draw the object in graphwin, which should be a
GraphWin object """
Tema 2

POO en Python

Petia Ivanova Radeva

82

La clase Punto
class Point(GraphicsObject):
def __init__(self, x, y):
GraphicsObject.__init__(self, ["outline", "fill"])
self.setFill = self.setOutline
self.x = x
self.y = y
def _draw(self, canvas, options):
x,y = canvas.toScreen(self.x,self.y)
return \
canvas.create_rectangle(x,y,x+1,y+1,options)

def _move(self, dx, dy):


self.x = self.x + dx
self.y = self.y + dy
def clone(self):
other = Point(self.x,self.y)
other.config = self.config.copy()
return other
def getX(self): return self.x
def getY(self): return self.y

Tema 2

POO en Python

Petia Ivanova Radeva

83

La clase BoundingBox
class _BBox(GraphicsObject):
# Internal base class for objects represented by bounding box
# (opposite corners) Line segment is a degenerate case.
def __init__(self, p1, p2, options=["outline","width","fill"]):
def _move(self, dx, dy):
def getP1(self):
def getP2(self):
def getCenter(self):
Tema 2

POO en Python

Petia Ivanova Radeva

84

La clase Rectngulo
class Rectangle(_BBox):
def __init__(self, p1, p2):
def _draw(self, canvas, options):
def clone(self):

Tema 2

POO en Python

Petia Ivanova Radeva

85

La clase Figura Oval


class Oval(_BBox):
def __init__(self, p1, p2):
def clone(self):
def _draw(self, canvas, options):

Tema 2

POO en Python

Petia Ivanova Radeva

86

La clase Crculo
class Circle(Oval):
def __init__(self, center, radius):
def clone(self):
def getRadius(self):

Tema 2

POO en Python

Petia Ivanova Radeva

87

Constructor
myCircle = Circle(Point(0,0), 20) # se llama al constructor
class Circle(Oval):
def __init__(self, center, radius):
p1 = Point(center.x-radius, center.y-radius)
p2 = Point(center.x+radius, center.y+radius)
Oval.__init__(self, p1, p2)
self.radius = radius

Petia Ivanova Radeva

La clase Lnea
class Line(_BBox):
def __init__(self, p1, p2):
def clone(self):
def _draw(self, canvas, options):
def setArrow(self, option):

Tema 2

POO en Python

Petia Ivanova Radeva

89

La clase Polgono
class Polygon(GraphicsObject):
def __init__(self, *points):
# if points passed as a list, extract it
def clone(self):
def getPoints(self):
def _move(self, dx, dy):
def _draw(self, canvas, options):
Tema 2

POO en Python

Petia Ivanova Radeva

90

La clase Imagen
class Image(GraphicsObject):
def __init__(self, p, pixmap):
def _draw(self, canvas, options):
def _move(self, dx, dy):
def undraw(self):
def getAnchor(self):
def clone(self):
Tema 2

POO en Python

Petia Ivanova Radeva

91

La clase Texto
class Text(GraphicsObject):
def __init__(self, p, text):
def _draw(self, canvas, options):

def getText(self):

def getAnchor(self):
def setFace(self, face):

def _move(self, dx, dy):

def setSize(self, size):


def setStyle(self, style):

def clone(self):

def setTextColor(self, color):

def setText(self,text):

Tema 2

POO en Python

Petia Ivanova Radeva

92

Uso
from graphics import *
win = GraphWin()
win.setCoords(0,0,10,10)
p=Point(3,4)
p.draw(win)
win = GraphWin()
win.setCoords(0,0,10,10)
t = Text(Point(5,5), "Centered Text")
t.draw(win)
p = Polygon(Point(1,1), Point(5,3), Point(2,7))
p.draw(win)
e = Entry(Point(5,6), 10)
e.draw(win)
win.getMouse()
p.setFill("red")
p.setOutline("blue")
p.setWidth(2)
s="
for pt in p.getPoints():
s = s + "(%0.1f,%0.1f) " % (pt.getX(), pt.getY())
Tema 2

POO en Python

Petia Ivanova Radeva

93

Mtodos pblicos y privados

Tema 2

POO en Python

t.setText(e.getText())
e.setFill("green")
e.setText("Spam!")
e.move(2,0)
win.getMouse()
p.move(2,3)
s = ""
for pt in p.getPoints():
s = s + "(%0.1f,%0.1f) " %\
(pt.getX(), pt.getY())
t.setText(s)
win.getMouse()
p.undraw()
e.undraw()
t.setStyle("bold")
win.getMouse()
t.setStyle("normal")
win.getMouse()
t.setStyle("italic")
win.getMouse()
t.setStyle("bold italic")
win.getMouse()
t.setSize(14)
win.getMouse()
t.setFace("arial")
t.setSize(20)
win.getMouse()
win.close()

Petia Ivanova Radeva

94

Ejercicio sobre POO en Python:


I ple e tar la aplicaci

Dice Roller seg las or as:

Al iniciar la roleta se tiran los


dados y se visualiza la puntuacin
obtenida

Cada vez ue se haga u


li k
so e el ot Roll Di e se
vuelven a tirar los dados y se
actualiza la visualizacin de los
dados

Al ap eta el ot
la aplicacin
Tema 2

Quit se ie a

POO en Python

Petia Ivanova Radeva

95

Usando widgets

La clase botn
Mtodos de la clase botn

constructor
activate
deactivate
clicked
getLabel

def activate(self):
"Sets this button to active."
self.label.setFill(black)
self.rect.setWidth(2)
self.active = 1
Petia Ivanova Radeva

La clase botn
def deactivate(self):
"ets this utto to i a tive."
self.la el.setFill da kg ey
self.rect.setWidth(1)
self.active = 0

Petia Ivanova Radeva

La clase botn
pt = win.getMouse()
if button1.clicked(pt):
# Do button1 stuff
elif button2.clicked(pt):
# Do button2 stuff
elif button3.clicked(pt)
# Do button3 stuff
...

def clicked(self, p):


"RETURNS true if button is active and p is inside"
return self.active and \
self.xmin <= p.getX() <= self.xmax and \
self.ymin <= p.getY() <= self.ymax
Petia Ivanova Radeva

La clase botn
# Button.py
from graphics import *
class Button:
"""A button is a labeled rectangle in a window.
It is activated or deactivated with the activate()
and deactivate() methods. The clicked(p) method
returns true if the button is active and p is inside it."""

def __init__(self, win, center, width, height, label):


""" Creates a rectangular button, eg:
qb = Button(myWin, Point(30,25), 20, 10, 'Quit') """
w,h = width/2.0, height/2.0
x,y = center.getX(), center.getY()
self.xmax, self.xmin = x+w, x-w
self.ymax, self.ymin = y+h, y-h
p1 = Point(self.xmin, self.ymin)
p2 = Point(self.xmax, self.ymax)
self.rect = Rectangle(p1,p2)
self.rect.setFill('lightgray')
self.rect.draw(win)
self.label = Text(center, label)
self.label.draw(win)
self.deactivate()

def clicked(self, p):


"RETURNS true if button active and p is inside"
return self.active and \
self.xmin <= p.getX() <= self.xmax and \
self.ymin <= p.getY() <= self.ymax
def getLabel(self):
"""RETURNS the label string of this button."""
return self.label.getText()
def activate(self):
"""Sets this button to 'active'."""
self.label.setFill('black')
self.rect.setWidth(2)
self.active = 1
def deactivate(self):
"""Sets this button to 'inactive'."""
self.label.setFill('darkgrey')
self.rect.setWidth(1)
self.active = 0

Petia Ivanova Radeva

La clase DieView y sus mtodos

Constructor

setValue()

__makePip(self, x, y) dibujar un punto


Funcin privada!

La encapsulacin de los datos y los mtodos es un proceso de organizarlos en


clases donde se separa la interfaz de la clase de la implementacin de sus
mtodos

Petia Ivanova Radeva

La clase DieView
class DieView:
""" DieView is a widget that displays a graphical
representation of a standard six-sided die.""
def __init__(self, win, center, size):
"""Create a view of a die, e.g.:
d1 = GDie(myWin, Point(40,50), 20)
creates a die centered at (40,50) having sides
of length 20."""

# first define some standard values


self.win = win # save this for drawing pips later
self.background = "white" # color of die face
self.foreground = "black" # color of the pips
self.psize = 0.1 * size # radius of each pip
hsize = size / 2.0 # half the size of the die
offset = 0.6 * hsize # distance from center to
outer pips

# create a square for the face


cx, cy = center.getX(), center.getY()
p1 = Point(cx-hsize, cy-hsize)
p2 = Point(cx+hsize, cy+hsize)
rect = Rectangle(p1,p2)
rect.draw(win)
rect.setFill(self.background)
# Create 7 circles for standard pip locations
self.pip1 = self.__makePip(cx-offset, cy-offset)
self.pip2 = self.__makePip(cx-offset, cy)
self.pip3 = self.__makePip(cx-offset, cy+offset)
self.pip4 = self.__makePip(cx, cy)
self.pip5 = self.__makePip(cx+offset, cy-offset)
self.pip6 = self.__makePip(cx+offset, cy)
self.pip7 = self.__makePip(cx+offset, cy+offset)
# Draw an initial value
self.setValue(1)
Petia Ivanova Radeva

La funcin __makePip()
def __makePip(self, x, y):
"Internal helper method to draw a pip at (x,y)"
pip = Circle(Point(x,y), self.psize)
pip.setFill(self.background)
pip.setOutline(self.background)
pip.draw(self.win)
return pip
def setValue(self, value):
"Set this die to display value."
# turn all pips off
self.pip1.setFill(self.background)
self.pip2.setFill(self.background)
self.pip3.setFill(self.background)
self.pip4.setFill(self.background)
self.pip5.setFill(self.background)
self.pip6.setFill(self.background)
self.pip7.setFill(self.background)
# turn correct pips on
if value == 1:
self.pip4.setFill(self.foreground)
elif value == 2:
self.pip1.setFill(self.foreground)
self.pip7.setFill(self.foreground)

elif value == 3:
self.pip1.setFill(self.foreground)
self.pip7.setFill(self.foreground)
self.pip4.setFill(self.foreground)
elif value == 4:
self.pip1.setFill(self.foreground)
self.pip3.setFill(self.foreground)
self.pip5.setFill(self.foreground)
self.pip7.setFill(self.foreground)
elif value == 5:
self.pip1.setFill(self.foreground)
self.pip3.setFill(self.foreground)
self.pip4.setFill(self.foreground)
self.pip5.setFill(self.foreground)
self.pip7.setFill(self.foreground)
else:
self.pip1.setFill(self.foreground)
self.pip2.setFill(self.foreground)
self.pip3.setFill(self.foreground)
self.pip5.setFill(self.foreground)
self.pip6.setFill(self.foreground)
self.pip7.setFill(self.foreground)
Petia Ivanova Radeva

La aplicacin final
# roller.py
# Graphics program to roll a pair of dice. Uses custom
widgets Button and DieView.
from random import randrange
from graphics import GraphWin, Point, Rectangle
from button import Button
from dieview import DieView
def main():
# create the application window
win = GraphWin("Dice Roller")
win.setCoords(0, 0, 10, 10)
win.setBackground("green2")
# Draw the interface widgets
die1 = DieView(win, Point(3,7), 2)
die2 = DieView(win, Point(7,7), 2)
rollButton = Button(win, Point(5,4.5), 6, 1, "Roll
Dice")
rollButton.activate()
quitButton = Button(win, Point(5,1), 2, 1, "Quit")
# Event loop
pt = win.getMouse()

while not quitButton.clicked(pt):


if rollButton.clicked(pt):
value1 = randrange(1,7)
die1.setValue(value1)
value2 = randrange(1,7)
die2.setValue(value2)
quitButton.activate()
pt = win.getMouse()
# close up shop
win.close()
main()

Petia Ivanova Radeva

Estructuras de datos bsicas


Book: Problem Solving with Algorithms and Data Structures

Tema 5

Tema 3

Pilas y Colas

Objetivos

Entender la lgica de las estructuras bsicas: pila, cola, cola de prioridad y deque.

Ser capaces de implementar los tipos de datos abstractos pila, cola, cola de
prioridad y deque.

Considerar ejemplos de uso de las pilas, colas, colas de prioridad y deques.

Ser capaz de reconocer las propiedades de los problemas, donde son apropiadas
las pilas, colas, cola de prioridad y deques.

Tema 3

Pilas y Colas

Petia Ivanova Radeva

Qu son las estructuras lineales?

Estructuras lineales estructuras con orden (el elemento


antes y despus e.d. estructuras con dos extremos donde se
aaden y borran los elementos).
Top y bottom, inicio y fin.
Tres tipos:
Pila
Cola y colas de prioridad
Deque

Tema 3

Pilas y Colas

Petia Ivanova Radeva

Pilas

Definicin una pila es una secuencia de objetos


ordenados donde los objetos se aaden y borran del
mismo extremo ( top ).
El otro extremo se llama bottom .

Es una estructura lineal, una coleccin secuencial.

Last In First Out (LIFO)

Ejemplos
La pila de objetos en Python
El botn Back del web browser
El comando undo
Tema 3

Pilas y Colas

Petia Ivanova Radeva

Pilas

En una pila no sabemos dnde estan los elementos.

La indexacin no es posible/eficiente.
Pero s cules han sido introducidos los ltimos.
Los elementos no estan fsicamente juntos -> apropiada para grandes volmenes de datos
La pila se expande automticamente.

La nica manera de eliminar los datos de una pila es desde su parte


superior.
Cada vez que retire los datos, la pila se reduce automticamente.

Pocos lenguajes de programacin ofrecen la estructura de datos de la pila


como una estructura preimplementada.
La hemos de crear utilizando otras estructuras de datos, p.e. como una matriz.
La nueva estructura de datos creada es una estructura TDA.
Muchos compiladores de lenguajes de programacin vienen con bibliotecas de
subprogramas que ya han creado la estructura de datos de la pila.
Tema 3

Pilas y Colas

Petia Ivanova Radeva

El tipo de Datos Abstracto Pila

Datos secuencia lineal ordenada de elementos heterogneos que se aaden y borran del
mismo extremo.

Operaciones bsicas:
Stack() crea una pila vaca. No necesita parmetros y retorna una pila vaca.
push(item) aade un nuevo elemento al top de la pila. Necesita el elemento como parmetro y no

retorna nada.
pop() borra el elemento del top de la pila. No necesita parmetros y retorna el elemento borrado del

top.
peek() retorna el primer elemento de la pila sin borrarlo de la pila. La pila no se modifica.
isEmpty() comprueba si la pila est vaca. No necesita parmetros y retorna un valor booleano.
size() o __len__() retorna el nmero de elementos de la pila. No necesita parmetros y retorna un

entero.
Tema 3

Pilas y Colas

Petia Ivanova Radeva

Ejemplo de las operaciones bsicas de una pila


Operacin

Contenido de la pila

Valor de retorno

s.isEmpty()
s.push(4)
s.push( dog )
s.peek()
s.push(True)
len(s)
s.isEmpty()
s.push(8.4)
s.pop()
s.pop()
len(s)
Tema 3

Pilas y Colas

Petia Ivanova Radeva

Ejemplo de las operaciones bsicas de una pila


Operacin

Contenido de la pila

Valor de retorno

s.isEmpty()

[]

True

s.push(4)

[4]

s.push( dog )

[4, dog ]

s.peek()

[4, dog ]

s.push(True)

[4, dog ,True]

len(s)

[4, dog ,True]

s.isEmpty()

[4, dog ,True]

False

s.push(8.4)

[4, dog ,True,8.4]

s.pop()

[4, dog ,True]

8.4

s.pop()

[4, dog ]

True

len(s)

[4, dog ]

Tema 3

Pilas y Colas

dog

Petia Ivanova Radeva

Implementacin de la clase pila


class Stack:
Define un TDA Pila
def __init__(self):

def __str__(self):
def isEmpty(self):
def push(self, item):
def pop(self):
def peek(self):
def __len__(self):
Tema 3

Pilas y Colas

Petia Ivanova Radeva

Recordad: Operaciones de las listas en Python


Metodo

Uso

Explicacion

append

milista.append(elemento)

Aade un elemento al final de la lista

insert

milista.insert(i, item)

Inserta un elemento a la posicin i

pop

milista.pop()

Borra y retorna el ltimo elemento

pop

milista.pop(i)

Borra y retorna el i-simo elemento

sort

milista.sort()

Modifica ordenando la lista

reverse

milista.reverse()

Invierte la lista

del

del milista[i]

Borra el elemento i

index

milista.index(item)

Retorna el ndice de la primera ocurrencia

count

milista.count(item)

Retorna el nmero de ocurrencias del item

remove

milista.remove(item)

Borra la primera ocurrencia de item


Petia Ivanova Radeva

Tema 1

Abstraccin de datos

10

Implementacin de la clase pila


class Stack:
Define un TDA Pila
def __init__(self):
self.__items = []
def __str__(self):
res=""
for i in self.__items: res=res+" "+str(i) #Alternativas?
return res
def isEmpty(self):
return self.__items == []
def push(self, item):
# Qu es recomendable: item o __item?
self.__items.append(item)
def pop(self):
return self.__items.pop()
def peek(self):
if len(self)>0: return self.__items[len(self)-1]
else: return None
def __len__(self):
return len(self.__items)
Tema 3

Pilas y Colas

Petia Ivanova Radeva

11

Implementacin de la clase pila


class Stack:
Define un TDA Pila
def __init__(self):
self.__items = []
def __str__(self):

def

def
def
def

def

return ''.join(str(elem)+', ' for elem in self.__items)


# Ventajas?
isEmpty(self):
return self.__items == []
push(self, item):
self.__items.append(item)
pop(self):
return self.__items.pop()
peek(self):
if len(self)>0: return self.__items[len(self)-1]
else: return None
__len__(self):
return len(self.__items)
Tema 3

Pilas y Colas

Petia Ivanova Radeva

12

Una alternativa para implementar una Pila


class Stack:
Define un TDA Pila
def __init__(self):
self.__items = []
def __str__(self):
return ''.join(str(elem)+', '
for elem in self.__items)
def isEmpty(self):
return self.__items == []
def push(self, item):
self.__items.append(item)
def pop(self):
return self.__items.pop()
def peek(self):
if len(self)>0:
return self.__items[len(self)-1]

else: return None


def __len__(self):
return len(self.__items)

Tema 3

Pilas y Colas

class Stack:
Define un TDA Pila
def __init__(self):
self.__items = []
def __str__(self):
return ''.join(str(elem)+', '
for elem in self.__items)
def isEmpty(self):
return self.__items == []
def push(self, item):
self.__items.insert(0,item)
def pop(self):
return self.__items.pop(0)
def peek(self):
if len(self)>0:
return self.__items[0]
else: return None
def __len__(self):
return len(self.__items)

Petia Ivanova Radeva

13

Test

La posibilidad de definir el operador apropiado para poder


hace p i t , do de es u a pila se lla a .

Para encapsular correctamente la clase pila, definimos los


datos co o ..

Para poder ejecutar len(p), donde p es una pila necesitamos


..

Las fu cio es

E la clase pila, el
Tema 3

odificado as de la clase pila so : ..


todo gette es: .

Pilas y Colas

Petia Ivanova Radeva

14

Ejemplo: chequear si una expresin contiene


parntesis balanceados

Determinar las expresiones correctas:


(()()())
((())))
((((((()()()())))))
()()()()
)()()()(

Fijmonos que cada parntesis que cierra corresponde al ltimo parntesis que
abre.
Tema 3

Pilas y Colas

Petia Ivanova Radeva

15

Implementacin
def parChecker(symbolString):
s = Stack()
balanced, index = True, 0
while index < len(symbolString) and balanced:
symbol = symbolString[index]
if symbol == '(': s.push(symbol)
elif symbol==')':
if s.isEmpty(): balanced = False
else: s.pop()
index += 1

if balanced and s.isEmpty(): return True


else: return False
>>>print parChecker('(()())()')
Tema 3

Pilas y Colas

Petia Ivanova Radeva

16

Smbolos balanceados (el caso general)

En el caso general, podemos encontrar (), [], {}

({[]){})]
(({{[[]]}{[][]}}()))
[{( )}{}]

Tema 3

Pilas y Colas

Petia Ivanova Radeva

17

Implementacin
def parCheckerComplete(symbolString):
s = Stack()
balanced,index = True,0
while index < len(symbolString) and balanced:
symbol = symbolString[index]
if symbol in '([{': s.push(symbol)
elif symbol in ')]}':
if s.isEmpty():
balanced = False
else:
Hay acceso a los
atributos privados de la
top = s.pop()
clase Stack?
if not matches(top,symbol):
balanced = False
index += 1
if balanced and s.isEmpty():
return True
else:
return False
Tema 3

Pilas y Colas

Petia Ivanova Radeva

18

Implementacin
def matches(open,close):
opens = "([{"
closers = ")]}
return opens.index(open) == closers.index(close)
>>parChecker('()()()()(())()())
True

Puede el algoritmo parsear expresiones de tipo?:


>>parCheckerComplete((a+b)/c*(d+)
False

Tema 3

Pilas y Colas

Petia Ivanova Radeva

19

Aplicaciones
Backtracking
Evaluacin de
expresiones y anlisis de
sintxis
Lenguajes de
programacin basados en
pilas

Tema 3

Pilas y Colas

Petia Ivanova Radeva

20

Relacin con la prctica

Dadas las clases: Deck, Discard_Pile y Player , cul de stas


se puede considerar como una pila?

Tema 3

Pilas y Colas

Petia Ivanova Radeva

21

Relacin con la prctica

Dadas las clases: Deck, Discard_Pile y Player , cul de stas


se puede considerar como una pila?

Por ejemplo, si consideramos la clase pila (Discard_Pile) - donde amontonamos las


cartas, slo la ltima carta se puede ver.

a. Datos
i. Cards
b. Mtodos
i. Constructor (__init__).
ii. show_last_card - retorna la ltima carta.
iii. append aadir una carta a la pila.
iv. len - Comprobar cuntas cartas tiene la pila.
v. test define funcin de test.

Cules de los datos y mtodos sern definidos y heredados de la


clase Pila y cules seran especficos para la clase de las cartas?
Tema 3

Pilas y Colas

Petia Ivanova Radeva

22

Colas

Definicin una coleccin lineal de elementos


heterogneos, donde los elementos se aaden por uno de
los lados y se eliminan por el otro.

Ejemplos:
La cola de impresin
El buffer de la secuencia de teclas

Tema 3

Pilas y Colas

Petia Ivanova Radeva

23

Colas

Es una estructura lineal, una coleccin secuencial.


First In First Out (FIFO)

- first-come first-served.

Las colas se pueden expander y contraer automticamente

segn la cantidad de elementos que tienen.


Tema 3

Pilas y Colas

Petia Ivanova Radeva

24

Colas

Una cola permite guardar en un extremo y recuperar por el


otro extremo del contenedor.

La mayora de los lenguajes de programacin no tienen la


cola pre-implementada.
Se ha de crear como TDA.

Pero normalmente existen libreras con la implementacin de


la cola como estructura de datos.
Tema 3

Pilas y Colas

Petia Ivanova Radeva

25

El tipo de Datos Abstracto Cola

Datos secuencia ordenada de elementos heterogneos


Operaciones bsicas
Queue() crea una cola vaca. No necesita argumentos.
enqueue(item) aade un nuevo elemento item a la cola. Necesita el
elemento como argumento y no retorna nada.
dequeue() borra el primer elemento de la cola. No necesita parmetros y
retorna el elemento.
isEmpty() comprueba si la cola est vaca. No necesita parmetros y retorna
un valor booleano.
size() o __len__() retorna el nmero de elementos de la cola. No necesita
argumentos y retorna un entero.

Tema 3

Pilas y Colas

Petia Ivanova Radeva

26

Cola
Operacin

Contenido de la cola

Valor de retorno

q.isEmpty()
q.enqueue(4)
q.enqueue( dog )
q.enqueue(True)
len(q)
q.isEmpty()
q.enqueue(8.4)
q.dequeue()
q.dequeue()
len(q)

Tema 3

Pilas y Colas

Petia Ivanova Radeva

27

Cola
Operacin

Contenido de la cola

Valor de retorno

q.isEmpty()

[]

True

q.enqueue(4)

[4]

q.enqueue( dog )

[ dog ,4]

q.enqueue(True)

[True, dog ,4]

len(q)

[True, dog ,4]

q.isEmpty()

[True, dog ,4]

False

q.enqueue(8.4)

[8.4,True, dog ,4]

q.dequeue()

[8.4,True, dog ]

q.dequeue()

[8.4,True]

dog

len(q)

[8.4,True]

Tema 3

Pilas y Colas

Petia Ivanova Radeva

28

Implementacin de la Cola en Python


class Queue:
Define un TDA Cola
def __init__(self):
def __str__(self):
def enqueue(self,el):
def dequeue(self):
def isEmpty(self):
def __len__():

Tema 3

Pilas y Colas

Petia Ivanova Radeva

29

Implementacin de la Cola en Python


class Queue:
Define un TDA Cola
def __init__(self):
self.__data=[]
def __str__(self):
return ''.join(str(elem)+', for elem in self.__data)
def enqueue(self,el):
self.__data.append(el)
def dequeue(self):
return self.__data.pop(0)
def isEmpty(self):
return self.__data==[]
def __len__():
return len(self.__data)

Tema 3

Pilas y Colas

Petia Ivanova Radeva

30

Ejercicio: Dada una lista de nmeros p.e. [1,5,3,4,2,7,5,9,0],


generar sus permutaciones?
[1, 5, 3, 4, 2, 7, 5, 9, 0]
[5, 3, 4, 2, 7, 5, 9, 0, 1]
[3, 4, 2, 7, 5, 9, 0, 1, 5]
[4, 2, 7, 5, 9, 0, 1, 5, 3]
[2, 7, 5, 9, 0, 1, 5, 3, 4]
[7, 5, 9, 0, 1, 5, 3, 4, 2]
[5, 9, 0, 1, 5, 3, 4, 2, 7]
[9, 0, 1, 5, 3, 4, 2, 7, 5]
[0, 1, 5, 3, 4, 2, 7, 5, 9]
Tema 3

Pilas y Colas

Relacin con la prctica?


Petia Ivanova Radeva

31

Implementacin del juego La patata caliente


Flavius Josephus (historiador del s. 1)
- El combate de los judios contra los
romanos.
- Josephus con sus 39 compaeros
atrapados en una cueva

Tema 3

Pilas y Colas

Petia Ivanova Radeva

32

Implementacin del juego La patata caliente


def hotPotato(namelist, N):
Implementa el juego de
la patata caliente
sim = Queue()
for name in namelist:

while sim.size() > 1:


for i in range(N-1):

def hotPotato(namelist, N):


Implementa el juego de
la patata caliente
sim = Queue()
for name in namelist:
sim.enqueue(name)
while len(sim) > 1:
for i in range(N-1):
sim.enqueue(sim.dequeue())
sim.dequeue()
return sim.dequeue()

return

>>>hotPotato(['Bill','David','Susan','Jane','Kent','Brad], 7)
Kent
Tema 3

Pilas y Colas

Petia Ivanova Radeva

33

Relacin con la prctica

Dadas las clases: Deck, Discard_Pile y Player , cul de stas


se puede implementar como una cola?

Tema 3

Pilas y Colas

Petia Ivanova Radeva

34

Relacin con la prctica

Dadas las clases: Deck, Discard_Pile y Player , cul de stas


se puede implementar como una cola?

Dada la clase mazo (Deck ) es el conjunto de cartas de donde sacamos las cartas,
a.Datos:
i. Mazo de cartas
b. Mtodos
i. Constructor crea todas las cartas con nmeros de 0 a 9 y colores.
ii. Obtener la carta i del mazo (__getitem__) devuelve la carta en la posicin i
del mazo.
iii. Retornar cuntas cartas tiene el mazo (len).
iv. Borrar la carta i del mazo (remove).
v. Repartir una carta a un jugador (deal_one_card).
vi. Repartir las cartas (deal) reparte N cartas a cada uno de los jugadores.

Cules de los datos y mtodos sern definidos y heredados de la


clase Cola y cules seran especficos para la clase de las cartas?
Tema 3

Pilas y Colas

Petia Ivanova Radeva

35

Colas de prioridad

A veces necesitamos que los elementos de la cola estn ordenados no por


el orden de llegada, sino por sus caractersticas.
Ejemplo: lista de preferencias de msica

La cola de prioridad representa una cola donde los elementos estan


ordenados por su prioridad.
Esto hace muy fcil recuperar el elemento con mayor prioridad (tiempo O(1)).

Ejercicio: Dada una estructura de nmeros reales, desarrollar un


algoritmo que en tiempo ptimo O(1) encuentra el nmero mayor por
valor absoluto.

Tema 3

Pilas y Colas

Petia Ivanova Radeva

36

Y cmo sera una cola de prioridad?


class PriorityQueue(Queue):
""" Cola de prioridad""
def __init__(self):
def (self,el):

Qu mtodos ha de tener?
Podemos reaprovechar alguna clase?
Qu mtodos redefinir?

Qu mtodos sobrecargar?

Tema 3

Pilas y Colas

Petia Ivanova Radeva

37

Y cmo sera una cola de prioridad?


class PriorityQueue(Queue):
""" Cola de prioridad, hereda de una cola pero inserta los elementos
en orden, por defecto ascendiente"""
def __init__(self):
Queue.__init__(self)
def enqueue(self,el):
if self.isEmpty(): self.insert(0,el)
elif el<=self.__getitem__(0): self.insert(0,el)
else:
inserted,i=False,0
while i< (len(self)-1) and not(inserted):
if self.__getitem__(i)<el and el<=self.__getitem__(i+1):
self.insert(i+1,el)
inserted=True
i=i+1
if not(inserted): self.insert(len(self),el)
Tema 3

Pilas y Colas

Petia Ivanova Radeva

38

Ejercicio

Dado un conjunto de datos ordenado y de gran volumen (p.e.


las pelculas en un vdeoclub), si tenemos espacio limitado,
en qu estructura guardar el contenido?

Tema 3

Pilas y Colas

Petia Ivanova Radeva

39

Relacin con la prctica

Dadas las clases: Deck, Discard_Pile y Player , cul de stas


se puede considerar como una cola de prioridad?

Tema 3

Pilas y Colas

Petia Ivanova Radeva

40

Relacin con la prctica

Dadas las clases: Deck, Discard_Pile y Player , cul de stas


se puede considerar como una cola?
La clase jugador (Player):
a.Datos:
i. Nombre (name)
ii. Cartas de la mano del jugador
b. Mtodos
i. Inicializa el nombre del jugador y sus cartas
ii. Imprimir el nombre del jugador y sus cartas
iii. Comprobar si puede jugar (can_play_card).
iv. Jugar carta (play_a_card).
v. Seleccionar carta (select_card).
vi. Imprimir cuntas cartas tiene en la mano.

Cules de los datos y mtodos sern definidos y heredados de la


clase Cola de prioridad y cules seran especficos para la clase?
Tema 3

Pilas y Colas

Petia Ivanova Radeva

41

Aplicaciones programas antivirus

Cada mensaje que viene, el programa antivirus lo guarda en


un extremo y si el mensaje est comprobado que no tiene
virus, se guarda en el otro extremo.

Si tiene virus se rechaza por el primer extremo.

Tema 3

Pilas y Colas

Petia Ivanova Radeva

42

Aplicaciones: Programacin multitarea &


multiprocesador (A-Steal job scheduling algorithm).
El algoritmo hace la planificacin de tareas de los mltiples
procesadores.

Cada procesador tiene su deque.

Para ejecutar el siguiente proceso, el procesador saca el primer


elemento.

Si el proceso se bifurca, se aade al deque por el otro extremo.

Y se ejecuta la siguiente tarea.

Cuando un procesador vace su deque, roba un proceso del II


extremo de otro procesador y lo ejecuta.

Algoritmo usado por la librera de programacin paralela de Intel's.


Tema 3

Pilas y Colas

Petia Ivanova Radeva

43

Deque

Una estructura lineal de elementos ordenados donde se


puede aadir y borrar por los dos lados de la secuencia.

Fijmonos que el prinicipio est a la derecha.


Tema 3

Pilas y Colas

Petia Ivanova Radeva

44

El TAD Deque

Deque() crea un deque nuevo vaco. No necesita parmetros y retorna el deque


vaco.
addFront(item) aade un nuevo item al principio del deque. Necesita como
parmetro el item y no retorna nada.
addRear(item) aade un nuevo item al final del deque. Necesita como parmetro
el item y no retorna nada.
removeFront() borra el primer item del deque. No necesita parmetros y retorna
el item. Modifica el deque.
removeRear() borra el ltimo item del deque. No necesita parmetros y retorna el
item. Modifica el deque.
isEmpty() comprueba si el deque est vaco. No necesita parmetros y retorna un
valor booleano.
__len__() o size() retorna en nmero de items del deque. No necesita parmetros
y retorna un entero.
Tema 3

Pilas y Colas

Petia Ivanova Radeva

45

Ejemplo de deque
[]
Operacin

Contenido de la cola

Valor de retorno

[4]
q.isEmpty()

[]

True

[ dog ,4]
q.addRear(4)

[4]

[ dog ,4, cat dog


q.addRear(
] )

[ dog ,4]

[q.addFront(
dog ,4, cat ,True]
cat )

[ dog ,4, cat ]

[d.addFront(True)
dog ,4, cat ,True]

[ dog ,4, cat ,True]

[len(q)
dog ,4, cat ,True]

[ dog ,4, cat ,True]

[8.4,
q.isEmpty()
dog ,4, cat ,True]

[ dog ,4, cat ,True]

False

[q.addRear
dog ,4, cat(8.4)
,True]

[8.4, dog ,4, cat ,True]

[q.removeRear()
dog ,4, cat ]

[ dog ,4, cat ,True]

8.4

[q.removeFront()
dog ,4, cat ]

[ dog ,4, cat ]

True

len(q)

[ dog ,4, cat ]

Tema 3

Pilas y Colas

Petia Ivanova Radeva

46

Implementacin del deque


class Deque:
def __init__(self):
def isEmpty(self):
def addFront(self,
item):
def addRear(self, item):
def removeFront(self):
def removeRear(self):

def __len__(self):
def __str__(self):
Tema 3

Pilas y Colas

class Deque:
def __init__(self):
self._items = []
def isEmpty(self):
return self._items == []
def addFront(self, item):
self._items.append(item)
def addRear(self, item):
self._items.insert(0,item)
def removeFront(self):
return self._items.pop()
def removeRear(self):
return self._items.pop(0)
def __len__(self):
return len(self._items)
def __str__(self):.
Petia Ivanova Radeva

47

Ejemplo: chequear si una palabra es palndromo


>>palchecker(gjgjhgj)
False
>>palchecker(toot)
True
>>palchecker(radar)
True

Tema 3

Pilas y Colas

Petia Ivanova Radeva

48

Ejemplo: chequear si una palabra es palndromo


def palchecker(aString):
chardeque = Deque()
for ch in aString:

while len(chardeque) > 1


and :

if first != last:

return stillEqual

Implementar el mismo programa sustituyendo el deque con una pila y una cola.
Tema 3

Pilas y Colas

Petia Ivanova Radeva

49

Ejemplo: chequear si una palabra es palndromo


def palchecker(aString):
chardeque = Deque()
for ch in aString:

while len(chardeque) > 1


and :

if first != last:

return stillEqual

def palchecker(aString):
chardeque = Deque()
for ch in aString:
chardeque.addRear(ch)
stillEqual = True
while len(chardeque) > 1 and
stillEqual:
first =chardeque.removeFront()
last = chardeque.removeRear()
if first != last:
stillEqual = False
return stillEqual

Es mejor hacer la funcin mtodo de la clase Deque?


Implementar el mismo programa sustituyendo el deque con una pila y una cola.
Tema 3

Pilas y Colas

Petia Ivanova Radeva

50

Lo que hemos visto

La lgica de las estructuras bsicas: pila, cola, cola de prioridad y deque.

La implementacin de los tipos de datos abstractos pila, cola, cola de prioridad y


deque.

Implementar ejemplos de uso de las pilas, colas, colas de prioridad y deques.

Ser capaz de reconocer las propiedades de los problemas, donde son apropiadas
las pilas, colas, colas de prioridad y deques.

Tema 3

Pilas y Colas

Petia Ivanova Radeva

51

Colecciones, arrays y estructuras


enlazadas
Tema 4

Objetivos

Reconocer diferentes categoras de colecciones y sus operaciones


Entender la diferencia entre los tipos de datos abstractos y los datos concretos usados para
implementarlos

Realizar operaciones bsicas sobre arrays, como inserciones y borrado de sus


elementos
Poder cambiar de tamao de un array cuando sea demasiado pequeo o grande

Realizar operaciones bsicas como recorrido, inserciones, borrado sobre


estructuras enlazadas

Saber valorar el espacio y tiempo de gestin de arrays y estructuras enlazadas


desde punto de vista de los modelos de memoria que implican estas estructuras
de datos

Petia Ivanova Radeva

Colecciones

Coleccin: Grupo de elementos que queremos tratar como


unidades conceptuales
Ejemplos: Listas, strings, pilas, colas, ABB, heaps, grafos, diccionarios,
conjuntos, etc.

Pueden ser homogeneos o heterogeneos


Las listas son heterogeneas en Python

Cuatro categoras principales:


Lineales, jerrquicas, grafos, y no ordenadas.
3

Petia Ivanova Radeva

Colecciones lineales

Ordenadas por su orden

Ejemplos ordinarios:
Listas de compra
Pila de platos
Cola de usuarios en el banco

Petia Ivanova Radeva

Colecciones jerrquicas

Estructura rbol

El padre de D3 es D1; sus hijos son D4, D5, y D6

Ejemplos: el sistema de directorios de


ficheros, la tabla de contenido de un libro
5

Petia Ivanova Radeva

Colecciones de grafos

Grafo: Coleccin en cual cada elemento puede tener muchos


padres y muchos hijos

Ejemplos: Mapas de las rutas de las aerolneas entre


ciudades; los diagramas de cables elctricos de los edificios
6

Petia Ivanova Radeva

Colecciones sin orden (conjuntos)

Los elementos no tienen orden concreto


No se puede definir el predecesor y el sucesor

Ejemplo: Bolsa de caniques

Petia Ivanova Radeva

Operaciones sobre Colecciones

Operaciones sobre Colecciones

Abstraccin y Tipos de datos abstractos

Para el usuario, una coleccin es una abstraccin

En Ciencias de Computacin, las colecciones son tipos de datos


abstractos (ADTs)
Los usuarios de los ADT los interesa aprender la interface de las ADTs
Los desarolladores son los que han de implementar su comportamiento de la
forma ms eficiente posible

Cmo se pueden implementar ADTs como clases o conjuntos de clases


relacionadas en mdulos?

10

Petia Ivanova Radeva

Estructuras de Datos para implementar las


Colecciones: Arrays

La estructura de datos y el tipo de datos concreto se refieren a la representacin


interna de los datos de un ADT

Las dos estructuras de datos ms usadas para implementar colecciones en la mayora de


lenguajes son: los arrays y las estructuras enlazadas

Un array es un objeto de tipo coleccin donde todos los elementos estn fsicamente
almacenados en un espacio continuo

Una lista enlazada es un objeto de tipo coleccin donde todos los elementos no
necesariamente estn fsicamente almacenados en un espacio continuo. La relacin entre
los elementos se consigue a travs de sus enlaces

11

Petia Ivanova Radeva

Estructuras de Datos para Implementar las


Colecciones: Arrays
Los arrays y las estructuras enlazadas
Diferentes maneras para almacenar y acceder a los datos en la memoria del
ordenador

Diferente forma de gestionar el espacio y el tiempo de ejecucin de los


algoritmos que manipulan las colecciones

vs.

12

Petia Ivanova Radeva

12

La Estructura de Datos Array

Array: Se basa a la lista en Python


Es una estructura de datos ms restringuida que las listas en Python

Definicin de la clase Array

13

Petia Ivanova Radeva

Implementacin del Array


An Array is a restricted list whose users can use only [], len, iter, and str.
To instantiate, use: <variable> = array(<capacity>, <optional fill value>)
The fill value is None by default.
class Array:
"""Represents an array."""
def __init__(self, capacity, fillValue
= None):
"""Capacity is the static size of
the array.
fillValue is placed at each
position.""
self._items = list()
for count in xrange(capacity):
self._items.append(fillValue)
def __len__(self):
"""-> The capacity of the array."""
return len(self._items)

def __iter__(self):
"""Supports traversal with a for
loop."""
return iter(self._items)
def __getitem__(self, index):
"""Subscript operator for access at
index."""
return self._items[index]
def __setitem__(self, index, newItem):
"""Subscript operator for
replacement at index."""
self._items[index] = newItem
def __str__(self):
"""-> The string representation of
the array."""
return str(self._items)
Petia Ivanova Radeva

14

Acceso Aleatorio y Memoria Continua

La indexacin del array se realiza a travs de una operacin

La direccin de un elemento: la direccin de la base + offset


La operacin de indexacin tiene dos pasos:
Localiza la direccin base
Calcula suma de la base + index*k, donde k es el nmero de bytes de cada
elemento del array, y
Retorna la referencia o el contenido posicionado en la memoria
15

Petia Ivanova Radeva

Memoria Esttica y Memoria Dinmica

En los lenguajes viejos los arrays eran estticos


int v[10];

Los lenguajes modernos suportan arrays dinmicos


int *v;
v= new int[N];

16

Petia Ivanova Radeva

Memoria Esttica y Memoria Dinmica

1
3
4
5

Para reajustar la longitud de un array en tiempo de ejecucin:


Crea un array con un tamao razonable al principio
Cuando est lleno, crea uno nuevo, ms grande y copia los datos
Cuando parece que el array no utiliza gran parte de la memoria, reduce
el tamao de mismo modo

1
3
4
5

Estos ajustes en Python son automticos cuando se utilizan las listas


de Python

17

Petia Ivanova Radeva

17

Tamao fsico y tamao lgico


El tamao fsico es el nmero de celdas del array
El tamao lgico es el nmero de elementos que actualmente tiene

Arrays con diferente tamao fsico

Garbage collection libera el espacio temporal que no se utiliza


Para evitar el garbage collection , se han de tener en cuenta los dos tamaos.

18

Petia Ivanova Radeva

Tamao fsico y tamao lgico

En general, el tamao fsico y el tamao lgico nos dicen puntos


importantes sobre el estado del array:
Si el tamao lgico es 0, el array es vaco
Sino, en cada momento el ndice del ltimo elemento en el array es su tamao lgico
menos 1.
Si el tamao lgico equivale al tamao fsico, no hay espacio para nuevos datos.

Tamao fsico

Tamao lgico

19

Petia Ivanova Radeva

Operaciones sobre Arrays

Consideramos los siguientes datos:

Las operaciones seran usadas para definir mtodos para las


colecciones que contienen arrays.

20

Petia Ivanova Radeva

Incrementar el tamao de un Array

1
3
4
5

Consiste en:
Crear un nuevo array ms grande
Copiar los datos del array viejo al nuevo
Reasignar a la variable del viejo array en el nuevo objeto

1
3
4
5

Para conseguir una ejecucin ms razonable, duplicar el tamao del array cada
vez que se incrementa el tamao:

21

Petia Ivanova Radeva

Decrementar el tamao de un Array

1
3
4
5

Esta operacin ocurre en las listas de Python cuando usando


pop() lleva a no aprovechar suficiente la memoria reservada (cuando
el nmero de elementos no usados supera un umbral)
Pasos:

Crea un array nuevo ms pequeo


Copia los datos del viejo array al nuevo
Reasigna a la vaiable del viejo array, la direccin del nuevo

22

1
3
4
5

Petia Ivanova Radeva

Insertar un elemento en un array que crece

El programador ha de comprobar sobre el espacio suficiente


e incrementar el tamao fsico si es necesario

Se mueven los elementos desde la posicin concreta hasta el


final lgico del array con una posicin
Se inserta el nuevo elemento
Se incrementar el tamao lgico con uno.
15231

15

231

157231

7
23

Petia Ivanova Radeva

Insertar un Elemento en un Array que


Aumenta

24

Borrar un Elemento de un Array

Pasos:
Mover los elementos desde la posicin concreta hasta el final del
tamao lgico con uno
Decrementar el tamao lgico con uno
Comprobar el espacio no utilizado y decrementar el tamao fsico del
array si es necesario

157231

El coste del borrado, en promedio, es lineal (O(n)).

25

Petia Ivanova Radeva

Borrado de un Elemento en un Array

26

157231

Complejidad: Tiempo, Espacio, y Arrays

El uso promedio de la memoria es O(n)


El coste de la memoria para usar un array corresponde con su factor de sobrecarga (el ratio de las
casillas ocupadas vs. el tamao fsico del array)

27

Petia Ivanova Radeva

Arrays Bi-Dimensionales (Grids)

A veces, un array bi-dimensional puede ser ms til que un uni-dimensional

Llamamos esta estructura tabla (grid, matriz);


para acceder un elemento:

28

Petia Ivanova Radeva

Procesando un Grid

A parte de los dobles corchetes para devolver sus elementos, se pueden


aadir los siguientes dos mtodos:
Ejemplos: getHeight y getWidth

Las operaciones sobre arrays unidimensionales se extienden fcilmente


para arrays bidimensionales

29

Petia Ivanova Radeva

Crear e inicializar una tabla (Grid)

Suponiendo que existe la clase Grid :

altura valor inicial


anchura

Una vez creada, se pueden cambiar sus valores:

30

Petia Ivanova Radeva

Definiendo la clase Grid

31

Definiendo la clase Grid

El mtodo __getitem__ es suficiente para suportar el uso del doble


corchete por el usuario de la clase:

32

Petia Ivanova Radeva

Tablas no uniformes y arrays multidimensionales

En una tabla (grid) no uniforme, hay un nmero fijo de filas pero el nmero de
columnas en cada fila puede variar

Se puede implementar como un array de listas o un array de arrays

Se pueden definir dimensiones a la definicin del grid; el nico lmite es la


memoria del ordenador
Un array tri-dimensional se puede visualizar como una caja de cajas ms pequeas con
sus columnas y filas
Profundidad, altura, y anchura; tres ndices; tres bucles

def __init__(self, rows, columns, fillValue = None):


self._data = Array(rows)
for row in xrange(rows):
self._data[row] = Array(columns, fillValue)
33

Petia Ivanova Radeva

Estructuras enlazadas

Despus de los arrays, las estructuras enlazadas son probablemente las


estructuras de datos ms usadas en los diferentes lenguajes

De mismo modo como el array, la estructura enlazada es un tipo concreto


de datos que se usa para implementar varios tipos de colecciones,
incluyendo las listas

Existen varias caractersticas que se han de tener en cuenta cuando se usan las
estructuras enlazadas para implementar otros tipos

34

Petia Ivanova Radeva

Estructuras enlazadas simples y doble enlazadas

Enlace vaco

No existe el acceso aleatorio, se ha de recorrer toda la lista.

No hace falta mover elementos ni en la insercin ni en el borrado (por qu?).

Se puede aumentar/disminuir la lista sin coste de memoria.


35

Petia Ivanova Radeva

Memoria no continua y Nodos

Una estructura enlazada separa la secuencia lgica de los elementos en la


estructura de cualquier ordenacin en la memoria fsica
Esquema de representacion de memoria no continua

La unidad bsica de representacin es el nodo:

Nodo enlazado simple

Nodo enlazado simple

36

Petia Ivanova Radeva

Memoria no continua y Nodos

Segn el lenguaje, se pueden definir los nodos para enlazar partes


separadas de la memoria de forma diferente:
Usando dos arrays paralelos

37

Petia Ivanova Radeva

Memoria no continua y Nodos

Formas de definir los nodos para usar la memoria no continua:


Usando apuntadores (null o nil representan enlaces vacos como valor de
un apuntador)
Memoria alocatada a partir del objeto
Usando referencias de objetos (e.g., Python)
En Python, None puede ser usado para asignar un enlace vaco
Un garbage collection automtico facilita para que el usuario no ha de ir
liberando la memoria

De aqu adelante vamos a usar los trminos enlace, apuntador y


referencia de forma equivalente.
38

Petia Ivanova Radeva

Definicin de la Clase Nodo Enlazado Simple

La clase Nodo ha de ser simple


La flexibilidad y la facilidad de uso son crticos

Un nodo simple enlazado ha de contener los datos y la referencia al siguiente


nodo:

class Node:
def __init__(self, data, next=None):
'''Instantiates a Node with default next of None'''

self.__data=data
self.__next=next
def __str__(self):
return str(self.__data)

39

Petia Ivanova Radeva

Usando la Clase Nodo Enlazado Simple

Las variables del Node se inicializan como None o algun otro objeto Node
node1=None
# Just an empty link
node2=Node('a', node1)
# A node containing data and an empty link
node3=Node('b', node2)
# A node containing data and a link to node2

40

Petia Ivanova Radeva

Usando la Clase Nodo Enlazado Simple


node1.__next = node3

->

AttributeError

Solucin:

node1 = Node("C", node3)

Las estructuras enlazadas se procesan con bucles

41

Petia Ivanova Radeva

Usando la Clase Nodo Enlazado Simple


class Node:
def __init__(self, data, next=None):
'''Instantiates a Node with default next of None'''
self.__data, self.__next=data,next
def __str__(self):
return str(self.__data)
def getNext(self):
return self.__next
def setNext(self,newNext): self.__next=newNext
def getData(self):
return self.__data
def setData(self,newData): self.__data=newData

Qu hace este cdigo?

for count in xrange(1,6):


head=Node(count,head)
while head!= None:
print head
head=head.getNext()

Qu problema tiene este cdigo y cmo evitarlo?

42

Petia Ivanova Radeva

La lista enlazada
class LinkedList:
def __init__(self):
self.__head=None
def initialize(self,until):
'''Add X nodes to the linked list'
self.__head=None
for count in xrange(0,until):
self.__head=Node(until-count,self.__head)

def getHead(self):
Returns the first element
return self.__head

43

Petia Ivanova Radeva

Operaciones sobre las Estructuras Enlazadas


Simples

Casi todas las operaciones en arrays son basadas en ndices


Los ndices son una parte integral de una estructura de tipo array

Podemos emular operacions basadas en el ndice


manipulando los enlaces dentro de la estructura?
Son eficientes? Cules?

Cmo realizar estas operaciones comunes como?:


Recorridos
Inserciones
Borrados
44

Petia Ivanova Radeva

Recorrido

Recorrido: Visitar cada nodo sin borrarlo


Usar una variable de referencia temporal

Ejemplo:

def traverse(self):
probe=self.__head
while probe!= None:
print probe
probe=probe.getNext()

None sirve de centinela para el proceso


Los recorridos son lineales en tiempo,
No requieren memoria extra
45

Petia Ivanova Radeva

Recorrido

46

Bsqueda

Recuerda al recorrido, pero necesita dos posibles sentinelas:


Un enlace vaco
En elemento que recorre los datos

Ejemplo:

def find(self,targetItem):

Traverse and look for a targetItem, returns True or False

probe, res = self.__head, True

while probe != None and targetItem!=probe.getData():


probe = probe.getNext()
if probe != None: print 'TargetItem has been found'
else:
res=False
print 'TargetItem is not in the linked list'
return res

En promedio, es lineal para estructuras enlazadas simples.


47

Petia Ivanova Radeva

Bsqueda

Accediendo al elemento i-simo de una estructura enlazada es una


operacin de bsqueda secuencial
Se empieza con el primer nodo y se cuentan el nmero de enlaces hasta llegar al nodo isimo.
def __getitem__(self,index):

Looks for the ith element

probe=self.__head

while index>0 and probe.getNext():


probe=probe.getNext()
index-=1

Las estructuras enlazadas no suportan el acceso aleatorio


if index>0: return None
else: return probe.getData()

Se puede utilizar la bsqueda binaria?


48

Petia Ivanova Radeva

Reemplazar un elemento con otro

Necesita recorrido, una vez encontrado, lo reemplaza.

def replace(self, targetItem, newItem):

probe=self.__head
while probe!=None and targetItem!=probe.getData():
probe=probe.getNext()
if probe!=None:
probe.setData(newItem)
return True
else: return False

49

Petia Ivanova Radeva

Reemplazar un elemento con otro


Reemplaza el i-simo elemento asumiendo 0 <= i < n
def replacei(self, index, newItem):

if index<0:
print'Index negativo'
return False
probe=self.__head
while probe!=None and index>=0:
probe=probe.getNext()
index-=1
if index<0:
probe.setData(newItem)
return True
else: return False

En promedio, coste lineal O(n) de las dos operaciones.


50

Petia Ivanova Radeva

Insertar al principio

Usa tiempo y memoria constante


def insertFirst(self,data):
Inserta data como primer elemento
self.__head=Node(data,self.__head)
51

Petia Ivanova Radeva

Insertar al final

Insertar un elemento al final de un array


(append en una lista de Python)
requere tiempo y memoria constantes
Siempre y cuando el array no ha de ser
cambiado de tamao

Para insertar al final cuntos casos


hemos de considerar?

52

Petia Ivanova Radeva

Inserting at the End (continued)


def insertLast(self,data):
probe=self.__head
if probe==None:
probe=Node(data)
else:
while probe.getNext():
probe=probe.getNext()
probe.setNext(Node(data))

53

Borrar al Principio

def removeFirst(self):
if self.__head==None: return None
res=self.__head.getData()
self.__head=self.__head.getNext()
54

Borrar del final

Borrar un elemento del


final del array (pop en
una lista de Python)
requere tiempo y
memoria constante
Siempre y cuando el
array no ha de cambiar
de tamao

Cuntos casos hemos de


contemplar para borrar al
final de una estructura?

55

Petia Ivanova Radeva

Borrar del final

Borrar un elemento del final del array (pop en una lista de Python) requere
tiempo y memoria constante
Siempre y cuando el array no ha de cambiar de tamao

Cuntos casos hemos de contemplar para borrar al final de una estructura?

def removeLast(self):
Borra el nodo del final de la estructura
if self.__head==None: return None
if self.__head.getNext()==None:
res, self.__head=self.__head.geData(), None
else:
probe=self.__head
while probe.getNext().getNext()!=None:
probe=probe.getNext()
res=probe.getNext().getData()
probe.setNext(None)
return res
56

Petia Ivanova Radeva

Insertar a cualquier posicin

Insercin al principio (mirar transparencias anteriores)


En las otras posiciones i, primero encuentra el nodo a la posicin i - 1 (si i
< n) o el nodo a la posicin n - 1 (if i >= n)

def inserti(self, index,data):


Insertar a posicion i
if self.__head==None or index<0:
self.__head=Node(data)
else:
probe=self.__head
while probe.getNext() and index>1:
probe=probe.getNext()
index-=1

Tiempo lineal O(n); uso constante de la memoria

#una vez llegado a la posicin index, insertamos


probe.setNext(Node(data,probe.getNext()))

57

Petia Ivanova Radeva

Insertar a Cualquier Posicin

58

Borrar de cualquer posicin

Tres casos por considerar:

def removei(self, index):


if self.__head==None:
removedItem=None
elif index<=0 or self.__head.getNext()==None:
removedItem=self.__head.getData()
self.__head=None
else:
probe=self.__head
while probe.getNext().getNext()!=None and index>1:
probe=probe.getNext()
index-=1
removedItem=probe.getNext().getData()
probe.setNext(probe.getNext().getNext())
return removedItem
59

Petia Ivanova Radeva

Complejidad : Uso del tiempo y el espacio en


las estructuras enlazadas simples

La principal ventaja es no tanto el tiempo, sino el uso ptimo


de la memoria!!!
60

Petia Ivanova Radeva

Extensiones de las estructuras enlazadas

Una estructura circular enlazada con un Nodo de Cabecera

Estructuras Dobles Enlazadas

61

Petia Ivanova Radeva

Variaciones sobre las estructuras enlazadas


lineales: Una estructura enlazada circular

Contiene un enlace desde el ltimo nodo hasta el primer nodo de la


estructura

El nodo de cabeza sirve como un marcador para el inicio y el final de la


estructura enlazada

62

Petia Ivanova Radeva

Una estructura enlazada circular


class CircularLinkedList:
def __init__(self):
self.__head, self.__tail=None, None
def __str__(self):
if self.__head==None: return ''
probe=self.__head
res=str(probe.getData())+','
if probe.getNext()!=self.__head:
probe=probe.getNext()
while probe !=self.__head:
res=res+str(probe.getData())+','
probe=probe.getNext()
return res
def insertFirst(self,data):
if self.__head==None:
self.__head=Node(data,self.__head)
self.__tail=self.__head
self.__head.setNext(self.__head)
else:
self.__head=Node(data,self.__head)
self.__tail.setNext(self.__head)
63

Petia Ivanova Radeva

Estructuras Enlazadas Dobles

from node import *


class TwoWayNode(Node):
def __init__(self,data,previous=None, next=None):
Node.__init__(self,data,next)
self.__previous=previous

64

Estructuras Enlazadas Dobles

65

Estructuras Enlazadas Dobles


def traverse(self):
Traversing from front to back
probe=self.__head
while probe!= None:
print probe.getData(),
probe=probe.getNext()

def traverseback(self):
Traversing from back to front
probe=self.__tail
while probe!= None:
print probe.getData(),
probe=probe.getPrevious()

66

Estructuras Enlazadas Dobles


from twowaynode import *
class DoubleLinkedList:
def __init__(self):
self.__head=None
self.__tail=None
def initialize(self,until):
'''Add X twowaynodes to the linked structure''
self.__head=TwoWayNode(0)
self.__tail=self.__head
for count in xrange(1,until):
self.__tail.setNext(TwoWayNode(count,self.__tail))
self.__tail=self.__tail.getNext()
67

Relacin con la prctica

Dadas las clases de la prctica: Card, Deck, Discard_Pile,


Player y Players, cul de stas se puede implementar como
una lista enlazada?
Qu tipo de lista exactamente utilizarais?

Tema 3

Pilas y Colas

Petia Ivanova Radeva

68

Relacin con la prctica

Cmo sera la pila implementada como lista enlazada?


Dibujarla
Disear el TDA
Implementarla

Tema 3

Pilas y Colas

Petia Ivanova Radeva

69

Relacin con la prctica

Cmo sera la cola y la cola de prioridad implementadas


como listas enlazadas?
Dibujarlas
Disear los TDA
Implementarlas

Tema 3

Pilas y Colas

Petia Ivanova Radeva

70

Resumen

Las colecciones son objetos que contienen 0 o ms objetos

Una estructura de datos es un objeto usado para representar los datos


contenidos en una coleccin

Un array es una estructura de datos que suporta acceso aleatorio, en


tiempo constante O(1), a cualquier elemento suyo a travs de su posicin

La insercin y el borrado en un array tiene coste O(n)

Puede ser bi-dimensional (grid) .

Categoras principales: lineal, jerrquica, grafo, y sin orden


Las colecciones son iterable
Las colecciones son tipos de datos abstractos

Cul es el coste del borrado en un grid?

71

Petia Ivanova Radeva

Resumen

Una estructura enlazada es una estructura de datos que consiste en 0 o


ms nodos
Un nodo enlazado simple contiene un elemento para los datos y un enlace
para el siguiente nodo
Las inserciones y los borrados en estructuras enlazadas no requiren trasladar
elementos de datos -> Coste O(1)
El recorruido y la bsqueda de elementos son secuenciales y por lo tanto
tienen coste O(n)

Las listas circulares y las listas enlazadas dobles permiten moverse en las
dos direcciones con mayor eficiencia
Normalmente, la dualidad del coste en trminos de tiempo y memoria de los
algoritmos

72

Petia Ivanova Radeva

Estructuras enlazadas: pilas, colas,


listas circulares y doblemente
enlazadas
Tema 5

Brad Miller, David Ranum, Problem Solving with Algorithms and Data Structures Release 3.0, 2013.
Pat Morin, Open Data Structures (in pseudocode), Edition 0.1G, http://opendatastructures.org.

Implementacin de la clase pila


class Stack:
Define un TDA Pila
def __init__(self):

def __str__(self):
def isEmpty(self):
def push(self, item):
def pop(self):
def peek(self):
def __len__(self):
Tema 3

Pilas y Colas

Petia Ivanova Radeva

Pila: Constructor

self.__head

class LinkedStack:
This is a Linked Stack
def __init__(self):
self.__head=None

Petia Ivanova Radeva

Pila: push()
self.__head

def push(self, item):


if self.__head==None:
self.__head=Node(item)

Petia Ivanova Radeva

Pila: push()
self.__head

D
D
D
D
D

def push(self, item):


if self.__head==None:
self.__head=Node(item)
else:
self.__head=Node(item,self.__head)
5

Petia Ivanova Radeva

Pila: pop()
self.__head

def pop(self, item):


if self.__head==None:
return None

Petia Ivanova Radeva

Pila: pop()
self.__head

D
D
D
D
D

def pop(self):
if self.__head==None:
res=None
else:
res=self.__head.getData()
self.__head=self.__head.getNext()
return res
7

Petia Ivanova Radeva

Implementacin de la Cola
class Queue:
Define un TDA Cola
def __init__(self):
def __str__(self):
def enqueue(self,el):
def dequeue(self):
def isEmpty(self):
def __len__():

Tema 3

Pilas y Colas

Petia Ivanova Radeva

Cola: Constructor
Cuntas variables centinelas
necesitamos?
self.__head
D

self.__tail

class LinkedStack:
This is a Linked Stack
def __init__(self):
self.__head=None
9

Petia Ivanova Radeva

Cola: enqueue()
self.__head
D

def enqueue(self, item):


if self.__head==None:
self.__head=Node(item)
self.__tail=self.__head

10

Petia Ivanova Radeva

Cola: enqueue ()
self.__head
D

self.__tail
D

def enqueue(self, item):


if self.__head==None:
self.__head=Node(item)
self.__tail=self.__head
else:
self.__tail.setNext(Node(item))
self.__tail=self.__tail.getNext()
11

Petia Ivanova Radeva

Extensiones de las estructuras enlazadas

Una estructura circular enlazada con un Nodo de Cabecera

Estructuras Dobles Enlazadas

12

Petia Ivanova Radeva

Variaciones sobre las estructuras enlazadas


lineales: Una estructura enlazada circular

Contiene un enlace desde el ltimo nodo hasta el primer nodo de la


estructura

El nodo de cabeza sirve como un marcador (centinela) para el inicio y el


final de la estructura enlazada

13

Petia Ivanova Radeva

Lista enlazada circular: Constructor

self.__head

14

Petia Ivanova Radeva

Lista enlazada circular: InsertFront


Casos:
self.__head

self.__head

self.__head

15

Petia Ivanova Radeva

Lista enlazada circular: InsertFront


Caso lista vaca:

self.__head

self.__head

16

Petia Ivanova Radeva

Lista enlazada circular: InsertFront


self.__head

self.__head

if self.__head==None:
self.__head=Node(data,self.__head)
self.__head.setNext(self.__head)

17

Petia Ivanova Radeva

Lista enlazada circular: InsertFront


Caso lista con un nodo:

self.__head

18

Petia Ivanova Radeva

Lista enlazada circular: InsertFront


Caso lista con un nodo:

self.__head

elif self.__head.getNext()==self.__head:
self.__head=Node(data,self.__head)
self.__head.getNext().setNext(self.__head)
19

Petia Ivanova Radeva

Lista enlazada circular: InsertFront


Caso de lista con varios nodos:

self.__head

20

Petia Ivanova Radeva

Lista enlazada circular: InsertFront


Caso de lista con varios nodos:
probe

self.__head

self.__head=Node(data,self.__head)
probe=self.__head.getNext()
while probe.getNext()!=self.__head:
probe=probe.getNext()

probe.setNext(self.__head)
21

Petia Ivanova Radeva

Lista enlazada circular: InsertFront


def insertFirst(self,data):
if self.__head==None:
self.__head=Node(data,self.__head)
self.__head.setNext(self.__head)
elif self.__head.getNext()==self.__head:
self.__head=Node(data,self.__head)
self.__head.getNext().setNext(self.__head)

Podemos
ahorrar este
pargrafo?

else:
self.__head=Node(data,self.__head)
probe=self.__head.getNext()
while probe.getNext()!=self.__head:
probe=probe.getNext()
probe.setNext(self.__head)

Petia Ivanova Radeva

22

Lista enlazada circular: InsertFront


def insertFirst(self,data):
if self.__head==None:
self.__head=Node(data,self.__head)

elif self.__head.getNext()==self.__head:
self.__head=Node(data,self.__head)
self.__head.getNext().setNext(self.__head)
else:
self.__head=Node(data,self.__head)
probe=self.__head.getNext()
while probe.getNext()!=self.__head:
probe=probe.getNext()
probe.setNext(self.__head)

Petia Ivanova Radeva

23

InsertFront (alternativa)
probe

self.__head

tail

def insertFirst(self,data):
if self.__head==None:
self.__head=Node(data,self.__head)
self.__tail=self.__head
self.__head.setNext(self.__head)
else:
self.__head=Node(data,self.__head)
self.__tail.setNext(self.__head)
24

Petia Ivanova Radeva

Lista circular enlazada (alternativa)


class CircularLinkedList:
def __init__(self):
self.__head=None
self.__tail=None
def insertFirst(self,data):
Ventajas?
if self.__head==None:
self.__head=Node(data,self.__head)
self.__tail=self.__head
self.__head.setNext(self.__head)
else:
self.__head=Node(data,self.__head)
self.__tail.setNext(self.__head)
Petia Ivanova Radeva

25

Lista doblemente enlazada

Una lista enlazada que se puede recorrer en las


dos direcciones

Petia Ivanova Radeva

26

Estructuras Enlazadas Dobles

Cmo definir el nodo?

class Node:

def __init__(self,data,previous=None, next=None):


self.__previous=previous
self.__next=next

from node import *

class TwoWayNode(Node):
def __init__(self,data,previous=None, next=None):
Node.__init__(self,data,next)
self.__previous=previous
27

Lista doblemente enlazada: Constructor

self.__head

class DoubleLinkedList:
Una lista doblemente
enlazada

def __init__(self):
self.__head=None

28

Petia Ivanova Radeva

Estructuras Enlazadas Dobles


def forward(self):
Traversing from front to back
probe=self.__head
while probe!= None:
print probe.getData(),
probe=probe.getNext()

29

Estructuras Enlazadas Dobles


def backword(self):
Traversing from back to front
probe=self.__tail
while probe!= None:
print probe.getData(),
probe=probe.getPrevious()

30

Lista doblemente enlazada: insert()

self.__head

class DoubleLinkedList:
Una lista doblemente
enlazada

def __init__(self):
self.__head=None
self.__tail=None
31

Petia Ivanova Radeva

Lista doblemente enlazada: insertfront()


D

self.__head

self.__tail

def insertFront(self,data):
self.__head=TwoWayNode(data,None, self.__head)
if self.__head.getNext():
self.__head.getNext().setPrevious(self.__head)
32

Petia Ivanova Radeva

Lista doblemente enlazada: insert()


self.__head

D
D

self.__tail

Qu casos de excepcin hemos de considerar?

33

Petia Ivanova Radeva

Relacin con la prctica

Dadas las clases de la prctica: Card, Deck, Discard_Pile, Player y Players,


cul de stas tiene sentido implementarla como lista enlazada?
Qu tipo de lista exactamente utilizar?

Tema 3

Pilas y Colas

Petia Ivanova Radeva

34

Relacin con la prctica

Cmo sera la pila implementada como lista enlazada?


Dibujarla
Disear el TDA
Implementarla

Tema 3

Pilas y Colas

Petia Ivanova Radeva

35

Relacin con la prctica

Cmo sera la cola y la cola de prioridad implementadas


como listas enlazadas?
Dibujarlas
Disear los TDA
Implementarlas

Tema 3

Pilas y Colas

Petia Ivanova Radeva

36

Skiplistas

Cmo conseguir el acceso, insercin y borrado en una lista


en tiempo O(log n)?

Se basa en el concepto de la randomizacin.

Suponen listas ordenadas.

Bi liografa: Pat Morin, Open Data tru tures in pseudo ode , Edition . G

Petia Ivanova Radeva

37

Skiplistas

Definicin: una skiplista es una secuencia de listas enlazadas L0, L1, Lr,
donde L0 es la lista original ordenada.

Construccin: Construimos recursivamente las listas Lr de las listas Lr-1


escogiendo aleatoriamiante un subconjunto de elementos de Lr-1.

Petia Ivanova Radeva

38

Skiplistas

En una skiplista, para cada elemento x se define su altura en funcin de


en cuantas sublistas pertenece. La altura mxima de los elementos define
la altura de la skiplista.
Como primer elemento de cada lista est un nodo llamado
centinela/cabecera.
Se puede demostrar que la altura de cada elemento corresponde a
cuntas veces ha sido escogido aleatoriamente?

Petia Ivanova Radeva

39

Skiplistas: buscar un elemento (find)

Se puede demostrar que la


bsqueda se hace en O(log n)

Petia Ivanova Radeva

40

Skiplistas: aadir un elemento (insert)

Se puede demostrar que la


insercin se hace en O(log n)

Petia Ivanova Radeva

41

Skiplistas: borrar un elemento (remove)

Se puede demostrar que el


borrado se hace en O(log n)

Petia Ivanova Radeva

42

Indexacin eficiente en las skiplistas

Si codificamos cada arco con


el nmero de elementos en
la lista L0, podemos ir a la
direccin i en O(log n).
Cmo?

Petia Ivanova Radeva

43

Extender la insercin y el borrado actualizando


los arcos (homework)

Petia Ivanova Radeva

44

Resumen

Una estructura enlazada es una estructura de datos que consiste en 0 o ms


nodos
Un nodo enlazado simple contiene un elemento para los datos y un enlace para el
siguiente nodo
Las inserciones y los borrados en estructuras enlazadas no requiren trasladar elementos
de datos -> Coste O(1)
El recorruido y la bsqueda de elementos son secuenciales y por lo tanto tienen coste
O(n)

Las listas circulares y las listas enlazadas dobles permiten moverse en las dos
direcciones con mayor eficiencia
Normalmente, la dualidad del coste en trminos de tiempo y memoria de los
algoritmos

Las pilas y las colas son fcilmente implementadas como listas enlazadas

Las skiplistas aseguran O(log n) para las operaciones bsicas.


45

Petia Ivanova Radeva

You might also like