Aula 19
1 Iterator
Iterator é um thunk do haskell - uma promessa de computação que retorna um elemento por vez.
1.1 classe
- tem que ter um metodo
__iter__que retorna um interator. A funçaoiterchama o metodo__iter__ - tem que ter o metodo
__next__que retorna o proximo elemento. A funçãonextchama o metodo__next__ - gera a exception
StopIterationquando não há mais elementos
x = iter([2,3]) next(x) next(x) next(x)
for x in l:
...
ii=iter(l)
try:
while True:
x = ii.__next__()
...
except StopIteration:
pass
class Repetidor:
def __init__(self,x,n=4):
self.n=n
self.x=x
def __iter__(self):
return self
def __next__(self):
if self.n<=0:
raise StopIteration
else:
self.n-=1
return self.x
1.2 generators
Generators são funcoes que guardam o estado entre uma chamada e
outra. Sintaticamente a unica diferença é usar um yield em vez do
return
def rep(x,n=4):
while n>0:
n-=1
yield x
1.3 generator comprehension
- Como list comprehention, mas usando
(4)
zz= (x*x for x in range(10,1000) if x % 4 == 0) zz.__next__() next(zz)
1.4 intertools
uma biblioteca para iterators https://docs.python.org/3/library/itertools.html
1.5 coroutines
processos que enviam mensagens de um para outro. Normalmente produtores, filtros e consumidores
um filtro precisa receber uma mensagem, e talvez enviar uma outra mensagem para o consumidor final
- enviar mensagem
consumidor.send(msg) - receber mensagem
msg = (yield)
def filtro(padrao,proximo):
print("Comecando filtro")
while True:
msg = (yield)
if padrao in msg:
proximo.send(msg)
def consumidor():
print("Comecando consumidor")
while True:
l=(yield)
print(l)
c=consumidor()
f=filtro("abc",c)
c.__next__() #para chegar no yield
f.__next__() # para chegar no yield
for x in "afh ahabcj agdb yyabctt abc abdddc".split():
f.send(x)
2 exercicios
Sem usar a itertools
- pares: dado um iterator, retorna um iterator com os elementos nas posicoes pares (0,2,..)
- reverte: dado um iterator, reverte ele *
- zip: dado 2 iterators, retorna um iterator que retorna os elementos intercalados
- cart: dado 2 iterators, retorna um iterator com o produto cartesiano dos elementos *
- ciclo: dado um iterator, retorna os elementos num ciclo infinito
- rangeinf(init,passo=1): retorna um iterator que gera numeros de init ate infinito, com passo
- take: como o take do haskell
- drop - como o drop do haskell
3 OO in Python
3.1 class
class Pessoa:
def setidade(self,x):
if x >0 :
self.idade=x
def getidade(self):
return self.idade
So da para definir os metodos. (Normalmente) nao ha a definicao de atributos/campos/variavies
Há sempre o parametro self para os metodos, que indicam o objeto
sobre o qual o metodo esta sendo executado
3.2 objetos
Atribuos/campos/variaveis dos objetos são sempre visiveis e modificaveis!! Nao ha atributos privados
x=Pessoa() x.setidade(12) x.getidade() x.idade x.idade=99 x.nome="jose"
Usualmente indica-se um atributo privado usando dois underscores __nome__
3.3 Construtor
Pessoa() cria um objeto, se existe isso chama o construtor
__init__
class Pessoa:
def __init__(self,idade,nome):
if idade>0:
self.idade=idade
self.nome=nome
x = Pessoa(-45,"jose")
3.4 Herança
class Aluno(Pessoa): pass a=Aluno() isinstance(a,Aluno) isinstance(a,Pessoa)
3.5 atributos de classe
class Pessoa: npernas=2 x=Pessoa() y=Pessoa() x.npernas x.npernas=9 x.npernas y.npernas Pessoa.npernas Pessoa.npernas=10 y.npernas x.npernas
3.6 OO in python?
Usualmente nao se cria um monte de objetos.
Usualmente objetos sao uma interface para as bibliotecas
3.7 Python object model
https://docs.python.org/3/reference/datamodel.html
operator overloading; definir diferentes acoes para o mesmo operador
x[i] acesso em listas e dicionários
- x[i] na verdade chama o metodo
__getitem__(x,i) __str__é chamado pelo print para imprimir um dado (converte p/ string)__init__e__new__sao chamados pelo construtor__eq__(x,y)é chamado na comparacao x == y__getattr__(self, name)chamado emx.a__setattr__para setar um atributo__call__(self[, args...])chamado emx(a,b,c)__len__(self)para len__iter__(self)e__next__(self)ja vimos__add__para +