Você está na página 1de 116

Luciano Ramalho

luciano@ramalho.org
@ramalhoorg

Fácil para começar, difícil de superar

Palestra apresentada na UNIFESP


São José dos Campos em 10/dez/2012
Ada Lovelace
• Ada A. Byron King,
condessa de
Lovelace
• nasceu em
10/dez/1815
• primeira
programadora
(antes de qualquer
homem)
@ramalhoorg
Python:
linguagem de uso geral
• Internet:YouTube, Globo.com, Bitly, Mozilla...
• Computação gráfica: Disney, ILM, AutoDesk...
• Desktop: Dropbox, BitTorrent, OpenOffice...
• Operações: Google, Rackspace, Ubuntu, RedHat...
• Enterprise: IBM, Oracle, ERP5, OpenERP...
• Games, computação científica, segurança, etc...
@ramalhoorg
@ramalhoorg
@ramalhoorg
@ramalhoorg
@ramalhoorg
@ramalhoorg
@ramalhoorg
@ramalhoorg
@ramalhoorg
@ramalhoorg
@ramalhoorg
Google em 1998
Google App Engine
code.google.com/edu/languages
YouTube
Globo.com
Mozilla Firefox Add-Ons
Dropbox
The Foundry, NUKE
Industrial Light & Magic
Autodesk Maya
Invesalius
Civilization IV
Frets on Fire
FBI e CIA
brasil.gov.br
Câmara dos Deputados
http://redmonk.com/sogrady/2012/09/12/
“Vocês são
o centro
do Vale do
Silício hoje”

Paul Graham,
Pycon US 2012
Linguagem
“expressiva”

O que isso
significa
na prática?

Linguagem
COBOL
Java
Java

Python
Python tem sido uma parte
importante do Google desde
o início, e continua sendo à
medida que o sistema cresce
e evolui... estamos procurando
mais pessoas com habilidade
nesta linguagem.

Peter Norvig, Google, Inc.


http://aima.cs.berkeley.edu/code.html
lis.py: interpretador
Lisp (Scheme) em
113 linhas de Python,
por Peter Norvig
>>> from lis import repl

Demo: lis.py
>>> repl()
lis.py> (* 7 3)
21
lis.py> (define resposta (* 6 7))
lis.py> resposta
42
lis.py> (define ! (lambda (n) (if (= n 0) 1 (* n (! (- n 1))))))
lis.py> (! 4)
24
lis.py> (! 5)
120
lis.py> (! 197)
10007840558408082122130389497134473659904776124145643156372043719
15587343235626799299914070366966935566947378481954772384977466613
67777918006944650646265409257583733981874437495228286501182991424
47739508657606635346735333579872783783532869428043930552260307311
88238628318646302096556423610922923784067025686796088553504768000
00000000000000000000000000000000000000000000
lis.py> !
<function <lambda> at 0x1004cbd70>
lis.py>
Sobre Python
• Linguagem dinâmica
• compilador é parte do ambiente de runtime
• Tudo são objetos
• Ex.: inteiros, funções, classes, exceções etc.
• Multi-plataforma
• Interpretador, APIs, bytecode, GUIs etc.
@ramalhoorg
Implementações
• CPython: a principal, escrita em C
• incluída na maioria das distros GNU Linux e no
Mac OS X; vários pacotes para Windows
• Jython: escrita em Java
• parte de IBM WebSphere e Oracle WebLogic
• IronPython: escrita em C#, .net CLR
• desenvolvida pela Microsoft
@ramalhoorg
Implementações (2)
• PyPy: Python em Python
• Implementação em
linguagem de alto-nível
facilitando a inovação
• Desempenho 5x
melhor que CPython
• Incompatível com as
extensões em C
@ramalhoorg
2.5

Python: evolução
2006-09…2011-05

2.6

• Versões do CPython em dez/2012


2008-10 3.0
2008-12…2009-07

3.1
2009-06 • 3.0, 2.5 e anteriores: fossilizadas
• 2.6 e 3.1: manutenção por 5 anos
2.7
2010-07
3.2
2011-02

3.3
• 2.7 e 3.2: versões atuais
• 2.7: versão final da série 2.x
2012-09

• 3.3: lançada em set/2012


3.4
2014-02

⋮ @ramalhoorg
Pythonista: app para iPad

@ramalhoorg
Pythonista
@ramalhoorg
Pythonista
@ramalhoorg
@ramalhoorg
Pythonista
@ramalhoorg
Pythonista
@ramalhoorg
Pythonista
@ramalhoorg
CPython 2.7: instaladores
• GNU Linux: pré-instalado em quase toda distro
• usar gerenciador de pacotes ou compilar (é fácil)
• Windows
• Python.org: instaladores MSI para 32 e 64 bits
• ActiveState ActivePython: 32 e 64 bits
• Mac OS: 32 bits (x86 e PPC), 64 bits (x86)
@ramalhoorg
pythontutor.com
pythontutor.com
Exemplo de doctest
# coding: utf-8
"""
Calcula a média de uma sequência de números

>>> media([10])
10.0
>>> media([10, 20])
15.0
>>> media([1, 2])
1.5

"""

def media(seq):
    return float(sum(seq))/len(seq)

@ramalhoorg
Para executar doctests
• Pela linha de comando:
• $ python -m doctest meu_script.py
• Usando um test-runner (unittest, nose, etc.)
• No próprio script (self-test):
if __name__=='__main__':
    import doctest
    print doctest.testmod(optionflags=doctest.REPORT_ONLY_FIRST_FAILURE
                                     |doctest.REPORT_NDIFF
                                     |doctest.NORMALIZE_WHITESPACE)

@ramalhoorg
Consoles interativos
• python
• integrado em IDEs
• iPython
• online
• bpython
• http://shell.appspot.com/
• IDLE • http://pythonwebconsole.thomnichols.org/
• http://www.pythonanywhere.com/

@ramalhoorg
IDEs, algumas opções
• PyDev (Eclipse)
• PyCharm (JetBrains) $$$
• Komodo Edit
• Komodo IDE $$$
• TextMate $ - OSX
• SublimeText $
• WingIDE $$$
@ramalhoorg
Em vez de IDE:
The Unix environment
• Linux ou OSX ou qualquer Unix:

• janelas de editor, console e navegador ou sua aplicação

• alternar entre janelas com alt-tab: simples, poderoso e eficaz

• Emacs: python-mode.el

• vi: http://www.vex.net/~x/python_and_vim.html

• Geany: um Gedit mais esperto para lidar com vários arquivos

@ramalhoorg
Configure o editor para...
• Indentar com 4 caracteres de espaço ao usar a
tecla TAB ou comandos de indentação multi-linha
• Salvar tabs como 4 espaços, nunca como tabs
• Limpar brancos no final das linhas ao salvar
• Indentação inteligente: preservar indentação da
linha acima e indentar automaticamente após: if,
elif, else, for, while, try, except, finally, def, class, with

@ramalhoorg
Comparando: C e Python
#include <stdio.h>

int main(int argc, char *argv[]) {


int i;
for(i = 0; i < argc; i++)
printf("%s\n", argv[i]);
return 0;
} import sys

for arg in sys.argv:


print arg @ramalhoorg
Iteração em Java

class Argumentos {
public static void main(String[] args) {
for (int i=0; i < args.length; i++)
System.out.println(args[i]);
}
}

$ java Argumentos alfa bravo charlie


alfa
bravo
charlie @ramalhoorg
Iteração em Java ≥1.5 ano:
2004

• Enhanced for (for melhorado)


class Argumentos2 {
public static void main(String[] args) {
for (String arg : args)
System.out.println(arg);
}
}

$ java Argumentos2 alfa bravo charlie


alfa
bravo
charlie @ramalhoorg
Iteração em Java ≥1.5 ano:
2004

• Enhanced for (for melhorado)


class Argumentos2 {
public static void main(String[] args) {
for (String arg : args)
System.out.println(arg);
}
}
ano:
import sys 1991

for arg in sys.argv:


print arg @ramalhoorg
Exemplos de iteração

• Iteração em Python não se limita a tipos primitivos


• Exemplos
• string
• arquivo
• Django QuerySet
@ramalhoorg
>>> from django.db import connection
>>> q = connection.queries
>>> q
[]
>>> from municipios.models import *
>>> res = Municipio.objects.all()[:5]
>>> q
[]
>>> for m in res: print m.uf, m.nome
...
GO Abadia de Goiás demonstração:
MG Abadia dos Dourados
GO Abadiânia queryset é um
MG Abaeté iterável lazy
PA Abaetetuba
>>> q
[{'time': '0.000', 'sql': u'SELECT
"municipios_municipio"."id", "municipios_municipio"."uf",
"municipios_municipio"."nome",
"municipios_municipio"."nome_ascii",
"municipios_municipio"."meso_regiao_id",
"municipios_municipio"."capital",
"municipios_municipio"."latitude",
"municipios_municipio"."longitude",
"municipios_municipio"."geohash" FROM "municipios_municipio"
ORDER BY "municipios_municipio"."nome_ascii" ASC LIMIT 5'}]
List comprehension
List comprehensions ● Compreensão de lista ou abrangência
● Exemplo: usar todos os elementos:
• Expressões que consomem– L2
iteráveis
= [n*10 for nein L]

produzem listas
qualquer iterável
resultado: uma lista

>>> s = 'abracadabra'
>>> l = [ord(c) for c in s]
>>> [ord(c) for c in s]
[97, 98, 114, 97, 99, 97, 100, 97, 98, 114, 97]

≈ notação matemática de conjuntos


@ramalhoorg
Set & dict comprehensions
• Expressões que consomem iteráveis e
produzem sets ou dicts

>>> s = 'abracadabra'
>>> {c for c in s}
set(['a', 'r', 'b', 'c', 'd'])
>>> {c:ord(c) for c in s}
{'a': 97, 'r': 114, 'b': 98, 'c': 99, 'd': 100}

@ramalhoorg
Tipos iteráveis embutidos
• basestring • frozenset
• str • list
• unicode • set
• dict • tuple
• file • xrange
@ramalhoorg
Funções embutidas que
consomem iteráveis
• all • max
• any • min
• filter • reduce
• iter • sorted
• len • sum
• map • zip
@ramalhoorg
Iteração em C (exemplo 2)
#include <stdio.h>

int main(int argc, char *argv[]) {


int i;
for(i = 0; i < argc; i++)
printf("%d : %s\n", i, argv[i]);
return 0;
}
$ ./args2 alfa bravo charlie
0 : ./args2
1 : alfa
2 : bravo
3 : charlie @ramalhoorg
Iteração em Python (ex. 2)
não
import sys
Pythonico!
for i in range(len(sys.argv)):
print i, ':', sys.argv[i]

$ python args2.py alfa bravo charlie


0 : args2.py
1 : alfa
2 : bravo
3 : charlie @ramalhoorg
Iteração em Python (ex. 2)
import sys Pythonico!
for i, arg in enumerate(sys.argv):
print i, ':', arg

$ python args2.py alfa bravo charlie


0 : args2.py
1 : alfa
2 : bravo
3 : charlie @ramalhoorg
Iteração em Python (ex. 2)
import sys isso constroi
um gerador
for i, arg in enumerate(sys.argv):
print i, ':', arg
o gerador produz uma
o gerador é um iterável preguiçoso!
tupla (indice, item)
sob demanda $ python args2.py alfa bravo charlie
a cada iteração 0 : args2.py
1 : alfa
2 : bravo
3 : charlie @ramalhoorg
Construtores embutidos
que consomem e
produzem iteráveis
• dict • reversed
• enumerate • set
• frozenset • tuple
• list
@ramalhoorg
Módulo itertools
• geradores (potencialmente) infinitos
• count(), cycle(), repeat()
• geradores que combinam vários iteráveis
• chain(), tee(), izip(), imap(), product(), compress()...
• geradores que selecionam ou agrupam itens:
• compress(), dropwhile(), groupby(), ifilter(), islice()...
• Iteradores que produzem combinações
• product(), permutations(), combinations()... @ramalhoorg
Exercício: construir e
controlar Tkinter.Label
import Tkinter
rel = Tkinter.Label()
rel['text'] = '10:42:29'
rel.grid()
rel['font'] = 'Helvetica 120 bold'

from time import strftime


rel['text'] = strftime('%H:%M:%S')

def tic():
    rel['text'] = strftime('%H:%M:%S')
     Para instalar
def tac():
tic()
Tkinter no
    rel.after(100, tac) Ubuntu Linux:

tac() $ sudo apt-get install python-tk


@ramalhoorg
Relógio com classe
import Tkinter
from time import strftime

class Relogio(Tkinter.Label):
    def __init__(self):
        Tkinter.Label.__init__(self)
        self.pack()
        self['text'] = strftime('%H:%M:%S')
        self['font'] = 'Helvetica 120 bold'
        self.tictac()
        
    def tictac(self):
        agora = strftime('%H:%M:%S')
        if agora != self['text']:
            self['text'] = agora
        self.after(100, self.tictac)

rel = Relogio()
rel.mainloop()

oopy/exemplos/relogio_oo.py @ramalhoorg
Uma pequena
parte da
hierarquia de
classes do
Tkinter
herança múltipla

mixin

he
ran
ça

ltipl
a
Um pouco mais da hierarquia de classes do Tkinter
Hierarquia de classes dos objetos gráficos doTkinter
Tudo é um objeto
• Não existem “tipos primitivos” como em Java
• desde Python 2.2, dezembro de 2001
>>> 5 + 3
8
>>> 5 .__add__(3)
8
>>> type(5)
<type 'int'>
@ramalhoorg
Funções são objetos
>>> def fatorial(n):
... '''devolve n!'''
... return 1 if n < 2 else n * fatorial(n-1)
...
>>> fatorial(5)
120
>>> fat = fatorial
>>> fat
<function fatorial at 0x1004b5f50>
>>> fat(42)
1405006117752879898543142606244511569936384000000000L
>>> fatorial.__doc__
'devolve n!'
>>> fatorial.__name__
'fatorial'
>>> fatorial.__code__
<code object fatorial at 0x1004b84e0, file "<stdin>", line 1>
>>> fatorial.__code__.co_varnames
('n',) @ramalhoorg
Funções são objetos
>>> fatorial.__code__.co_code
'|\x00\x00d\x01\x00j\x00\x00o\x05\x00\x01d\x02\x00S\x01|\x00\x00t\x00\x00|
\x00\x00d\x02\x00\x18\x83\x01\x00\x14S'
>>> from dis import dis
>>> dis(fatorial.__code__.co_code)
0 LOAD_FAST 0 (0)
3 LOAD_CONST 1 (1)
6 COMPARE_OP 0 (<)
9 JUMP_IF_FALSE
12 POP_TOP
5 (to 17)
Bytecode da
13 LOAD_CONST
16 RETURN_VALUE
2 (2)
função
>> 17 POP_TOP
18 LOAD_FAST 0 (0)
fatorial
21 LOAD_GLOBAL 0 (0)
24 LOAD_FAST 0 (0)
27 LOAD_CONST 2 (2)
30 BINARY_SUBTRACT
31 CALL_FUNCTION 1
34 BINARY_MULTIPLY
35 RETURN_VALUE
>>> @ramalhoorg
Tipos

@ramalhoorg
Alguns tipos básicos
>>> i = 7 Python 2.7 >>> i = 7 Python 3.2
>>> type(i) >>> type(i)
<type 'int'> <class 'int'>
>>> j = 2**100 >>> j = 2**100
>>> type(j)
int e long >>> type(j)
<type 'long'> unificados no <class 'int'>
>>> f = 7. Python 3 >>> f = 7.
>>> type(f) >>> type(f)
<type 'float'> <class 'float'>
>>> s = 'abc' >>> s = 'abc'
>>> type(s) str >>> type(s)
<type 'str'> x <class 'str'> SyntaxError
>>> u = u'abc' unicode >>> u = u'abc'
ou
>>> type(u) x
<type 'unicode'> <class ‘s tr’>
bytes
>>> b = b'ABC' >>> b = b'ABC' (Python 3.3)
>>> type(b) >>> type(b)
<type 'str'> <class 'bytes'>
>>> b[0] >>> b[0]
'A' 65
@ramalhoorg
Tipos embutidos (built-in)
• Implementados em C, por eficiência
• Métodos inalteráveis (como “final”, em Java)
• Texto: str, unicode (Python 2 e Python 3)
• Números: int, long (Python 2), float, complex, bool
• Coleções: list, tuple, dict, set, frozenset, bytes
(Python 3)

@ramalhoorg
Tipagem forte
• O tipo de um objeto nunca muda, e não existem
“tipos variantes”
• Raramente Python faz conversão automática
>>> a = 10
>>> b = '9'
>>> a + b
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'
>>> a + int(b)
19
>>> str(a) + b
'109'
>>> 77 * None
Traceback (most recent call last):
File "<stdin>", line 1, in <module> @ramalhoorg
TypeError: unsupported operand type(s) for *: 'int' and 'NoneType'
Tipagem dinâmica:
variáveis não têm tipo
>>> def dobro(x):
... return x * 2
...
>>> dobro(7)
14
>>> dobro(7.1)
14.2
>>> dobro('bom')
'bombom'
>>> dobro([10, 20, 30])
[10, 20, 30, 10, 20, 30]
>>> dobro(None)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in dobro
TypeError: unsupported operand type(s) for *: 'NoneType' and 'int'

@ramalhoorg
Duck typing
• “Se voa como um pato, nada como um pato e
grasna como um pato, é um pato.”
• Tipagem dinâmica permite duck typing (tipagem
pato): estilo de programação que evita verificar os
tipos dos objetos, mas apenas seus métodos
• No exemplo anterior, a função dobro funciona
com qualquer objeto x que consiga fazer x * 2
• x implementa o método __mult__(n), para n
inteiro
@ramalhoorg
Exemplo: tômbola
• Sortear um a um
todos os itens de
uma coleção finita,
sem repetir
• A mesma lógica é
usada em sistemas
para gerenciar
banners online

@ramalhoorg
Interface da tômbola

• Carregar itens
• Misturar itens
• Sortear um item
• Indicar se há mais
itens

@ramalhoorg
Projeto da tômbola

• UML:
diagrama de classe

@ramalhoorg
TDD: Test Driven Design
• Metodologia de desenvolvimento iterativa na qual,
para cada funcionalidade nova, um teste é criado
antes do código a ser implementado
• Esta inversão ajuda o programador a desenvolver
com disciplina apenas uma funcionalidade de cada
vez, mantendo o foco no teste que precisa passar
• Cada iteração de teste/implementação deve ser
pequena e simples: “baby steps” (passinhos de
bebê)
@ramalhoorg
Doctests
• Um dos módulos para fazer testes automatizados
na biblioteca padrão de Python
• o outro módulo é o unittest, da família xUnit
• Doctests foram criados para testar exemplos
embutidos na documentação
• Exemplo de uso:
$ python -m doctest cao.rst

oopy/exemplos/cao.rst @ramalhoorg
Sobrecarga de
operadores
@ramalhoorg
Sobrecarga de operadores
• Python permite que as classes definidas pelo
usuário (você!) implementem métodos para os
operadores definidos na linguagem
• Não é possível redefinir a função dos operadores
nos tipos embutidos
• isso evita surpresas desagradáveis
• Nem é possível inventar novos operadores
• não podemos definir ~, <=>, /|\ etc. @ramalhoorg
Objetos invocáveis
• Você pode definir suas próprias funções...
• E também novas classes de objetos que se
comportam como funções: objetos invocáveis
• basta definir um método __call__ para
sobrecarregar o operador de invocação: ()
• o(x)
• Exemplo: tômbola invocável
@ramalhoorg
Tômbola invocável
• Já que o principal uso de uma instância de tômbola
é sortear, podemos criar um atalho:
em vez de t.sortear() >>> t = TombolaInvocavel()
apenas t() >>> t.carregar([1, 2, 3])
>>> t()
3
>>> t()
from tombola import Tombola 2
class TombolaInvocavel(Tombola):
'''Sorteia itens sem repetir;
a instância é invocável como uma função'''

def __call__(self):
return self.sortear() @ramalhoorg
Alguns operadores
existentes
• Aritméticos: + - * / ** //
• Bitwise: & ^ | << >>
• Acesso a atributos: a.b
• Invocação: f(x)
• Operações em coleções: c[a], len(c), a in c, iter(c)
• Lista completa em Python Reference: Data Model
http://docs.python.org/reference/datamodel.html
@ramalhoorg
Exemplo: vetor (2d)
y
• Campos: x, y
• Métodos:
• distancia
Vetor(4, 5)

Vetor(2, 4)

• abs (distância até 0,0)


• + (__add__)
Vetor(2, 1)
x • * (__mul__) escalar
oopy/exemplos/vetor.py @ramalhoorg
Vetor
from math import sqrt

class Vetor(object):

def __init__(self, x=0, y=0):


self.x = x
self.y = y

def __repr__(self):
return 'Vetor(%s, %s)' % (self.x, self.y)

def distancia(self, v2):


dx = self.x - v2.x >>> from vetor import Vetor
dy = self.y - v2.y >>> v = Vetor(3, 4)
return sqrt(dx*dx + dy*dy) >>> abs(v)
5.0
def __abs__(self): >>> v1 = Vetor(2, 4)
return self.distancia(Vetor(0,0))
>>> v2 = Vetor(2, 1)
>>> v1 + v2
def __add__(self, v2):
dx = self.x + v2.x Vetor(4, 5)
dy = self.y + v2.y >>> v1 * 3
return Vetor(dx, dy) Vetor(6, 12)

def __mul__(self, n):


return Vetor(self.x*n, self.y*n) @ramalhoorg
Baralho polimórfico

@ramalhoorg
Carta de
baralho
class Carta(object):

naipes = 'paus ouros copas espadas'.split()


valores = '2 3 4 5 6 7 8 9 10 J Q K A'.split()

def __init__(self, valor, naipe):


self.valor = valor
self.naipe = naipe

def __repr__(self):
return 'Carta(%r, %r)' % (self.valor, self.naipe)

def __str__(self):
return self.valor + ' de ' + self.naipe

@classmethod
def todas(cls):
return [cls(v, n) for n in cls.naipes
for v in cls.valores] @ramalhoorg
Carta de
>>> zape = Carta('4',
'paus')
>>> zape.valor
'4'

baralho >>> zape


Carta('4', 'paus')
>>> monte = Carta.todas()
>>> len(monte)
class Carta(object): 52
>>> monte[0]
naipes = 'paus ouros copas espadas'.split() Carta('2', 'espadas')
valores = '2 3 4 5 6 7 8 9 10 J Q K A'.split() >>> monte[-3:]
[Carta('Q', 'copas'),
def __init__(self, valor, naipe): Carta('K', 'copas'),
self.valor = valor Carta('A', 'copas')]
self.naipe = naipe

def __repr__(self):
return 'Carta(%r, %r)' % (self.valor, self.naipe)

def __str__(self):
return self.valor + ' de ' + self.naipe

@classmethod
def todas(cls):
return [cls(v, n) for n in cls.naipes
for v in cls.valores] @ramalhoorg
Baralho
polimórfico (demo)
from carta_ord import Carta

class Baralho(object):

def __init__(self):
self.cartas = Carta.todas()

def __len__(self):
return len(self.cartas)

def __getitem__(self, pos):


return self.cartas[pos]

def __setitem__(self, pos, valor):


self.cartas[pos] = valor
@ramalhoorg
Baralho
polimórfico (final)
from carta_ord import Carta

class Baralho(object):

def __init__(self):
self.cartas = Carta.todas()

def __len__(self):
return len(self.cartas)

def __getitem__(self, pos):


return self.cartas[pos]

def __setitem__(self, pos, valor):


self.cartas[pos] = valor
@ramalhoorg
http://xkcd.com/353/