Document Actions
Send this page to somebody Print this page
Parte 5

Python es un lenguaje orientado a objetos completo. Podes definir tus propias clases, usar herencia con clases provistas por el lenguaje o nuevas clases e instanciar las nuevas clases.

5.1. Clases en Python

Una clase en python posee las siguientes caracteristicas:

  • Se puede llamar una clase como si fuera un función. La clase retorna otro objeto, conocido como instancia de la clase. La clase es tambien reconocida con el tipo de la instancia.
  • Una clase posee atributos con nombre
  • Los atributos de clases estan atados a funciones, conocidos como métodos de clase
>>> class Persona:
...     pass

5.2. Instancia de clases

>>> Persona()
... __main__.Persona instance at 0xb7d19c6c>
>>> p = Persona()
>>> p
<__main__.Persona instance at 0xb7d19c2c>

5.3. Cuerpo de clases: variables de instancias y métodos de clase

>>> class Persona:
...     def __init__(self, nombre, apellido, edad):
...             self.nombre = nombre
...             self.apellido = apellido
...             self.edad = edad
...
>>> Persona('carlos','juarez',10)
<__main__.Persona instance at 0x832fa8c>

class Persona:
"""Una persona"""
    def __init__(self, nombre, apellido, edad):
        self.nombre = nombre
        self.apellido = apellido
        self.edad = edad

    def login(self):
         return self.nombre[0] + self.apellido

    def mail(self):
         return self.login() + '@midominio.com'

    def estadoFisico(self, cantidad):
        self.estado_fisico = cantidad
>>> from persona import Persona  ; p = Persona('cacho','castana',10)
>>> p.estadoFisico(10)
>>> p.estado_fisico
10
class Persona:
    def __init__(self, nombre, apellido, edad, estado=0):
        self.nombre = nombre
        self.apellido = apellido
        self.edad = edad
        self.estado_fisico = estado

    def login(self):
         return self.nombre[0] + self.apellido

    def mail(self):
         return self.login() + '@midominio.com'

5.4 Herencia

from persona import Persona
class Jugador(Persona):
"""Un jugador"""
    def __init__(self, nombre, apellido, edad, estado, posicion):
        Persona.__init__(self, nombre, apellido, edad, estado)
        self.posicion = posicion
        self.titular = False

    def juega(self):
        self.titular = True
        return self.titular

    def no_juega(self):
        self.titular = False
        return self.titular
>>> from jugador import Jugador
>>> riquelme = Jugador('Roman','Riquelme', 22, 10, 10)
>>> riquelme.nombre
'Roman'
>>> riquelme.apellido
'Riquelme'
>>> riquelme.mail
<bound method Jugador.mail of <jugador.Jugador instance at 0xb7da92ec>>
>>> riquelme.mail()
'RRiquelme@midominio.com'
>>> riquelme.juega()
True
>>> riquelme.titular

Cuando usar self

  • En la definición de los métodos de clases, se debe usar self explicitamente como primer argumento (incluyendo __init__)
  • Cuando se llama un método de la clase ancestro, se debe incluir self como argumento
  • Pero cuando se llama la clase desde fuera de la clase, no se debe incluir self

Sobre __init__

  • Los métodos __init__ son opcionales, pero si se usa uno en una subclase se debe llamar explicitamente al ancestro
  • __init__ es ejecutado inmediatamente despues que la clase es creada. Aunque cumple un rol similar, __init__ no es un constructor porque al momento que se ejecuta __init__ la instancia ya está creada.

Mas lectura sobre clases:


5.5 Instanciando clases

>>> from persona import Persona
>>> p = Persona('Ramon', 'Diaz', 40)
>>> p
<persona.Persona instance at 0xb7cf706c>
>>> p.__class__
<class persona.Persona at 0xb7cf511c>
>>> p.__doc__
'Una persona'

Mas lectura


5.6. Garbage collector

>>> def leakmem():
...     p = Persona('Mr','Smith',30)
...
>>> for i in xrange(1000000):
...     leakmem()
Python posee un garbage collector llamado "reference counting", que lleva la cuenta de las referencias a un objeto. En el ejemplo anterior hay una sola referencia a local a p. Cuando leakmen termina, p queda fuera de contexto la el numero de referencias a p va a 0 y Python destruye la instancia automáticamente.
>>> def leakmem():
...     p = Persona('Mr','Smith',30)
...
>>> for i in range(1000000):
...     leakmem()

Mas lectura


5.7. UserDict: Una clase wrapper

class UserDict:                              
    def __init__(self, dict=None):            
        self.data = {}                        
        if dict is not None: self.update(dict)
    def clear(self): self.data.clear()      
    def copy(self):                            
        if self.__class__ is UserDict:         
            return UserDict(self.data)        
        import copy                            
        return copy.copy(self)                
    def keys(self): return self.data.keys()    
    def items(self): return self.data.items() 
    def values(self): return self.data.values()
>>> from UserDict import UserDict
>>> class Equipo(UserDict):
...     "equipo de futbol"
...     def __init__(self, nombre):
...             UserDict.__init__(self)
...             self.nombre = nombre

Herencia de un tipo de datos interno

>>> class Equipo(dict):
...     "equipo de futbol"
...     def __init__(self, nombre):
...             self.nombre = nombre
>>> Equipo('Belgrano')
{}
>>> equipo = Equipo('Belgrano')
>>> equipo
{}

5.8. Métodos especiales

    def __getitem__(self, key): return self.data[key]
>>> r = Equipo('River')
>>> r['aa']='aa'
>>> r['aa']
'aa'
>>> r.__getitem__('aa')
'aa'
    def __setitem__(self, key, item): self.data[key] = item
>>> r.__setitem__('aa','222')
>>> r['aa'] = 222
>>> r
{'aa': '222'}

class Persona:
    """ una persona"""
    def __init__(self, nombre, apellido, edad, estado=0):
        self.nombre = nombre
        self.apellido = apellido
        self.edad = edad
        self.estado_fisico = estado

    def login(self):
         return self.nombre[0] + self.apellido

    def mail(self):
         return self.login() + '@midominio.com'

    def __getitem__(self, attr):
        return getattr(self, attr, 'no es un atributo valido')
>>> p = Persona('juan','diaz',20)
>>> p['nombre']
'juan'
>>> p['nombre'] = 'raul'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: Persona instance has no attribute '__setitem__'

5.9. Otros métodos especiales

  • __repr__
    >>> repr(p)
    '<persona.Persona instance at 0xb7d7b1ac>'
  • __cmp__
    >>> p == p
    True
    >>> cmp(p,p)
    0
    >>> cmp(p,p1)
    -1
    >>> cmp(p1,p)
    1
    >>> cmp.__doc__
    'cmp(x, y) -> integer\n\nReturn negative if x<y, zero if x==y, positive if x>y.'
  • __len__
    >>> p.__len__
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: Persona instance has no attribute '__len__'
  • __delitem__
    >>> del p
    >>> p
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    NameError: name 'p' is not defined

Mas lectura

Python Reference Manual documenta todos los metodos especiales de clases.

5.10. Atributos de clase

>>> class counter:
... count = 0
... def __init__(self):
... self.__class__.count += 1
...
>>> counter
<class __main__.counter at 010EAECC>
>>> counter.count
0
>>> c = counter()
>>> c.count
1
>>> counter.count
1
>>> d = counter()
>>> d.count
2
>>> c.count
2
>>> counter.count
2

5.11. Métodos privados

class Persona:
    """ una persona"""
    def __init__(self, nombre, apellido, edad, estado=0):
        self.nombre = nombre
        self.apellido = apellido
        self.edad = edad
        self.estado_fisico = estado

    def __login(self):
         return self.nombre[0] + self.apellido

    def mail(self):        
return self.__login() + '@midominio.com'

    def __getitem__(self, attr):
        return getattr(self, attr, 'no es un atributo valido')

Ejercicios

  1. Implementar un equipo de futbol completo que tenga diferentes posiciones: arquero, defensor, mediocampista, delantero
  2. Implementar la clase club que tiene muchos equipos de diferentes disciplinas
  3. Hacer una pequeña interface usando input y raw input para crear un club y agregar disciplinas y a cada una equipos. Listar y crear nuevos equipos.

Copyright (C) 2004-2007 Menttes - All Rights Reserved