El soporte de POO de Python es bastante completo, comparable a Java, C# o C++. El concepto esencial de "objeto" se refiere a la existencia de un estado persistente. Las funciones solo operan en relación a sus parámetros para obtener un resultado y, por regla general, no tienen estado.
Los objetos sin embargo tienen atributos, que son datos accesibles por los métodos (funciones asociadas al objeto) entre invocaciones sucesivas durante la vida del objeto. Los objetos que tienen los mismo métodos y los mismo atributos son instancias de una misma clase. Las clases se definen con la palabra reservada class:
In [1]:
%%file bank/__init__.py
class BankAccount(object):
def __init__(self):
self.balance = 0
def withdraw(self, amount):
self.balance -= amount
return self.balance
def deposit(self, amount):
self.balance += amount
return self.balance
# ejemplo extraido de "python-practice-book"
In [2]:
from bank import BankAccount
BankAccount.withdraw
Out[2]:
In [3]:
b = BankAccount()
b.withdraw
Out[3]:
En este ejemplo:
A continuación crearemos 2 instancias de esta clase:
In [4]:
account_a = BankAccount()
account_b = BankAccount()
account_a.balance
Out[4]:
In [5]:
account_a.deposit(200)
Out[5]:
In [6]:
account_a.deposit(100)
Out[6]:
In [7]:
BankAccount.__dict__
Out[7]:
Si se aplica a una instancia, contiene los atributos:
In [8]:
account_a.__dict__
Out[8]:
In [9]:
class A(object):
_size = 20
@classmethod
def size(cls):
return cls._size
A.size()
Out[9]:
In [10]:
A().size()
Out[10]:
In [11]:
class A(object):
@staticmethod
def show():
return "static"
print(A.show())
print(A().show())
In [12]:
class A(object):
names = []
def add(self, name):
self.names.append(name)
a1 = A()
a2 = A()
a1.add("foo")
a2.add("bar")
print(a1.names)
print(A.names)
In [13]:
class MinimumBalanceException(Exception):
pass
class MinimumBalanceAccount(BankAccount):
def __init__(self, minimum_balance):
super(MinimumBalanceAccount, self).__init__()
self.minimum_balance = minimum_balance
def withdraw(self, amount):
if self.balance - amount < self.minimum_balance:
raise MinimumBalanceException(self.balance - amount)
return BankAccount.withdraw(self, amount)
minimum_account = MinimumBalanceAccount(100)
minimum_account.deposit(400)
minimum_account.withdraw(350)
In [14]:
type(account_a)
Out[14]:
In [15]:
type(minimum_account)
Out[15]:
Pertenencia a una clase:
In [16]:
help(isinstance)
In [17]:
isinstance(account_a, BankAccount)
Out[17]:
In [18]:
isinstance(account_a, MinimumBalanceAccount)
Out[18]:
Comprobación de la jerarquía:
In [19]:
help(issubclass)
In [20]:
issubclass(MinimumBalanceAccount, BankAccount)
Out[20]:
In [21]:
issubclass(MinimumBalanceAccount, object)
Out[21]:
In [22]:
f = account_a.deposit
f(100)
Out[22]:
In [23]:
BankAccount
Out[23]:
In [24]:
class A(object):
pass
class B(A):
pass
def make(cls):
return cls()
a = make(A)
a
Out[24]:
type es la clase de las clases, en decir, una metaclase. Concretamente es la superclase de todas las metaclases.
In [25]:
type(A)
Out[25]:
In [26]:
type(type)
Out[26]:
Creando una clase al vuelo con type():
In [27]:
SomeClass = type("SomeClass", (), {})
some = SomeClass()
some
Out[27]:
Clases base de una clase
In [28]:
B.__bases__
Out[28]:
Clases que especializan una clase:
In [29]:
A.__subclasses__()
Out[29]:
Orden de resolución de métodos:
In [30]:
B.mro()
Out[30]:
Clase de una instancia:
In [31]:
some.__class__
Out[31]:
Averiguar si un objeto tiene un atributo:
In [32]:
hasattr(some, "missing_attribute")
Out[32]:
Obtener o cambiar el valor de un atributo dado su nombre:
In [33]:
setattr(some, "foo", 5)
getattr(some, "foo")
Out[33]: