Python Avançado
Ernesto Revilla
Software Integrado para o Controle de Empresas, Lda.
GCubo: Grupo de usuários de GNU/Linux de Granada
[Link]. Informática (Univ. Granada)
Abril 2004
GCubo: Grupo de usuários de GNU/Linux de Granada
Herencia simple desde tipos internos
Python, desde a versão 2.2, permite herdar de tipos de dados internos,
como:
●
int, float, complex, str, unicode
●
list, dict, tuple
classe DefaultDict(dict):
def __init__(self, valoresIniciais=None, padrao=0.0):
dict.__init__(valoresIniciais ou {})
self._default=default
def __getitem__(self, key):
tente:
return dict.__getitem__(self, chave)
exceto KeyError:
return self._default
se __nome__=="__principal__":
d=DefaultDict({'a': 5})
print 'valor de e:', d['e']
print 'valor de a:', d['a']
Veja [Link]
GCubo: Grupo de usuários de GNU/Linux de Granada
Simular tipos internos 1
Existem construções sintáticas que facilitam a redação dos programas,
como [ ], { }, !=, ... Podemos personalizar seu comportamento.
Realizamos um dicionário por delegação:
class MiDicc:
def __init__(self, diccInicial=None):
self._dicc=dict(diccInicial ou {})
def __getitem__(self, item):
lendo, item
return self._dicc[item]
def __setitem__(self, item, valor):
print "estabelecendo", item
self._dicc[item]=valor
def zap(self):
self._dicc={}
def __getattr__(self, attr):
se attr estiver em ['itens', 'chaves', 'valores']:
return getattr(self._dicc, attr)
Veja [Link].
GCubo: Grupo de usuários de GNU/Linux de Granada
Simular tipos internos 2
Usar as entradas do dicionário como atributos:
classe MiDicc2(MiDicc):
def __getattr__(self, attr):
return MiDicc.__getitem__(self, attr)
def __setattr__(self, attr, valor):
MiDicc.__setitem__(self, attr, valor)
produzir bucle infinito!!, ao estabelecer atributo _dicc em MiDicc
def __setattr__(self, attr, valor):
se attr não estiver em ['_dicc']:
MiDicc.__setitem__(self, attr, valor)
senão:
MiDicc.__dict__['_dicc']=valor
# se MiDicc tivesse herdado de object
# MiDicc.__setattr__(self, attr, valor)
Veja [Link].
GCubo: Grupo de usuários de GNU/Linux de Granada
Um exemplo prático
Para este ejemplo es necesario tener la base de datos sqlite ([Link]),
como também o binding para python ([Link]).
Conexão a um bd sqlite:
importar sqlite
con=[Link]('[Link]')
cur=[Link]()
def criarTabela():
[Link]("criar tabela personas (num inteiro, "
"nombre text, "apellidos text, edad integer;")
def insertarDatosEjemplo():
personas=[ [1, 'Erny', 'Revilla'], [2, 'Lorenzo', 'Gil'],
[3, 'Dani', 'Molina']]
para persona em personas:
[Link]("insert into personas (num, nombre, "
apellidos) valores (%s, '%s', '%s');
Veja os arquivos [Link], [Link] e [Link] que mostram como pode ser criada uma
pequeña capa de persistencia para objetos.
GCubo: Grupo de utilizadores de GNU/Linux de Granada
Coisas sobre __init__
●
__init__ representa o método de inicialização de instância, não é o
inicializador (como em c++) em vez de construtor.
●
__init__ é chamado depois que a memória foi reservada e realizada
uma mínima inicialização do objeto.
●
ao realizar herança múltipla, é necessário definir __init__ para indicar o
ordem das chamadas de __init__ das superclasses
classe A(object):
def __init__(self):
print "__init__ de A"
classe B(objeto):
def __init__(self):
print "__init__ de B"
class C(A,B): pass # isso está errado!!!
c=C()
classe C(A,B):
def __init__(self):
A.__init__(self)
B.__init__(self)
Veja [Link] GCubo: Grupo de usuários de GNU/Linux de Granada
__new__, o construtor
●
__new__ é sempre um método de classe
●
__new__ aparece en la versión 2.2 de python
●
com __new__ também se podem devolver instâncias de outros tipos.
Exemplos:
classe A (objeto):
def __init__(self, *args, **kwargs):
print "criando objeto do tipo A com "
"argumentos pos. %s y argumentos nombrados %s"
% (args, kwargs)
# devolver outros tipos de objetos
classe B(objeto):
def __new__(cls, *args, **kwargs):
retornar A(*args, **kwargs)
x=B(1,2, pepe='no')
Veja [Link]
GCubo: Grupo de usuários de GNU/Linux de Granada
__new__: singleton
# singleton:
classe Singleton(object):
_instance=None
def __new__(cls, *args, **kwargs):
se não cls._instance:
Criando Singleton
cls._instance=object.__new__(cls, *args,
**kwargs)
return cls._instance
def __init__(self, *args, **kwargs):
Inicializando Singleton
s=Singleton()
s=Singleton()
GCubo: Grupo de usuários de GNU/Linux de Granada
Metaclases
●
Ao terminar a leitura da definição de uma classe, o Python cria esta usando
una metaclase de forma Metaclase(nombre, superclases, diccionario)
●
Nome é o nome da classe, Superclasses é uma tupla
●
dicionário contém as funções e identificadores definidos dentro da
classe
●
Atualmente (>=2.2) usa duas metaclasses, uma para as classes antigas
([Link]) e outra para os novos (type)
●
Na metaclasse, podemos definir novos atributos ou funções para a classe
class Metaclasse(type):
def __init__(self, nome, bases, dic):
type.__init__(self, nome, bases, dic)
Definindo classe %s:
imprimir "Bases: %s" % (bases ou None)
print "Dict: %s" % dic
classe A(objeto):
__metaclass__=Metaclase
_attributes=["at1","at2","at3"]
y=5
def __init__(self):
self.x=10 GCubo: Grupo de usuários de GNU/Linux de Granada
Metaclases 2
Veja [Link] para o exemplo anterior.
O seguinte exemplo cria novos métodos em uma classe (getters e setters) para
os atributos especificados.
class Metaclase(type):
def __init__(self, nome, bases, dic):
type.__init__(self, nome, bases, dic)
se "_attributes" em dic:
para attr em dic['_atributos']:
f=lambda s,a=attr: getattr(s,a)
setattr(self, 'get'+attr, f)
f=lambda s, valor, a=attr: setattr(s,a,valor)
setattr(self, 'set' + attr, f)
Veja [Link]
GCubo: Grupo de usuários de GNU/Linux de Granada