From 19cda4a8b946ef2265fb182e1e672b2df5adcd44 Mon Sep 17 00:00:00 2001
From: Julio Biason
>>> a = {'Python': 'Rocks',
->>> 1: 1.0}
+... 1: 1.0}
@@ -411,7 +411,7 @@ set(['a'])
a = 1L
)a = lambda a: a + 2
)r'string\s'
, usadas para regex)r'string\s'
, usadas para regex)
>>> if a == 1:
->>> b = 2
+... b = 2
>>> c = 3
@@ -445,9 +445,9 @@ set(['a'])
>>> a = 1
>>> while True:
->>> a += 1
->>> if a > 10:
->>> break
+... a += 1
+... if a > 10:
+... break
@@ -514,7 +514,7 @@ True
>>> soma = 0
>>> for valor em [345, 123, 123, 34]:
->>> soma += valor
+... soma += valor
@@ -545,7 +545,7 @@ True
>>> for l in 'Python':
->>> print l
+... print l
@@ -555,7 +555,7 @@ True
>>> d = {'Python': 'Rocks', 'Parrot': 'Dead', 'Favorite Color': 'Blue'}
>>> for key in d:
->>> print key, d[key]
+... print key, d[key]
@@ -565,7 +565,7 @@ True
>>> d = {'Python': 'Rocks', 'Parrot': 'Dead', 'Favorite Color': 'Blue'}
>>> for (key, value) in d.iteritems():
->>> print key, value
+... print key, value
Forma considerada "correta" é a anterior.
@@ -595,7 +595,7 @@ iterável[start:end:step]
>>> a = [1, 2, 3, 4]
->>> print a[1:2]
+... print a[1:2]
[2]
>>> a = [1, 2, 3, 4]
->>> print a[:2]
+... print a[:2]
[1, 2]
@@ -621,7 +621,7 @@ iterável[start:end:step]
>>> a = [1, 2, 3, 4]
->>> print a[1:-1]
+... print a[1:-1]
[2, 3]
@@ -631,7 +631,7 @@ iterável[start:end:step]
>>> a = 'Python Rocks'
->>> print a[7:-1]
+... print a[7:-1]
'Rock'
@@ -640,7 +640,7 @@ iterável[start:end:step]
Deixar os dois índices em branco cria uma cópia "flat".
>>> a = [1, 2, 3, 4]
->>> print a[:]
+... print a[:]
[1, 2, 3, 4]
@@ -672,7 +672,7 @@ iterável[start:end:step]
>>> def funcao(a, b, c):
->>> return (a + b) / c
+... return (a + b) / c
@@ -681,7 +681,7 @@ iterável[start:end:step]
>>> def funcao(a, b, c):
->>> return (a + b) / c
+... return (a + b) / c
>>>
>>> funcao(b=2, c=3, a=10)
4
@@ -734,6 +734,8 @@ iterável[start:end:step]
Não existe função para o destrutor.
+ (Existe, mas ninguém usa.)
+
Existem ainda outras funções
mágicas, mas não vamos falar sobre elas
nesse momento.
@@ -741,10 +743,10 @@ iterável[start:end:step]
>>> class MyClasse(object):
->>> def __init__(self):
->>> self.valor = 0
->>> def show(self):
->>> print self.valor
+... def __init__(self):
+... self.valor = 0
+... def show(self):
+... print self.valor
@@ -766,10 +768,10 @@ iterável[start:end:step]
>>> class MyClasse(object):
->>> def __init__(self, name):
->>> self.name = name
->>> def show(self):
->>> print self.name
+... def __init__(self, name):
+... self.name = name
+... def show(self):
+... print self.name
>>> my = MyClasse('Julio')
>>> my.show()
@@ -777,17 +779,34 @@ Julio
+
+ Propriedades podem ser injetadas a qualquer momento.
+
+
+>>> class A(object):
+... def __init__(self):
+... self.value = 10
+>>>
+>>> a = A()
+>>> a.name = 'Julio'
+
+
+ Inserção de propriedades pode ser
+ barrada com o uso da variável mágica
+ __slots__
, mas raramente é usado.
+
+
Herança
>>> class A(object):
->>> def __init__(self):
->>> self.value = 10
+... def __init__(self):
+... self.value = 10
>>> class B(A):
->>> def __init__(self):
->>> super(B, self).__init__()
->>> self.name = 'AAAA'
+... def __init__(self):
+... super(B, self).__init__()
+... self.name = 'AAAA'
@@ -796,14 +815,14 @@ Julio
>>> class A(object):
->>> def __init__(self):
->>> self.value = 10
+... def __init__(self):
+... self.value = 10
>>> class B(object):
->>> def __init__(self):
->>> self.name = 'AAAA'
+... def __init__(self):
+... self.name = 'AAAA'
>>> class C(A, B):
->>> def __init__(self):
->>> super(C, self).__init__()
+... def __init__(self):
+... super(C, self).__init__()
@@ -812,17 +831,124 @@ Julio
- Propriedades podem ser injetadas a qualquer momento.
+ super()
é mais usado para resolução
+ hierárquia com herança múltipla.
+
+
->>> class A(object):
->>> def __init__(self):
->>> self.value = 10
->>>
->>> a = A()
->>> a.name = 'Julio'
+>>> class Adao(object): pass
+>>> class Eva(object): pass
+>>> class AvoPaterno(Adao, Eva): pass
+>>> class AvohPaterna(Adao, Eva): pass
+>>> class AvoMaterno(Adao, Eva): pass
+>>> class AvohMaterna(Adao, Eva): pass
+>>> class Pai(AvoPaterno, AvohPaterna): pass
+>>> class Mae(AvoMaterno, AvohMaterna): pass
+>>> class Filho(Pai, Mae): pass
+
+
+
+>>> help(Filho)
+
+
+
+
+
+Help on class Filho in module __main__:
+
+class Filho(Pai, Mae)
+ | Method resolution order:
+ | Filho
+ | Pai
+ | AvoPaterno
+ | AvohPaterna
+ | Mae
+ | AvoMaterno
+ | AvohMaterna
+ | Adao
+ | Eva
+ | __builtin__.object
+
+
+
+
+ A ordem de resolução pode ser usada para inserir
+ mocks sem o uso de mocks.
+
+ ... embora só sirva para mockar
+ objetos "é um" e não "contém um".
+
+
+
+
+>>> class Robo(object):
+... def pegar(self, ferramenta):
+... print 'Pegando', ferramenta
+... def pra_frente(self):
+... print 'Movendo pra frente'
+... def pra_tras(self):
+... print 'Voltando'
+... def largar(self):
+... print 'Largando ferramenta'
+
+
+
+
+
+>>> class RoboDeLimpeza(Robo):
+... def clean(self, repeticoes=10):
+... super(Robo, self).pegar('vassoura')
+... for _ in xrange(repeticoes):
+... super(Robo, self).pra_frente()
+... super(Robo, self).pra_tras()
+... super(Robo, self).largar()
+
+
+
+
+
+>>> class MockRobo(Robo):
+... def __init__(self):
+... self.acoes = []
+... def pegar(self, ferramenta):
+... self.acoes.append('Pegar {}'.format(ferramenta))
+... def pra_frente(self):
+... self.acoes.append('frente')
+... def pra_tras(self):
+... self.acoes.append('tras')
+... def largar(self):
+... self.acoes.append('largar')
+
+
+
+
+
+>>> class MockRoboDeLimpeza(RoboDeLimpeza, MockRobo):
+... pass
+
+
+
+
+
+Help on class MockRoboDeLimpeza in module __main__:
+
+class MockRoboDeLimpeza(RoboDeLimpeza, MockRobo)
+ | Method resolution order:
+ | MockRoboDeLimpeza
+ | RoboDeLimpeza
+ | MockRobo
+ | Robo
+ | __builtin__.object
+
+
+
+ Mais informações no vídeo de Raymond Hettinger:
+ Super Considered super!
+
+
@@ -867,9 +993,8 @@ Julio
>>> def a(l=[]):
->>> l.append(1)
->>> print l
->>>
+... l.append(1)
+... print l
>>> a()
[1]
>>> a()
@@ -882,10 +1007,9 @@ Julio
>>> def a(l=None):
->>> if not l:
->>> l = []
->>> l.append(1)
->>>
+... if not l:
+... l = []
+... l.append(1)
>>> a()
[1]
>>> a()
@@ -906,8 +1030,7 @@ Julio
>>> def a(*args):
->>> print args
->>>
+... print args
>>> a(1)
[1]
>>> a(1, 2, 3, 4, 5)
@@ -920,8 +1043,7 @@ Julio
>>> def a(**kwargs):
->>> print kwargs
->>>
+... print kwargs
>>> a(a=1)
{'a': 1}
>>> a(value1=10, a=2)
@@ -934,9 +1056,8 @@ Julio
>>> def a(*args, **kwargs):
->>> print args
->>> print kwargs
->>>
+... print args
+... print kwargs
>>> a(a=1)
[]
{'a': 1}
@@ -949,17 +1070,72 @@ Julio
>>> def a(a, b, *args, name=None, **kwargs):
->>> print 'a =', a
->>> print 'b =', b
->>> print 'args =', args
->>> print 'name = ', name
->>> print 'kwargs =', kwargs
+... print 'a =', a
+... print 'b =', b
+... print 'args =', args
+... print 'name = ', name
+... print 'kwargs =', kwargs
Saída de uma chamada desta função fica a cargo do leitor.
+
+
+ for
tem else
+
+
+
+
+>>> for i in xrange(10):
+... if i == 1:
+... break
+... else:
+... print 'Oh no'
+
+
+ WAT
+
+
+
+ for
tem else
+
+ else
é chamado se a execução do loop
+ chegar ao final.
+
+
+>>> for record in all_content:
+... if record.name = search:
+... found = record
+... break
+... else:
+... found = None
+
+
+
+
+
+
+ try
tem else
+
+
+
+
+>>> try:
+... func_that_raises_exception()
+... else:
+... print 'Yay!'
+
+
+ else
é chamado quando
+ exceções não ocorrerem.
+
+ finally
+ SEMPRE é chamado.
+
+
+
"Functions are First Class Citizens"
@@ -968,12 +1144,10 @@ Julio
>>> def funcao(a, b, c):
->>> return (a + b) / c
->>>
+... return (a + b) / c
>>> def check(a, b, c, condition, function):
->>> if condition:
->>> print function(a, b, c)
->>>
+... if condition:
+... print function(a, b, c)
>>> check(1, 2, 3, True, funcao)
1
>>> check(1, 2, 3, False, funcao)
@@ -988,12 +1162,10 @@ Julio
>>> class A(object):
->>> def __init__(self):
->>> self.value = 10
->>>
->>> def show_name(self):
->>> print 'Julio'
->>>
+... def __init__(self):
+... self.value = 10
+... def show_name(self):
+... print 'Julio'
>>> a = A()
>>> a.show = show_name
>>> a.show()
@@ -1017,7 +1189,7 @@ Julio
>>> def retrieve(connection):
->>> # faz algo com a conexão para recuperar dados.
+... # faz algo com a conexão para recuperar dados.
Problema: antes de sair executando algo na conexão, tem que ser
@@ -1030,15 +1202,15 @@ Julio
>>> def retrieve(connection):
->>> # faz algo com a conexão para recuperar dados.
->>>
+... # faz algo com a conexão para recuperar dados.
+
>>> def update(connection):
->>> # atualiza algo usando a função
->>>
+... # atualiza algo usando a função
+
>>> def check(connection, call):
->>> if not connection.is_connected:
->>> connection.retry()
->>> call(connection)
+... if not connection.is_connected:
+... connection.retry()
+... call(connection)
Novo problema: Todo lugar onde antes era chamado retrieve
@@ -1052,18 +1224,17 @@ Julio
>>> from functools import wrap
->>>
>>> def check(func):
->>> def check_conn(*args, **kwargs):
->>> # acha a conexão em args ou kwargs
->>> if not connection.is_connected:
->>> connection.retry()
->>> return func(*args, **kwargs)
->>> return check_conn
->>>
+... def check_conn(*args, **kwargs):
+... # acha a conexão em args ou kwargs
+... if not connection.is_connected:
+... connection.retry()
+... return func(*args, **kwargs)
+... return check_conn
+
>>> @check
>>> def retrieve(connection):
->>> # faz algo com a conexão para recuperar dados
+... # faz algo com a conexão para recuperar dados
Não precisa alterar nenhuma chamada de retrieve
.
@@ -1078,22 +1249,22 @@ Julio
>>> class CheckConn(object):
->>> def __init__(self, func):
->>> self.func = func
->>>
->>> def __call__(self, *args, **kwargs):
->>> if 'connection' in kwargs:
->>> connection = kwargs['connection']
->>> else:
->>> connection = args[0]
->>>
->>> if not connection.is_connected:
->>> connection.retry()
->>> self.func(*args, **kwargs)
+... def __init__(self, func):
+... self.func = func
+...
+... def __call__(self, *args, **kwargs):
+... if 'connection' in kwargs:
+... connection = kwargs['connection']
+... else:
+... connection = args[0]
+...
+... if not connection.is_connected:
+... connection.retry()
+... self.func(*args, **kwargs)
>>> @CheckCon
>>> def retrieve(connection):
->>> # retrieve
+... # retrieve
@@ -1111,16 +1282,16 @@ Julio
>>> class CheckConn(object):
->>> def __init__(self, func):
->>> self._func = func
->>>
->>> @property
->>> def func(self):
->>> return self._func
->>>
->>> @func.setter
->>> def func(self, value):
->>> self._func = func
+... def __init__(self, func):
+... self._func = func
+...
+... @property
+... def func(self):
+... return self._func
+...
+... @func.setter
+... def func(self, value):
+... self._func = func
@@ -1129,112 +1300,112 @@ Julio
>>> class CheckConn(object):
->>> def __init__(self, func):
->>> self._func = func
->>>
->>> @staticmethod
->>> def from_text(self, text):
->>> return CheckConn(getattr(self, text))
+... def __init__(self, func):
+... self._func = func
+...
+... @staticmethod
+... def from_text(self, text):
+... return CheckConn(getattr(self, text))
-
-
- Comprehensions e Generators
+
+
+ Comprehensions e Generators
- Python permite criar listas processando listas sem
- for
com list
- comprehensions.
+ Python permite criar listas processando listas sem
+ for
com list
+ comprehensions.
-
+
>>> a = [1, 2, 3]
>>> [item * 2 for item in a]
>>> [2, 4, 6]
-
+
- Pra quem gosta de coisas "funcionais", é o mesmo que
- map
.
+ Pra quem gosta de coisas "funcionais", é o mesmo que
+ map
.
-
+
>>> a = [1, 2, 3]
>>> map(lamba f: f * 2, a)
>>> [2, 4, 6]
-
-
+
+
-
- Comprehensions (contd.)
- É possível filtrar elementos com list comprehensions.
+
+ Comprehensions (contd.)
+ É possível filtrar elementos com list comprehensions.
-
+
>>> a = [1, 2, 3]
>>> [item for item in a if item > 2]
>>> [3]
-
+
- Funcionalmente, é o mesmo que filter
.
+ Funcionalmente, é o mesmo que filter
.
-
+
>>> a = [1, 2, 3]
>>> filter(lambda f: f > 2, a)
>>> [3]
-
-
+
+
- Enquanto que comprehensions criam novas listas, generators - geram elementos sob demanda.
+Enquanto que comprehensions criam novas listas, generators + geram elementos sob demanda.
-
+
>>> a = [1, 2, 3]
>>> (item * 2 for item in a)
<generator object <genexpr> at 0x7f8673dfc050>
-
-
+
>>> [item for item in range(5000000)]
-
+
- vs
+vs
-
+
>>> (item for item in xrange(5000000))
-
-
+
>>> [item for item in range(5000000)][:5]
-
+
- vs
+vs
-
+
>>> (item for item in xrange(5000000))[:5]
-
-
+
>>> def gen(max_value):
->>> for value in xrange(max_value):
->>> yield value * 2
-
+... for value in xrange(max_value):
+... yield value * 2
+
- Generator functions não podem ter return
!
Generator functions não podem ter return
!
+
>>> class Connection(object):
->>> def __init__(self):
->>> self._conn = None
->>>
->>> def __enter__(self):
->>> self._conn = self._make_connection()
->>> return self._conn
->>>
->>> def __exit__(self, exc_type, exc_value, traceback):
->>> self._conn.close()
->>> if exc_type: # then exc_value and traceback
->>> print "Exception!", exc_type, exc_value
->>> print traceback
-
-
-
+... def __init__(self):
+... self._conn = None
+...
+... def __enter__(self):
+... self._conn = self._make_connection()
+... return self._conn
+...
+... def __exit__(self, exc_type, exc_value, traceback):
+... self._conn.close()
+... if exc_type: # then exc_value and traceback
+... print "Exception!", exc_type, exc_value
+... print traceback
+
+
+
>>> with Connection() as connection:
->>> connection.request('Value')
-
+... connection.request('Value')
+
+
>>> try:
->>> conn = self._make_connection()
->>> conn.request('value')
->>> finally:
->>> conn.close()
->>> except Exception as exc: # Bare exceptions are BAAAADDD!
->>> print 'Exception!', exc
-
+... conn = self._make_connection()
+... conn.request('value')
+... finally:
+... conn.close()
+... except Exception as exc: # Bare exceptions are BAAAADDD!
+... print 'Exception!', exc
+
>>> def func(a):
->>> """Função mágica"""
->>> return a
+... """Função mágica"""
+... return a
>>> print func.__doc__
Função mágica
@@ -1388,7 +1559,7 @@ def send(sender, recipient, message_body, priority):
diretórios a serem pesquisados e um makefile com a opção
html para geração de arquivos HTML.)