116
Fácil para começar, difícil de superar Luciano Ramalho [email protected] @ramalhoorg Palestra apresentada na UNIFESP São José dos Campos em 10/dez/2012

Introdução a linguagem Python

Embed Size (px)

DESCRIPTION

Palestra sobre a linguagem Python e seus contextos de uso

Citation preview

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

Luciano [email protected]

@ramalhoorg

Palestra apresentada na UNIFESPSão José dos Campos em 10/dez/2012

@ramalhoorg

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

Google em 1998

Google App Engine

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

“Vocês são o centro

do Vale do Silício hoje”

Paul Graham, Pycon US 2012

Linguagem“expressiva”

O que issosignifica

na prática?

Linguagem COBOL

Java

Python

Java

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

Peter Norvig, Google, Inc.

lis.py: interpretador Lisp (Scheme) em

113 linhas de Python,por Peter Norvig

>>> from lis import repl>>> repl()lis.py> (* 7 3)21lis.py> (define resposta (* 6 7))lis.py> resposta42lis.py> (define ! (lambda (n) (if (= n 0) 1 (* n (! (- n 1))))))lis.py> (! 4)24lis.py> (! 5)120lis.py> (! 197)100078405584080821221303894971344736599047761241456431563720437191558734323562679929991407036696693556694737848195477238497746661367777918006944650646265409257583733981874437495228286501182991424477395086576066353467353335798727837835328694280439305522603073118823862831864630209655642361092292378406702568679608855350476800000000000000000000000000000000000000000000000lis.py> !<function <lambda> at 0x1004cbd70>lis.py>

Demo: lis.py

@ramalhoorg

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

Python: evolução• Versões do CPython em dez/2012

• 3.0, 2.5 e anteriores: fossilizadas

• 2.6 e 3.1: manutenção por 5 anos

• 2.7 e 3.2: versões atuais

• 2.7: versão final da série 2.x

• 3.3: lançada em set/2012

2.52006-09…2011-05

2.6 2008-10 3.0

2008-12…2009-07

3.1 2009-06

3.2 2011-02

2.7 2010-07

3.3 2012-09

3.4 2014-02

@ramalhoorg

Pythonista: app para iPad

@ramalhoorgPythonista

@ramalhoorgPythonista

@ramalhoorg

@ramalhoorgPythonista

@ramalhoorgPythonista

@ramalhoorgPythonista

@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)

pythontutor.com

pythontutor.com

@ramalhoorg

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

• bpython

• IDLE

• online

• http://shell.appspot.com/

• 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 charliealfabravocharlie

@ramalhoorg

Iteração em Java ≥1.5

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

$ java Argumentos2 alfa bravo charliealfabravocharlie

ano:2004

• Enhanced for (for melhorado)

@ramalhoorg

Iteração em Java ≥1.5

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

ano:2004

• Enhanced for (for melhorado)

import sys

for arg in sys.argv: print arg

ano:1991

@ramalhoorg

Exemplos de iteração

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

• Exemplos

• string

• arquivo

• Django QuerySet

>>> 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ásMG Abadia dos DouradosGO AbadiâniaMG Abaeté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'}]

demonstração: queryset é um iterável lazy

@ramalhoorg

List comprehensions• Expressões que consomem iteráveis e

produzem listas

>>> 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]

List comprehension

● Compreensão de lista ou abrangência de lista

● Exemplo: usar todos os elementos:

– L2 = [n*10 for n in L]

qualquer iterável

resultado: uma lista

≈ 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

• str

• unicode

• dict

• file

• frozenset

• list

• set

• tuple

• xrange

@ramalhoorg

Funções embutidas que consomem iteráveis• all

• any

• filter

• iter

• len

• map

• max

• min

• reduce

• sorted

• sum

• 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 charlie0 : ./args21 : alfa2 : bravo3 : charlie

@ramalhoorg

Iteração em Python (ex. 2)

import sys

for i in range(len(sys.argv)): print i, ':', sys.argv[i]

$ python args2.py alfa bravo charlie0 : args2.py1 : alfa2 : bravo3 : charlie

não Pythonico!

@ramalhoorg

Iteração em Python (ex. 2)

import sys

for i, arg in enumerate(sys.argv): print i, ':', arg

$ python args2.py alfa bravo charlie0 : args2.py1 : alfa2 : bravo3 : charlie

Pythonico!

@ramalhoorg

import sys

for i, arg in enumerate(sys.argv): print i, ':', arg

Iteração em Python (ex. 2)

isso constroium gerador

o gerador produz uma tupla (indice, item)

sob demandaa cada iteração

o gerador é um iterável preguiçoso!$ python args2.py alfa bravo charlie0 : args2.py1 : alfa2 : bravo3 : charlie

@ramalhoorg

Construtores embutidos que consomem e produzem iteráveis

• dict

• enumerate

• frozenset

• list

• reversed

• set

• tuple

@ramalhoorg

• 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()...

Módulo itertools

@ramalhoorg

import Tkinterrel = Tkinter.Label()rel['text'] = '10:42:29'rel.grid()rel['font'] = 'Helvetica 120 bold'

from time import strftimerel['text'] = strftime('%H:%M:%S')

def tic():    rel['text'] = strftime('%H:%M:%S')    def tac(): tic()    rel.after(100, tac)

tac()

Exercício: construir e controlar Tkinter.Label

$ sudo apt-get install python-tk

Para instalar Tkinter no

Ubuntu Linux:

@ramalhoorg

Relógio com classeimport Tkinterfrom 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

Uma pequena parte da hierarquia declasses do Tkinter

herança múltipla

herança múltipla

mixin

Um pouco mais da hierarquia de classes do Tkinter

Hierarquia de classes dos objetos gráficos doTkinter

@ramalhoorg

Tudo é um objeto

• Não existem “tipos primitivos” como em Java

• desde Python 2.2, dezembro de 2001

>>> 5 + 38>>> 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 5 (to 17) 12 POP_TOP 13 LOAD_CONST 2 (2) 16 RETURN_VALUE >> 17 POP_TOP 18 LOAD_FAST 0 (0) 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 >>>

Bytecode da função

fatorial

@ramalhoorg

Tipos

@ramalhoorg

Alguns tipos básicos>>> i = 7>>> type(i)<type 'int'>>>> j = 2**100>>> type(j)<type 'long'>>>> f = 7.>>> type(f)<type 'float'>>>> s = 'abc'>>> type(s)<type 'str'>>>> u = u'abc'>>> type(u)<type 'unicode'>>>> b = b'ABC'>>> type(b)<type 'str'>>>> b[0]'A'

>>> i = 7>>> type(i)<class 'int'>>>> j = 2**100>>> type(j)<class 'int'>>>> f = 7.>>> type(f)<class 'float'>>>> s = 'abc'>>> type(s)<class 'str'>>>> u = u'abc'

>>> b = b'ABC'>>> type(b)<class 'bytes'>>>> b[0]65

Python 2.7 Python 3.2

SyntaxErrorou

<class ‘str’>(Python 3.3)

int e long unificados no

Python 3

strx

unicodex

bytes

@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 + bTraceback (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 * NoneTraceback (most recent call last): File "<stdin>", line 1, in <module>TypeError: unsupported operand type(s) for *: 'int' and 'NoneType'

@ramalhoorg

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 dobroTypeError: 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()apenas t()

from tombola import Tombola

class TombolaInvocavel(Tombola): '''Sorteia itens sem repetir; a instância é invocável como uma função'''

def __call__(self): return self.sortear()

>>> t = TombolaInvocavel()>>> t.carregar([1, 2, 3])>>> t()3

>>> t()2

@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)

• Campos: x, y

• Métodos:

• distancia

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

• + (__add__)

• * (__mul__) escalar

oopy/exemplos/vetor.py

Vetor(2, 1)

Vetor(2, 4)

Vetor(4, 5)

x

y

@ramalhoorg

Vetorfrom 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 dy = self.y - v2.y return sqrt(dx*dx + dy*dy)

def __abs__(self): return self.distancia(Vetor(0,0))

def __add__(self, v2): dx = self.x + v2.x dy = self.y + v2.y return Vetor(dx, dy)

def __mul__(self, n): return Vetor(self.x*n, self.y*n)

>>> from vetor import Vetor>>> v = Vetor(3, 4)

>>> abs(v)5.0

>>> v1 = Vetor(2, 4)>>> v2 = Vetor(2, 1)

>>> v1 + v2Vetor(4, 5)>>> v1 * 3

Vetor(6, 12)

@ramalhoorg

Baralho polimórfico

@ramalhoorg

Carta debaralho

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 debaralho

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]

>>> zape = Carta('4', 'paus')

>>> zape.valor'4'

>>> zapeCarta('4', 'paus')

>>> monte = Carta.todas()>>> len(monte)

52>>> monte[0]

Carta('2', 'espadas')>>> monte[-3:]

[Carta('Q', 'copas'), Carta('K', 'copas'), Carta('A', 'copas')]

@ramalhoorg

Baralhopolimó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

Baralhopolimó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

http://xkcd.com/353/