Вы находитесь на странице: 1из 218

Phyton Labaki-ModuloA.

pdf
Python Labaki-ModuloB.pdf
Python Labaki-ModuloC.pdf
C Cr ru up po o P Py yt th ho on n a ap pr re es se en nt ta a: :
I In nt tr ro od du u o o a a P Py yt th ho on n - - h h d du uI Io o A A




























J Jo os su u L La ab ba ak kI I
I Ia ab ba ak kI I@ @f fe eI Is s. .u un ne es sp p. .b br r






UNESP - ILHA SDLTEIPA
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
2
Apresentao

Este material foi desenvolvido para apoiar os cursos da srie "Introduo
a Python" ministrados pelo Grupo Python para nossos mais diversos tipos de
audincia. O guia inteiro composto por trs volumes que correspondem aos mdulos
dados nos nossos cursos: Mdulo A - Bem-vindo a Python!, Mdulo B - Python
Orientado a Objetos e Mdulo C - Tkinter. Todos eles podem ser encontrados na
internet, nas pginas do Grupo Python (http://grupopython.cjb.net), na pgina do
autor (http://labaki.tk) e na pgina da comunidade Python no Brasil
(http://www.python-brasil.com.br).
Desenvolvemos este guia pensando tambm nos autodidatas que no
participaram dos nossos cursos e baixaram este material da internet. Se voc est
nesta situao, pode tirar dvidas por e-mail.
Lembramos que o nosso objetivo no ensinar programao, e sim guiar
voc nos passos bsicos em Python. Se sua inteno aprender a programar, prefira o
excelente material do prof. Luciano Ramalho em (http://www.magnet.com.br).
Recomendamos que voc acompanhe e implemente os exemplos, tente
entender os erros que podem ocorrer e tente resolver as questes que eventualmente
aparecem ao longo deste material. Ao final, h alguns exemplos e exerccios de
fixao.
Mande suas dvidas, sugestes, crticas ou comentrios por e-mail! Sua
opinio sobre o guia muito importante para ns.


Josu Labaki
Grupo Python
Departamento de Engenharia Mecnica
UNESP - Campus de Ilha Solteira
labaki@feis.unesp.br
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
3
ndice

Parte I - Bem-vindo a Python! 5
1.Por que estudar Python? 5
2.Usando o interpretador de Python 6
3.Usando Python como uma calculadora 7
4.Variveis - nada a declarar 8
Parte II - Tipos de Objetos 10
1.Strings 10
2.Listas 15
3.Tuplas 19
4.Dicionrios 21
Parte III - Formatando Objetos 23
1.Formatando strings 23
2.Recursos de manipulao de listas 26
Parte IV - Testes, Loops, Varreduras e Erros 29
1.Enquanto... 29
2.Entrada de dados 31
3.If... Elif... Else... 33
4.For 35
5.Break 40
6.Tratamento de erros 42
Parte V - Nosso primeiro programa completo 46
Parte VI - Funes e Mdulos 51
1.Definindo funes 51
2.Funes sobre seqncias 57
3.Return versus side effects 62
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
4
4.Mdulos 66
5.Um pouco de teoria: Escopo 73
Parte VII - Alguns truques... 79
1.Manipulao de arquivos 79
2.Mdulo OS - mexendo no Sistema Operacional 83
3.Time e Random 86
4.Python e AutoCAD: bons amigos 89
5.Msica, maestro! 92
6.Calendar 93
Parte VIII - Exemplos 95
1.numanalise.py - Trabalhando com funes 95
2.catch_mail.py - Trabalhando com strings 98
3.matrizes.py - Cadeias de for e listas 100
4.morse_code.py - Dicionrios e sons 102
5.newton-raphson.py - Escrevendo em arquivos 104
6.memoria.py - Um joguinho simples de memria 109
Parte IX - Exerccios 111
Vem a... 113






I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
5
Parte I - Bem-vindo a Python!

1. Por que estudar Python?

Python uma linguagem de programao de altssimo nvel (VHLL - Very High
Level Language), criada pelo holands Guido Van Rossum sob o ideal de "Programao
de Computadores para todos. Este ideal fez com que o desenvolvimento de Python
tivesse sempre em mente a liberdade (gratuita, cdigo aberto), disponibilidade (Python
roda em Windows, Linux, Mac, Palm, em celulares, e outra infinidade de sistemas) e
principalmente a clareza de sintaxe, que hoje responsvel pela alta produtividade s
conseguida com Python.
Python uma linguagem Orientada a Objetos, um paradigma que facilita
entre outras coisas o controle sobre a estabilidade dos projetos quando estes comeam
a tomar grandes propores. Mas como a Orientao a Objetos ainda vista como um
paradigma para "experts, Python permite que o usurio programe na forma
procedural, se desejar.
Python tambm uma linguagem altamente modular. Isso significa que
provavelmente algum j fez todo ou parte do programa que voc precisa
desenvolver, economizando um tempo precioso do seu trabalho.
Estas e outras vantagens fizeram que grandes empresas e universidades
comeassem a usar Python com sucesso, como a Philips, Industrial Light and Magic
(empresa de George Lucas), que usou Python para controlar efeitos especiais de Star
Wars, a NASA, a Aliana Espacial Universal (USA), a Nokia que usa Python em seus
celulares, a Disney, os sites Google e Yahoo, entre outros. Veja estes e mais exemplos
no site Pythonology (http://www.pythonology.org).
Enfim, uma boa resposta para a pergunta-ttulo deste captulo pode ser a
mostrada nas FAQs do portal Python brasileiro (http://www.pythonbrasil.com.br):

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
6
"Porque Python uma linguagem simples e elegante. Porque Python
fcil de aprender. Porque Python pode ser usado para resolver uma grande
variedade de problemas. Porque Python incentiva voc a escrever seus
programas da maneira correta, sem que isso se torne um empecilho
produtividade.
Python tem uma curva de aprendizado bastante interessante,
permitindo que novos programadores, mesmo os que nunca tenham
programado antes, sejam imediatamente produtivos escrevendo scripts
procedurais. O programador pode rodar o interpretador como um shell, vendo
imediatamente o resultado da sada de cada comando e explorando os
recursos da linguagem interativamente.
Para construir aplicaes mais complexas, Python possibilita a fcil
migrao para a programao orientada a objetos. Um programa pode evoluir
naturalmente para esse paradigma medida que se torna mais complexo. A
facilidade inicial do Python no barateia a linguagem, como comum em
linguagens que tm por objetivo expresso serem fceis de aprender. Python
simples de aprender porque uma linguagem bem planejada.

2. Usando o interpretador de Python.

H vrias formas de interpretar seu cdigo em Python. A mais utilizada a
nativa da linguagem, o IDLE. Usurios Windows podem geralmente acessa-lo em
Iniciar > Programas > Python 2.3 > IDLE. Pelo IDLE voc pode executar algumas
linhas de cdigo para testar seu programa, ou mesmo rodar um programa completo
para saber rapidamente o que est acontecendo com os objetos que voc definiu, alm
de fazer de modo prtico a introspeco sobre estes objetos e outros recursos de
Python.
Usurios Linux podem usar um interpretador interativo como o IDLE, porm
sem as cores, simplesmente digitando `python na linha de comandos. Muitas
distribuies Linux j trazem Python nativamente.
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
7
3. Usando Python como uma calculadora.

Observe como fcil usar o IDLE como uma calculadora. Alm de poder ver
todos os clculos anteriores, voc tambm pode usar os resultados deles em clculos
futuros, simplesmente copiando e colando os resultados. Os operadores algbricos
usados no interpretador so os mesmos que voc j usava em outros programas do
seu sistema operacional: +, -, * e /. Os operadores booleanos so os seguintes:

>>> a=1
>>> b=2
>>> a == b # == testa se a igual a b
False
>>> a != b # != testa se a diferente de b
True
>>> a <> b # <> tambm testa se a diferente de b
True
>>> a > b # > testa se a maior que b
False
>>> a < b # < testa se a menor que b
True
>>> 2*a >= b # testa se o dobro de a maior ou igual a b
True

O smbolo # usado em Python para adicionar comentrios aos cdigos. Tudo
o que estiver escrito aps esse sinal, enxergado como comentrio e no executado
com o cdigo.
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
8
O sinal usado por Python para potncias algbricas **:

>>> 2**3 # o mesmo que 2
3
(dois ao cubo).
8
>>> 2**(3+6) # Dois elevado a 9
512

H um ltimo operador que retorna o resto da diviso entre dois nmeros:

>>> 7 % 2 # O resto da diviso entre 7 e 2
1

Quanto deve ser o resultado de 2**(3+6) % 7?

4. Variveis - nada a declarar!

Python uma linguagem dinamicamente tipada. Isso quer dizer que no
necessrio tipar as variveis para usa-las. Por um processo chamado "binding, atribui-
se um objeto a um nome e este nome incorpora o tipo do objeto. Assim, para
atribuirmos o valor 2, que um inteiro, ao nome "valor1, s precisamos fazer
valor1=2, e "valor1 ser automaticamente tipado por Python como inteiro.
Para saber qual o tipo de determinado objeto, usamos a funo type(x), que
retorna o tipo do objeto x:

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
9
>>> valor1=2
>>> valor1
2
>>> type(valor1)
<type 'int'>

Perceba que no precisamos "declarar a varivel "valor1 antes de utiliza-la.
Se agora voc quiser atribuir o valor "Boa tarde! ao nome "valor1, pode fazer isso
naturalmente. Desta vez, o objeto "valor1 ir incorporar o tipo de "Boa tarde! (que
uma string - o que talvez voc conhea de FORTRAN como "character):

>>> valor1='Boa tarde!'
>>> valor1
'Boa tarde!'
>>> type(valor1)
<type 'str'>

Os principais tipos de objetos em Python so inteiros, floats (nmeros reais,
que o computador representa da melhor maneira possvel por meio de variaes na
posio do separador decimal), strings (texto), listas, tuplas e dicionrios. Pode-se
transformar o tipo original de um objeto para inteiro, float ou string por meio das
funes int, float e str, respectivamente, como veremos melhor adiante.




I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
10
Parte II - Tipos de Objetos

1. Strings

Strings so os objetos que Python oferece para trabalhos com texto. As
strings em Python so seqncias, e por isso podemos trabalhar com elas com muito
mais eficincia do que em outras linguagens.

>>> palavra='termodinmica'
>>> palavra
'termodin\xe2mica'

Este estranho termodin\xe2mica a maneira como Python salvou o valor
do objeto "palavra na memria, j que o computador no conhece caracteres
estranhos como acentos. Mas no se preocupe, isso s faz sentido para a mquina.
Para o usurio, o valor salvo continua sendo "termodinmica. Para ver isso,

>>> print palavra
'termodinmica'

Em Python, uma string uma seqncia de letras, endereada de tal forma
que voc possa requisitar um valor qualquer desta seqncia e fazer o que quiser com
ele. Como qualquer seqncia em Python, os endereamentos comeam a ser
contados do zero. A sintaxe para requisitar o valor atribudo a um endereo X de uma
seqncia S S[X].
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
11
>>> palavra[2]
'r'
>>> 2*palavra[0]
'tt'

Voc tambm pode solicitar um intervalo de uma seqncia. Por exemplo,
para solicitar os valores da seqncia "palavra que esto entre os endereos 9 e 12,
fazemos

>>> palavra[9:12]
'mic'

Para entender melhor o que aconteceu aqui, lembre-se de que os endereos
em Python se referem aos intervalos entre os itens, e no ao item em si. Isto , o
endereamento usado no objeto `palavra o seguinte:



Assim fica fcil entender porque palavra[9:12] retorna os itens m, i e c!
Podemos omitir o endereo da direita, se ele for o ltimo da seqncia:

>>> palavra[9:]
'mica'
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
12
Da mesma forma, os valores entre o primeiro endereo (0) e o 9 so

>>> palavra[0:9]
'termodin\xe2'

Ou, como estamos falando do primeiro endereo,

>>> palavra[:9]
'termodin\xe2'

Perceba a diferena:

>>> print palavra[:9]
'termodin'

O que obteremos de print palavra[:]?

Se voc no deseja recolher todos os valores da seqncia contidos no
intervalo, pode determinar um incremento:

>>> palavra[1:8]
'ermodin'
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
13
>>> palavra[1:8:2]
'emdn'

Assim so retornados os valores de palavra entre os endereos 1 e 8, com
incremento 2 (ou seja, os elementos dos endereos 1, 3, 5 e 7). Veja um exemplo com
incremento 3:

>>> palavra[1:8:3]
'eon'

Ou seja, os elementos dos endereos 1, 4 e 7. Com incremento negativo,
possvel varrer uma seqncia de trs para frente, assim:

>>> palavra[7:0:-1]
'nidomre'

Na ltima sentena conseguimos capturar os valores do endereo 7 at 0,
exceto o prximo zero, vasculhando a seqncia "palavra de trs para frente.
Como estamos falando do primeiro endereo (zero), podemos omitir esta
informao:

>>> palavra[7::-1]
'nidomret'

Igualmente se a varredura comea do ltimo endereo:

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
14
>>> palavra[:4:-2]
'ai\xe2i'

(Voc j est acostumado a enxergar \xe2 como ", no ?).
Ora, se podemos omitir o ltimo e o primeiro endereos, ento fica fcil
inverter uma seqncia qualquer:

>>> palavra[::-1]
'acim\xe2nidomret'

Talvez voc j tenha pensado como isso deve ser interessante para verificar
se uma palavra um palndromo
1
...

>>> palindromo='socorram me subi no onibus em marrocos'
>>> palindromo[::-1]
'socorram me subino on ibus em marrocos'

A varredura de strings ao contrrio no to usada, mas este conceito
importante e ser bem mais til quando aplicado a outros tipos de seqncias que
veremos adiante.
Quando executado sobre strings, o operador "+ significa "concatenao, isto
, adio ao final da string anterior.


1
Palndromos so palavras ou sentenas que so iguais tanto se lidas de trs para frente quanto no sentido
normal.
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
15
>>> palavra=palavra+' aplicada'
>>> print palavra
'termodinmica aplicada'
>>> palavra[14:]
'aplicada'

Outra funo que podemos executar sobre qualquer seqncia em Python
len(x), que retorna o tamanho da seqncia x.

>>> len(palavra)
22

2. Listas

Um dos tipos de objeto mais teis em Python a lista. A lista tambm uma
seqncia, e sua sintaxe :

>>> lista=[1,2,3]
>>> lista
[1, 2, 3]

Neste exemplo, temos uma lista de inteiros, mas uma lista pode conter floats,
strings, outras listas ou outros objetos quaisquer.
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
16
Como qualquer seqncia, a lista segue o mesmo sistema de endereamento
que j vimos em strings:

>>> lista[0]
1
>>> lista[0]+lista[2]
4

O operador "+ tambm representa concatenao em listas. A seguir estamos
concatenando a lista [1,2,3] com a lista [4] (que uma lista de nico elemento).
Fazer lista+4 d erro, porque estamos tentando concatenar o inteiro 4 lista [1,2,3].

>>> lista=lista+[4]
>>> lista
[1, 2, 3, 4]
>>> lista+4

Traceback (most recent call last):
File "<pyshell#1>", line 1, in -toplevel-
lista+4
TypeError: can only concatenate list (not "int") to list

>>> lista=lista+[0,0,0]
>>> lista
[1, 2, 3, 4, 0, 0, 0]

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
17
Tambm podemos solicitar um valor atribudo aos endereos de uma
seqncia de trs para frente. O ltimo endereo tambm chamado de [-1], o
penltimo de [-2], e assim por diante:

>>> lista[-1]
0
>>> lista[2:-2]
[3, 4, 0]

Aqui, questionamos sobre o tamanho da seqncia "lista:

>>> len(lista)
7

Uma caracterstica importante das listas que elas so seqncias mutveis,
ao contrario das strings. Isso quer dizer que podemos alterar o valor atribudo a um
determinado endereo de uma lista, mas no podemos fazer isso com strings.

>>> lista[0] = 'zero'
>>> lista
['zero', 2, 3, 4, 0, 0, 0]
>>> lista[1] = lista[1]+lista[2]
>>> lista
['zero', 5, 3, 4, 0, 0, 0]
>>> lista[2] = lista[0]
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
18
>>> lista
['zero', 5, 'zero', 4, 0, 0, 0]

Mas com strings...

>>> a='Boa tarde!'
>>> a[0]='N'

Traceback (most recent call last):
File "<pyshell#3>", line 1, in -toplevel-
a[0]='N'
TypeError: object doesn't support item assignment

No tenha medo destas mensagens de erro! Elas nos ajudam a entender o
que est havendo de errado. A linha fundamental a ltima, que diz que tipo de erro
ocorreu. Neste caso, a mensagem object doesn't support item assignment (o
objeto no suporta atribuio aos itens), confirma o que dissemos sobre as strings
serem imutveis.
Observe uma aplicao interessante para listas de listas:

>>> linha1=[1,2,3]
>>> linha2=[0,-1,1]
>>> linha3=[3,3,3]
>>> matriz=[linha1,linha2,linha3]
>>> matriz
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
19
[[1, 2, 3], [0, -1, 1], [3, 3, 3]]
>>>matriz[1]
[0, -1, 1]

Por que matriz[1] retorna esta lista em vez do inteiro 2?

Chamando um elemento dessa pseudo-matriz:

>>> matriz[1][2]
1

3. Tuplas

Tuplas so objetos como as listas, com a diferena de que tuplas so
imutveis como strings. Uma vez criadas, no podem ser modificadas. A sintaxe de
tuplas :

>>> tupl=(1,2,3)
>>> tupl
(1, 2, 3)
>>> tupl[0]=0

Traceback (most recent call last):
File "<pyshell#10>", line 1, in -toplevel-
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
20
tupl[0]=0
TypeError: object doesn't support item assignment

As tuplas podem tambm conter quaisquer objetos; inteiros, floats, listas,
outras tuplas, etc.
Com as tuplas podemos fazer algo bem comum nos programas em Python,
chamado "packing-unpacking:

>>> a,b = 0,'Deu certo?'
>>> a
0
>>> b
'Deu certo?'

como se estivssemos dizendo "a e b so iguais a 0 e 'Deu certo?,
respectivamente.
Mais fantstico ainda, podemos trocar o valor de dois objetos facilmente:

>>> a,b=b,a
>>> a
'Deu certo?'
>>> b
0

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
21
4. Dicionrios

Dicionrios tambm so contineres, mas no so seqncias porque no so
indexados seqencialmente da forma que strings, listas e tuplas so. Seu sistema de
endereamento por chaves. Cada chave tem um valor atribudo. Se voc quer saber
um valor de um dicionrio, deve perguntar pelas chaves, no pelos endereos. A
sintaxe de dicionrios :

>>> aurelio={'denomiao':'ilha solteira','populao':23000,'renda':1500}
>>> aurelio
{'popula\xe7\xe3o': 23000, 'denomia\xe7\xe3o': 'ilha solteira',
'renda':1500}

Neste exemplo, temos o inteiro 23000 atribudo chave "populao. Para
adicionar novos valores a outras chaves, fazemos

>>> aurelio['vocao']='turismo'

atribuindo assim a string "turismo nova chave "vocao.

>>> aurelio
{'popula\xe7\xe3o': 23000, 'voca\xe7\xe3o': 'turismo',
'denomia\xe7\xe3o': 'ilha solteira', 'renda': 1500}

E para requisitar o valor atribudo a alguma chave,
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
22
>>> aurelio['renda']
1500

Dicionrios so mutveis. fcil alterar o valor contido em uma chave:

>>> aurelio['renda']=aurelio['renda']+200
>>> aurelio['renda']
1700

Podemos verificar quais chaves um dicionrio possui ou perguntar se ele
contm alguma chave em especial:

>>> aurelio.keys()
['popula\xe7\xe3o', 'voca\xe7\xe3o', 'denomia\xe7\xe3o', 'renda']
>>> aurelio.has_key('idade')
False
>>> aurelio['idade']=33
>>> aurelio.has_key('idade')
True

A sentena dicionario.items() retorna uma lista de tuplas contendo o par
(chave,valor atribudo):
>>> aurelio.items()
[('idade', 33), ('popula\xe7\xe3o', 23000), ('voca\xe7\xe3o', 'turismo'),
('denomia\xe7\xe3o', 'ilha solteira'), ('renda', 1700)]
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
23
Parte III - Formatando objetos

1. Formatao de strings

Podemos formatar alguma string usando a sintaxe



Vejamos alguns exemplos:

>>> constante=3.14
>>> print 'O valor de pi %f' %constante
O valor de pi 3.14

Observe a consistncia do cdigo com o esquema mostrado acima: O
marcador % colocado no lugar onde ser inserido o valor contido no nome
"constante. Como o valor de "constante um float (3.14), logo depois do marcador
vem a indicao do tipo da varivel, "f.
Novos exemplos com outros tipos de variveis:
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
24
>>> nome='abacaxi'
>>> caracteristica='amarelo'
>>> print '%s uma fruta' %nome
abacaxi uma fruta
>>> print '%s %s' %(nome,caracteristica)
abacaxi amarelo

assim que inserimos vrios valores dentro de uma string: usando uma tupla
contendo os valores, na ordem em que aparecero.

>>> print '%f %ss tambm so %ss' %(constante,nome,caracteristica)
3.14 abacaxis tambm so amarelos

Desta vez trs valores foram inseridos na string. Eles aparecem na string na
mesma ordem em que foram dispostos na tupla. Os tipos acompanham: primeiro "f,
que indica que "constante um float, e depois "s e "s, que indica que "nome e
"caracterstica so strings. Observe: no segundo e no terceiro marcadores temos %ss
com dois "s. O primeiro "s indica o tipo da varivel, string, e o terceiro faz parte da
string - neste caso est fazendo o plural de "abacaxi e "amarelo.

O que seria impresso se a string comeasse com '%fs .....?

Inserindo .x depois de um marcador de floats dizemos que o valor aparecer
com somente x casas decimais:

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
25
>>> valor = 3.1415926535897931
>>> print 'O valor %.2f' %valor
O valor 3.14
>>> print 'O valor %.3f' %valor
O valor 3.141
>>> print 'O valor %f' %valor
O valor 3.1415926535897931

Inserindo y. depois de um marcador qualquer, dizemos que o valor que for
inserido no lugar do marcador dever ter exatamente y caracteres:

>>> print 'O valor %8.2f' %valor
O valor 3.14

Somando o inteiro 3, o marcador decimal e as duas casas decimais, todo o
float inserido no marcador tem 4 caracteres. Ento so adicionados mais 4 espaos em
branco antes do valor, para completar os 8 caracteres exigidos.

>>> print 'O valor %12.4f' %valor
O valor 3.1416

O inteiro 3, o marcador decimal e quatro casas decimais exigem mais 6
espaos em branco para completar 12 caracteres.


I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
26
2. Recursos de manipulao de listas

>>> a=[1,2,3]
>>> a
[1, 2, 3]

O mtodo append adiciona um valor ao final da lista. Extend faz a mesma
coisa, mas adiciona uma lista inteira de uma vez.

>>> a.append('poncan')
>>> a
[1, 2, 3, 'poncan']
>>> a.extend([0,0,-3])
>>> a
[1, 2, 3, 'poncan', 0, 0, -3]

Veja a diferena se fizermos append de uma lista inteira: a lista ser
adicionada como um nico valor, num nico endereo:

>>> b=[1,2,3]
>>> b.append([1,2,3])
>>> b
[1, 2, 3,[1, 2, 3]]

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
27
Se em vez de adicionar um valor ao final da lista voc quiser inserir num
endereo especfico, pode usar insert(endereo,valor). Aqui inserimos o valor "start
no endereo zero da lista a.

>>> a.insert(0,'start')
>>> a
['start',1,2,3,'poncan',0,0,-3]

Tambm h algumas ferramentas para retirar valores de listas. Remove
uma delas. Fazendo remove(0) sobre a lista a, retiramos dela o primeiro valor 0 que
apareceu. Depois fazemos o mesmo com "poncan:

>>> a.remove(0)
>>> a
['start', 1, 2, 3, 'poncan', 0, -3
>>> a.remove('poncan')
>>> a
['start', 1, 2, 3, 0, -3]

Um pouco parecido com remove o mtodo pop. objeto1.pop(i) remove de
objeto1 o valor armazenado no endereo i:

>>> a.pop(0)
'start'
>>> a
[1, 2, 3, 0, -3]
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
28
J o mtodo count retorna o nmero de vezes que seu argumento aparece na
lista. Para saber o nmero de vezes (uma vez) que o valor "3 aparece na lista "a,
fazemos:

>>> a.count(3)
1

J vimos que a varredura ao contrrio, por meio de incremento negativo,
poderia ser aplicada a qualquer seqncia, no somente a strings. Vamos aproveitar
que estamos falando de manipulao de listas para verificar isso. Veja como fcil
obter a Escala de Dureza de Mohs em ordem decrescente de dureza:

>>> Mohs=['Talco', 'Gipsita', 'Calcita', 'Fluorita', 'Apatita',
'Ortoclsio', 'Quartzo', 'Topzio', 'Corndon', 'Diamante']
>>> Mohs[::-1]
['Diamante', 'Cor\xedndon', 'Top\xe1zio', 'Quartzo', 'Ortocl\xe1sio',
'Apatita', 'Fluorita', 'Calcita', 'Gipsita', 'Talco']







I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
29
Parte IV - Testes, Loops, Varreduras e Erros

1. Enquanto...

No cdigo abaixo, o loop "while testa se o valor de b menor que 5. Se isso
for verdade, so executados os procedimentos depois dos dois pontos (:). Neste caso,
imprimimos o valor de b e depois fazemos uma reatribuio: chamamos de "b o valor
anterior atribudo a "b somado a 1.

>>> b=0
>>> while b < 5:
print b
b=b+1

0
1
2
3
4

Perceba o alinhamento de todos os procedimentos que devem ser executados
caso b seja menor que 5. Este um conceito muito importante em Python:
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
30
indentao
2
. Quando fizermos um programa completo, voc perceber que quando no
quiser que um loop faa mais nada, basta retornar o alinhamento. Uma caracterstica
do IDLE que ele percebe onde o cdigo deve ser indentado e faz isso
automaticamente. Voc percebe esta caracterstica quando pressioa ENTER depois de
... b < 5:. A linha inferior j automaticamente alinhada debaixo do while. Ao
pressionar ENTER novamente depois de print b e b=b+1, acontece a mesma coisa,
isso porque o IDLE espera que voc informe mais um procedimento. Pressionando
ENTER mais uma vez, o Shell perceber que no h mais procedimentos a serem
adicionados e s ento executa o cdigo.
Vejamos um loop mais elaborado; desta vez, com string formatada.

>>> b=1
>>> while b < 5:
print '%i dlares valem %.2f reais' %(b,b*2.98)
b=b+1

1 dlares valem 2.98 reais
2 dlares valem 5.96 reais
3 dlares valem 8.94 reais
4 dlares valem 11.92 reais

Se no for includa a ltima linha que "incrementa o valor de b, este valor
permanecer sempre 1, e o loop testar sempre 1 < 5. Como isso sempre verdade,
ser impressa eternamente a linha


2
Voc tambm pode encontrar na literatura de Python o termo endentao, que significa a mesma coisa. No
entanto, indentao mais utilizado, embora seja um neologismo (j incorporado por alguns dicionrios da
lngua portuguesa).
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
31
1 dlares valem 2.98 reais

Se voc fizer este teste, basta pressionar CTRL+C (se estiver usando o IDLE)
para cancelar o loop.
Ao estudar o script de outras pessoas, pode ser que voc encontre algo como
b+=1, ou b*=2. Escrever b+=n o mesmo que b=b+n, e escrever b*=n o mesmo que
b=b*n.

2. Entrada de dados

Veja como ler uma entrada do usurio em Python:

>>> x = raw_input('Informe a fase: ')
Informe a fase: vapor
>>> x
'vapor'

A funo raw_input(s) mostra a string s para o usurio e espera que ele
fornea algum dado. Ento, a funo transforma este dado numa string e a retorna
para o cdigo.
Para salvar esta entrada e usa-la posteriormente, basta salvar o resultado da
funo sob um nome qualquer, como fizemos acima com "x.
Todo mundo, ao menos uma vez na vida, se esquece de que raw_input()
retorna sempre uma string e perde tempo com isso. Veja um clssico:
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
32

>>> a = raw_input('Tamanho do lado do quadrado: ')
Tamanho do lado do quadrado: 23
>>> print 'O permetro deste quadrado ', 4*a
O permetro deste quadrado 23232323
>>> type(a)
<type 'str'>

Obviamente, o permetro de um quadrado de lado 23 no 23232323. Este
o resultado da multiplicao da string a pelo inteiro 4: quatro vezes a string.
Se voc quer solicitar um inteiro ou um float do usurio, deve converter o
resultado de raw_input() para o tipo de objeto desejado usando as funes int ou
float:

>>> a = raw_input('Tamanho do lado do quadrado: ')
Tamanho do lado do quadrado: 23
>>> a = int(a)
>>> type(a)
<type 'int'>
>>> print 'O permetro deste quadrado ', 4*a
O permetro deste quadrado 92

Ou mais diretamente,

>>> a = int(raw_input('Tamanho do lado do quadrado: '))
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
33
Tamanho do lado do quadrado: 23
>>> type(a)
<type 'int'>
Analogamente, a funo para transformar o tipo de um objeto em float
float(x):

>>> r = float(raw_input('Raio: '))
Raio: 4.5
>>> type(r)
<type 'float'>

3. If... Elif... Else...

No pseudocdigo abaixo, testamos se o nome "x contm a string "lquido.

IF
Se isto for verdade, o cdigo imprime "Menos de 100 C.
ELIF
Seno, se "x no "lquido, mas "vapor, o cdigo imprime "Mais de 100 C.
ELSE
Caso "x no seja nem "lquido nem "vapor, o resultado "Menos de 0 C.

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
34
Ateno para a indentao: tudo que desejamos que seja feito caso x seja
"lquido est alinhado. O mesmo com elif e else.

>>> x = raw_input('Informe a fase: ')
Informe a fase: vapor
>>> if x == 'lquido':
print 'Menos de 100 C'
elif x == 'vapor' :
print 'Mais de 100 C'
else:
print 'Menos de 0 C'

Mais de 100 C

Vamos dar uma melhorada no cdigo da pgina 30, j que a impresso que
fizemos l deu uma escorregada gramatical ("1 dlares valem...):

>>> b = 1
>>> while b < 4:
if b==1:
print '%i dlar vale %.2f reais' %(b,b*2.98)
else:
print '%i dlares valem %.2f reais' %(b,b*2.98)
b+=1

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
35
1 dlar vale 2.98 reais
2 dlares valem 5.96 reais
3 dlares valem 8.94 reais
4. For

O for de Python uma ferramenta poderosa e muito caracterstica desta
linguagem. Com for, podemos "varrer qualquer seqncia (strings, listas, tuplas) ou
dicionrio.

>>> a = ['Joo', 'Rafael', 'Douglas']
>>> a
['Jo\xe3o', 'Rafael', 'Douglas']
>>> for i in a:
print i

Joo
Rafael
Douglas
>>> for x in a:
print '%s tem %i letras' %(x,len(x))

Joo tem 4 letras
Rafael tem 6 letras
Douglas tem 7 letras

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
36
"Para x em a: - "x o nome que demos a cada um dos elementos da
seqncia a neste exemplo. Desta forma, quando falamos em x estamos falando do
elemento da seqncia a que est sendo estudado no momento. Primeiro, "x "Joo
(o primeiro elemento de a). por isso que quando imprimimos x e len(x) imprimimos
na verdade "Joo e len(`Joo). Simples, no? Poderamos ter usado qualquer nome
no lugar de x.
Uma funo importante para usarmos o for a funo range(ni,nf,i), que cria
uma lista comeando do inteiro ni at o inteiro nf-1, com incremento i entre os
nmeros:

>>> range(1,11,2)
[1, 3, 5, 7, 9]

Os valores de ni, nf e i precisam ser nmeros inteiros. Podemos omitir ni e i
se estes valores forem zero e 1, respectivamente:

>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> range(1,11)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> for elefante in range(5):
print elefante**2

0
1
4
9
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
37
16

Assim o for sobre a seqncia range(5). Para voc perceber que podemos
chamar os elementos da seqncia de qualquer coisa, usamos o (bizarro) nome
"elefante.
O tamanho da seqncia a (tamanho 3) um nmero inteiro, ento no h
problema em aplicar a funo range sobre len(a). Na verdade, isso o mesmo que
range(3):

>>> for i in range(len(a)):
print i

0
1
2

E aqui vemos porque interessante que range gere uma lista de nmeros
inteiros - o endereamento das seqncias em Python tambm feito por nmeros
inteiros:

>>> for i in range(len(a)):
print i,a[i]

0 Joo
1 Rafael
2 Douglas
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
38

Nesta altura do campeonato voc j deve ter percebido que a indentao
tambm o mecanismo que regula quais aes fazem parte do raio de ao do bloco
de for.
E assim encadeamos alguns blocos de for:

>>> matriz = ((1,0,0),(0,1,0),(0,0,1))
>>> for i in range(len(matriz)): # o mesmo que range(3), ok?
print '\n'
for j in range(len(matriz)): # idem
print matriz[i][j],

1 0 0

0 1 0

0 0 1

O cdigo print '\n' imprime uma linha em branco. Podemos fazer print
'\n'*k para imprimir k linhas em branco...
Neste exemplo e no anterior, aparece uma vrgula na linha de print. Ela
serve para imprimir os termos todos na mesma linha.
Ao aplicar uma varredura de for sobre um dicionrio, o nome dado aos
elementos interpretado como sendo a chave do dicionrio. Melhor mostrar com
exemplos:
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
39

>>> oramento = {'asa':1200,'combustvel':200,'motor':4500}
>>> for qualquer in orcamento:
print qualquer

combustvel
asa
motor

O nome qualquer assume o valor das chaves do dicionrio orcamento. Sendo
assim,

>>> for teste123 in orcamento:
print teste123,'custa R$',orcamento[teste123]

combustvel custa R$ 200
asa custa R$ 1200
motor custa R$ 4500

Por exemplo: j que teste123 assume o valor das chaves de orcamento, seu
primeiro valor assumido 'combustvel', a primeira chave deste dicionrio. Assim,
fazer orcamento[teste123] o mesmo que fazer orcamento['combustvel'], que
retornar o valor associado a esta chave.

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
40
Voc sabe que dicionario.items() retorna uma lista
de tuplas contendo o par (chave, valor). Usando este
mtodo, como voc faria para imprimir os mesmos
resultados do ltimo bloco de for? Lembre-se que o for pode
vasculhar qualquer seqncia, inclusive uma lista de tuplas.

5. Break

O comando break serve para abortar um bloco de while ou for.
Voc se lembra do operador "%? Ele retorna o resto da diviso entre dois
inteiros. O cdigo abaixo faz uma varredura na lista [2,3,4,5,6,...,n-1] e testa se n
divisvel por algum destes valores. Se for divisvel (ou seja, se n % i == 0), ento n
no um nmero primo e a varredura do for cancelada com break.

>>> n = int(raw_input('Nmero a testar: '))
Nmero a testar: 28
>>> for i in range(2,n):
if n % i == 0: print 'Nmero no primo'; break

Nmero no primo

Nota: Se o cdigo a ser executado aps um sinal de dois pontos contm
poucas linhas, voc pode coloca-lo na frente dos dois pontos e separar os
procedimentos com ponto e vrgula, como fizemos acima no bloco de if. O mesmo sinal
de dois pontos aparece em blocos de for, while e em definies de funes.
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
41
A seguir demonstramos o break abortando um bloco de while:

>>> b=10
>>> while 1:
b=b-1
print b
if b<7: break

9
8
7
6

Observao: while 1: um loop infinito. Use isto sempre que quiser
executar um cdigo indefinidamente. Voc pode cancela-lo com um break. O cdigo
break cancela somente o loop a que est submetido, se houver vrios loops
encadeados:

loop1:
blablabla
blebleble
loop2:
bliblibli
blobloblo
break2 # Cancela somente o loop2
break1 # Est alinhado com o loop1, portanto cancela somente loop1.
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
42
6. Tratamento de erros

Nem sempre podemos garantir que as operaes que efetuamos sobre uma
seqncia ou ao longo de um loop so vlidas, principalmente se a seqncia for muito
grande ou for fornecida pelo usurio.
Num exemplo simples, vamos recolher uma lista de 3 inteiros fornecidos pelo
usurio. O que nos garante que o usurio no tentar inserir uma string na lista?

>>> lst=[]
>>> for nome in range(3):
lst.append(int(raw_input('Digite um valor: ')))

Digite um valor: 33
Digite um valor: -4
Digite um valor: a

Traceback (most recent call last):
File "<pyshell#26>", line 2, in -toplevel-
lst.append(int(raw_input('Digite um valor: ')))
ValueError: invalid literal for int(): a

A funo int(qualquercoisa) no pde transformar a string `a em um inteiro
(claro!). Como evitar ento que o usurio fornea uma string ou outro valor qualquer
que no possa ser transformado em inteiro? Uma das formas :

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
43
>>> lst=[]
>>> for i in range(3):
while 1:
try:
lst.append(int(raw_input('Digite um valor: ')))
break
except:
print 'Digite somente nmeros!!!'

Digite um valor: 2
Digite um valor: a
Digite somente nmeros!!!
Digite um valor: r
Digite somente nmeros!!!
Digite um valor: t
Digite somente nmeros!!!
Digite um valor: 33
Digite um valor: e
Digite somente nmeros!!!
Digite um valor: w
Digite somente nmeros!!!
Digite um valor: -4.99
>>> lst
[2, 33, -4]

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
44
A sintaxe de try :

try:
primeiro tenta fazer isso
e tudo que esteja neste alinhamento (indentao, lembra?)
isso tambm
e isso
except:
se qualquer linha dentro do bloco try der erro,
ento sero executadas estas linhas.

No exemplo anterior, tentamos concatenar lista lst o valor coletado pelo
raw_input, porm transformado em nmero inteiro pela funo int(). Se fornecermos
uma string, a funo no conseguir transform-la em inteiro. A entra em ao o
bloco "except:, com o qual imprimimos um aviso para que o usurio informe um
nmero. Como estamos dentro de um bloco de loop infinito, voltamos novamente ao
try para recolher um valor do usurio e transforma-lo em inteiro. Se no houver erro
desta vez, iremos para a prxima linha, "break, que cancelar o loop infinito.
Acaba por a? No. Ainda estamos fazendo a varredura do for, ento iremos
para o prximo valor da seqncia range(3), e assim por diante.
A seguir, recolhemos um inteiro do usurio e tentamos calcular seu inverso.
Se o usurio digitar um inteiro menor que zero, teremos problemas quando x for igual
a zero, j que no h inverso de zero. Assim, simplesmente tentamos calcular o
inverso de x; se no for possvel, informamos que no foi possvel.

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
45
>>> x = int(raw_input('Digite um nmero inteiro: '))
Digite um nmero inteiro: -3
>>> while x<3:
try:
print 1./x
except:
print 'No possvel dividir 1 por %i' %x
x=x+1 # Tambm pode ser x+=1

-0.333333333333
-0.5
-1.0
No possvel dividir 1 por 0
1.0
0.5

Podemos evitar este problema se pularmos a
diviso 1./x quando x for igual a zero. Como voc faria
isso?

Observe tambm a diferena entre 1/3 e 1./3: no primeiro, temos uma
diviso de dois inteiros que gera um resultado inteiro, 0. No segundo, temos uma
diviso entre o float 1. (que o mesmo que 1.0) e o inteiro 3, que gera um resultado
float, 0.33333333333333331. Se quisermos o resultado em float, basta que um dos
termos da operao seja um float:

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
46
>>> 1+2
3
>>> 1+2.0
3.0
>>> 2*9
18
>>> 2*9.
18.0
>>> 1/3.
0.33333333333333331



Parte V - Nosso primeiro programa completo

Voc pode escrever programas em Python at mesmo no bloco de notas;
basta que salve o arquivo com extenso .py e que no se esquea da indentao.
Uma das formas mais prticas no editor do IDLE, que alm de mostrar com
cores diferentes as diversas partes do cdigo como no IDLE, tambm indenta o cdigo
automaticamente onde necessrio e facilita os testes do programa.
Para usar este editor para escrever um programa completo, v a File > New
window no IDLE, ou simplesmente CTRL+N.
Assim que voc salvar o programa (no se esquea da extenso .py!), as
strings vo aparecer em verde, algums cdigos como if, for e while aparecero em
laranja e os comentrios em vermelho. Acostume-se a salvar o programa antes
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
47
mesmo de comear a escrev-lo, assim voc poder contar desde o incio com o auxlio
das cores.
Quando quiser testar um programa, v a Run > Run Module, ou
simplesmente F5.
Vamos fazer um programa que teste se um nmero fornecido pelo usurio
perfeito. Dizemos que um nmero perfeito se ele for igual soma dos seus divisores
menores que ele prprio. O menor nmero perfeito, por exemplo, 6 (6=1+2+3).

# perfeitos.py
n = int(raw_input('Digite o nmero a ser testado: '))
teste = 0
for i in range(1,n):
if n % i == 0:
teste=teste+i
if teste == n:
print n, ' um nmero perfeito'
else:
print n, 'no um nmero perfeito'

Vamos analisar este programa:
Linha 1: aqui lemos do usurio o valor de n. Inicialmente o valor uma
string, como qualquer valor recebido pela funo raw_input, e depois o
transformamos em inteiro pela funo int, para s ento atribuir o resultado
ao nome n.
Linha 2: Uma forma de fazer o teste se n perfeito ou no criar uma
varivel inicialmente valendo zero e ir somando a ela todos os divisores de n
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
48
que encontrarmos. Ao final, testamos se o valor desta varivel igual a n. Se
for, n um nmero perfeito.
Linha 3: Ok, ento vamos procurar os divisores de n. Sabemos que todos os
inteiros candidatos a divisores de n esto na seqncia range(1,n) (agora
voc j enxerga essa seqncia como [1,2,3,4,...,n-1], no ?). Ento basta
fazer uma varredura (isto , um for) sobre range(1,n) testando quais destes
so divisores de n.
Linha 4: Se o termo atual da seqncia divisor de n, ento...
Linha 5: ...adicione-o a teste!
Linha 6: Terminamos a busca dos divisores. Perceba que voltamos ao
alinhamento do for. Segundo a indentao, tudo o que escrevermos agora
no ser mais executado para cada um dos valores da seqncia. Basta ento
testar se a soma dos divisores de n, agora salvo sob o nome "teste,
corresponde a n.
Linha 7: Isto o que ser executado caso o valor de "teste seja igual ao de n
(ou seja, se n for igual soma dos seus divisores - um nmero perfeito,
portanto).
Linha 8: Seno, (se "teste no igual soma dos divisores de n)...
Linha 9: ...n no um nmero perfeito.
Executando o programa (pressionar F5 o jeito mais rpido),

>>>
Digite o nmero a ser testado: 6
6 um nmero perfeito

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
49
Voltando janela onde est o programa e pressionando F5 novamente para
testar outro valor,

>>>
Digite o nmero a ser testado: 7
7 no um nmero perfeito

Chato pressionar F5 toda hora, no ? Encapsulando todo este cdigo num
loop infinito (while 1:, por exemplo), voc pode executar isso infinitas vezes:

while 1:
o cdigo aqui (indentado corretamente)

Encapsulando o programa todo num loop infinito, o
problema passa a ser outro: preciso pressionar CTRL+C
para cancelar o teste. Como voc faria para o programa
parar os testes de forma mais elegante, de preferncia
perguntando ao usurio se ele deseja testar mais algum
nmero?
Como bom curioso, voc no est se perguntando que
outros nmeros so perfeitos alm do 6? Agora voc tem o
poder em suas mos (Python)! Tente fazer um programa
para descobrir quais so os 3 nmeros perfeitos que
existem at 10000 alm do 6.

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
50
Voc tambm pode executar seu programa clicando em seu cone, na pasta
em que o programa foi salvo. Desta forma, o programa no ser executado no IDLE, e
sim num ambiente mais veloz. Um detalhe quando se usa esta forma de execuo
que a janela que aberta enquanto o programa roda se fecha imediatamente aps o
trmino do programa, no permitindo ao usurio estudar os dados de sada. Uma
forma simples de mant-la aberta at que o usurio deseje incluir uma linha

raw_input(Pressione ENTER)

ao final do programa, j que raw_input espera por uma entrada do usurio. Se o
usurio vai pressionar ENTER ou outra tecla qualquer, no importa, j que esta
informao no ser usada para nada.
Para editar o programa no IDLE, clique sobre o cone com o boto da direita e
escolher "Editar com IDLE.
Observao: se voc estiver usando Linux (meus parabns!), necessrio
adicionar uma linha no comeo do seu programa especificando a localizao do
Python:

#!/usr/bin/python

A linha acima informa ao sistema para procurar pelo programa
/usr/bin/python e transmitir o resto do arquivo a este programa. Note que o
diretrio onde se encontra o Python varia de sistema para sistema. O diretrio acima
vlido para o Conectiva Linux 10.0.
Agradecimentos ao parceiro Carlos Mota Castro, fervoroso defensor de Linux,
por esta observao. O Carlos adaptou esta nota de uma apostila de Perl que ele
estava aprendendo. Estava aprendendo, porque agora ele j ouviu falar de Python...
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
51
Parte VI - Funes e Mdulos

1. Definindo funes

Assim como os mdulos, as funes podem ser muito teis para executar um
bloco de cdigo que ser repetido vrias vezes, economizando linhas de cdigo.
Quando ocorrer um erro nestes procedimentos que sero muito repetidos, basta
alterar a funo, sem a necessidade de vasculhar todo o programa corrigindo todas as
repeties. A sintaxe para definir funes em Python :

def nome_da_funcao(parametro1,parametro2,...):
operacoes sobre os n parametros

Imagine que seja necessrio calcular o quadrado de um nmero vrias vezes
ao longo do programa. Podemos criar uma funo para isso do seguinte modo:

>>> def f(x):
return x**2

>>> f(3)
9


I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
52
Outra funo, desta vez com dois argumentos:

>>> def elevar(x,y):
return x**y

>>> elevar(9,9)
387420489

H meios de definir funes que trabalham com um nmero indefinido de
argumentos, de acordo com a sintaxe:

def nome_da_funo(*nome1):
procedimentos...

Esta sintaxe toma todos os elementos inseridos dentro dos parnteses como
sendo uma tupla. Observe:

>>> def impressora(*argumentos):
return argumentos

>>> impressora(1,2,3)
(1, 2, 3)

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
53
Assim fica claro como os argumentos fornecidos pelo usurio - 1, 2 e 3 - so
admitidos como argumentos da funo em forma de tupla. Considerando isso,
podemos trabalhar estes argumentos facilmente, j que temos um certo traquejo em
manipular tuplas:

>>> def somatoria(*argumentos):
soma = 0
for i in argumentos:
soma+=i # Voc j sabe: soma+=i o mesmo que soma=soma+i
return soma

>>> somatoria(1,2,3,4,5)
15

A funo recm-definida assume quantos argumentos o usurio desejar.
Apesar disso, alguns argumentos podem no ser admitidos pelos procedimentos
definidos dentro da funo, por exemplo,

>>> somatoria(1,2,3,4,'teste')

Traceback (most recent call last):
File "<pyshell#27>", line 1, in -toplevel-
somatoria(1,2,3,4,'teste')
File "<pyshell#25>", line 4, in somatoria
soma+=i
TypeError: unsupported operand type(s) for +=: 'int' and 'str'
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
54
Isso porque a funo somatoria no capaz de somar inteiros com a string
'teste'.

Usando o que aprendemos sobre tratamentos de erros,
como voc reescreveria a funo somatoria para informar
ao usurio que um de seus argumentos foi invlido? Evolua
este cdigo para mostrar tambm qual dos argumentos
invlido (o primeiro, o segundo, etc.).

As funes no precisam ser limitadas a operaes algbricas:

>>> def testa_primo(n):
teste=1
for i in range(2,n):
if n % i == 0:
teste=teste+1
if teste != 1:
print 'Nmero no primo'
else:
print 'Nmero primo'

>>> testa_primo(28)
Nmero no primo
>>> testa_primo(7)
Nmero primo
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
55
No h problema algum em usar o resultado da funo para outra operao.
Assim, podemos usar diretamente f(3) - que igual a 9 - como parmetro da funo
elevar:

>>> elevar(f(3),4)
6561

Voc pode colocar um default para um argumento, para ser admitido pela
funo caso o usurio da funo no fornea este argumento.

>>> def user(nome='Labaki'):
print 'Meu nome ',nome

>>> user('Mamute')
Meu nome Mamute
>>> user()
Meu nome Labaki

Outro exemplo:

>>> cadastro=[]
>>> def add(x,y='Casado',z=3):
cadastro.append([x,y,z])
>>> add('Mozart','Solteiro','sem filhos')
>>> cadastro
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
56
[['Mozart', 'Solteiro', 'sem filhos']]
>>> add('Beethoven')
>>> cadastro
[['Mozart', 'Solteiro', 'sem filhos'], ['Beethoven', 'Casado', 3]]
>>> add('Bach','Vivo')
>>> cadastro
[['Mozart', 'Solteiro', 'sem filhos'], ['Beethoven', 'Casado', 3],
['Bach', 'Vi\xfavo', 3]]

Se voc quer usar o default de y mas no o de z, pode indicar isso assim:

>>> add('Salieri',z=4)
>>> cadastro
[['Mozart', 'Solteiro', 'sem filhos'], ['Beethoven', 'Casado', 3],
['Bach', 'Vi\xfavo', 3], ['Salieri', 'Casado', 4]]

Para facilitar a vida de quem usar seus programas, e talvez a sua prpria
quando tiver que fazer manuteno nos seus programas, pode-se inserir pequenas
informaes sobre as funes dentro delas. So as chamadas "doc strings.

>>> def f(x):
"""Esta funo retorna o
quadrado de um nmero"""
return x**2
>>> f(2)
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
57
4
>>> print f.__doc__
Esta funo retorna o
quadrado de um nmero

2. Funes sobre Seqncias

Se voc possui uma seqncia e precisa aplicar uma funo sobre cada um
dos seus termos, h meios bem prticos de fazer isso. Um deles a funo map, que
aplica uma funo sobre uma seqncia e retorna uma lista contendo os resultados.
Na sintaxe mostrada abaixo, cada um dos elementos de seqncia1 tomado como
argumento de funo1:

map(funo1, seqncia1)

>>> def quadrado(termo):
return termo**2

>>> elementos=[1,2,3,4,5,6]
>>> map(quadrado,elementos)
[1, 4, 9, 16, 25, 36]

Obtemos assim a lista com os quadrados dos termos da lista elementos.
Isso tambm funciona com operaes no algbricas:
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
58
>>> orcamento={'asa':1200, 'combustvel':200, 'motor':4500}
>>> def cambio(componente):
print componente[0],'R$ ',componente[1]
print componente[0],'US$ ',componente[1]/3.
print '\n'

>>> map(cambio,orcamento.items())
combustvel R$ 200
combustvel US$ 66.6666666667

asa R$ 1200
asa US$ 400.0

motor R$ 4500
motor US$ 1500.0

[None, None, None]

Breve explicao sobre o cdigo acima: j vimos que orcamento.items()
uma lista de tuplas,

>>> orcamento.items()
[('combust\xedvel', 200), ('asa', 1200), ('motor', 4500)]

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
59
assim podemos aplicar a funo map sobre esta seqncia como sobre qualquer outra.
Neste caso, a funo map tomar a primeira tupla, ('combust\xedvel', 200) como o
argumento componente da funo cambio. Ao fazer componente[0], estamos fazendo
('combust\xedvel', 200)[0], que correspondente a 'combustvel', enquanto
componente[1] correspondente a '200'. E assim com todos os termos da seqncia.
Aquele estranho [None, None, None] ao final da execuo um resultado
importantssimo e vai alimentar uma discusso posterior sobre return versus side
effects.
Outra interao funo-seqncia interessante reduce, que toma uma
funo e uma seqncia e retorna um nico valor, com a sintaxe reduce(funo,
seqncia):

>>> def soma(alfa,beta):
return alfa+beta

>>> reduce(soma,[1,2,3])
6

Primeiro, reduce assume o primeiro item da lista [1,2,3] (o inteiro 1) como
sendo o argumento alfa da funo soma, e o segundo item (o inteiro 2) como sendo o
argumento beta. Resultado: 1+2 = 3. Este inteiro 3 tomado ento como o
argumento alfa e o prximo item da lista (o inteiro 3) assumido como beta.
Resultado: 3+3 = 6. O processo repetido at o final da seqncia.

Este recurso parece ideal para o nosso algoritmo
anterior de verificar se um nmero perfeito, no parece?
Como voc reescreveria aquele algoritmo usando reduce?
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
60
Mais um exemplo:

>>> def eleva(base,expoente):
return base**expoente

>>> elementos=[4,3,2,1]
>>> reduce(eleva,elementos)
4096

Da mesma forma, o que acontece aqui :

base expoente base**expoente Resultado
Primeiro Passo 4 3 4**3 64
Segundo Passo 64 2 64**2 4096
Terceiro Passo 4096 1 4096**1 4096
Resultado 4096

Um recurso de trabalho com funes e seqncias muito caracterstico de
Python so as list comprehensions, que permitem gerar uma lista a partir de funes
simples.

>>> [x**2 for x in [1,2,3]]
[1, 4, 9]

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
61
Com ltima sentena dizemos: retorne-me uma lista contendo os quadrados
de x, sendo x cada um dos elementos da seqncia [1,2,3]. E abaixo, conseguimos
uma lista de tuplas contendo o par (valor, quadrado do valor), sendo valor cada um
dos itens da seqncia [0, 1, 2, 3, 4].

>>> [(x,x**2) for x in range(5)]
[(0, 0), (1, 1), (2, 4), (3, 9), (4, 16)]

A seguir, usamos list comprehensions para operaes no algbricas. Esta
tambm uma boa ocasio para voc se convencer de que formatao de strings no
serve s quando a string est aps um print, mas sim em qualquer lugar onde haja
uma string.

>>> ['%ss' %nome for nome in ['Proclise','Jilo','Bozo','Cauchy']]
['Proclises', 'Jilos', 'Bozos', 'Cauchys']

Tambm simples usar list comprehensions com seqncia de seqncias.
Com uma tupla de tuplas fica assim:

>>> valores=((4,5,6),(7,8,9),(5,6,-7))
>>> [a+b+c for (a,b,c) in valores]
[15, 24, 4]

Aqui, 15 = 4+5+6, 24 = 7+8+9 e 4 = 5+6-7.
Os resultados das list comprehensions podem ser usados naturalmente como
qualquer lista, inclusive em blocos de for e funes como reduce e map.
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
62
>>> def metade(t):
return t/2.

>>> map(metade,[rrr*2 for rrr in [66,77,88,99]])
[66.0, 77.0, 88.0, 99.0]

Neste exemplo, [rrr*2 for rrr in [66,77,88,99]] gera a lista [132, 154,
176, 198]. Ento a funo map aplica a funo metade que divide cada um destes
termos por 2, voltando lista original. Mais fcil ainda, voc pode usar as list
comprehensions para fazer mapeamentos, aplicando a funo metade diretamente
sobre os termos rrr:

>>> [metade(rrr*2) for rrr in [66,77,88,99]]
[66.0, 77.0, 88.0, 99.0]

3. Return versus Side Effects

[None, None, None]

O que ser que isso???
L da Matemtica Elementar j sabemos que uma funo uma relao que
associa a cada elemento de um conjunto A um nico elemento de outro conjunto B.
Pode haver funes que no tm correspondentes em B para alguns valores de A (um
caso clssico, f(x) = 1/x no existe quando x=0), mas podemos garantir que uma
funo nunca retornar dois valores em B para um nico valor em A.
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
63
Os mesmos princpios se aplicam s funes em Python. Nossas funes
podem tomar um ou mais argumentos e sempre retornaro um - e somente um -
resultado, definido pelo cdigo return:

def nome_da_funo(argumento_1,argumento_2,...,argumento_n):
return parmetro

Nesta funo genrica, o (nico) valor de retorno parmetro. Observe uma
funo j conhecida, em que o parmetro de retorno o quadrado do argumento de
entrada:

>>> def f(x):
return x**2

>>> f(3)
9

Qualquer outra coisa que a funo imprima, concatene, modifique, etc., no
considerada valor de retorno, e sim side effect (efeito colateral).

>>> lista=[]
>>> def f(x):
lista.append(x)
print x
return x**2

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
64
>>> f(2)
2
4
>>> lista
[2]

Aqui, o 2 impresso e o 2 concatenado lista so side effects e o 4 impresso
o valor de retorno da funo. Isso pode ser percebido facilmente quando o resultado
de execuo da funo usado para outra finalidade, como no exemplo abaixo:

>>> 2*f(9)
9
162
>>> lista
[2, 9]

Multiplicar f(9) por um nmero s ter efeito sobre seu valor de retorno, 81 =
9**2. Somente o valor de retorno dessa funo f (o 89) multiplicado por 2,
resultando em 162. Os side effects no sofrem alterao alguma - o argumento 9 foi
impresso e concatenado lista.
Quando no definido nenhum valor de retorno com o comando return, a
funo entende que seu valor de retorno None. Neste caso, qualquer operao sobre
os resultados de execuo da funo gera erros:

>>> def h(t):
print t**3
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
65
>>> h(7)
343
>>> 2*h(7)
343

Traceback (most recent call last):
File "<pyshell#38>", line 1, in -toplevel-
2*h(7)
TypeError: unsupported operand type(s) for *: 'int' and 'NoneType'

O erro era previsvel, j que no faz sentido multiplicar None por 2.
O famigerado [None, None, None], portanto, se refere aos valores de
retorno da funo cambio da pgina 58, quando aplicados sobre os argumentos da
lista orcamento.items().
Nas pginas de exerccios h um teste bem interessante e famoso que ilustra
muito bem a diferena entre returns e side effects. Tente prever o resultado da
execuo do script sem execut-lo.

Quaisquer resultados obtidos com as funes builtins
de Python, como map, reduce, raw_input, type, tambm
so valores de retorno e/ou side effects. A funo map, por
exemplo, gera uma lista a partir da execuo de uma
funo sobre uma seqncia. Sugira uma forma simples de
descobrir se a lista gerada por map um valor de retorno
ou um side effect desta funo.

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
66
4. Mdulos

Em algumas ocasies, voc poder precisar das mesmas funes vrias vezes
em programas diferentes. Quando isso ocorrer, pode usar mdulos, que so como
"pacotes de funes.
Vamos criar nosso primeiro mdulo, contendo quatro funes: uma que
calcula a circunferncia de um crculo, outra que calcula a rea do crculo, outra que
eleva uma base qualquer a uma potncia qualquer e uma funo intil.
O procedimento para criar um mdulo o mesmo para escrever um programa
completo: abra uma nova janela. No IDLE, v a File > New Window, ou simplesente
CTRL+N. Digite as funes neste programa e salve-o com a extenso .py -
necessrio que seja num diretrio que esteja no path
3
. Para saber quais diretrios do
seu computador esto no path, voc pode usar este pequeno script (que voc
entender melhor como funciona ao final deste captulo):

>>> import sys
>>> for i in sys.path:
print i

Chamaremos nosso mdulo atual de circulos.py.

#circulos.py
def perimetro(r):
"""Esta funcao calcula o perimetro de

3
Sem muito rigor, o path uma relao de todos os diretrios em que Python vai procurar pelo seu mdulo.
Se voc quiser, pode salvar seu mdulo na pasta Python23, em C:, que certamente estar no path. No entanto,
evite salvar todos os seus mdulo l, para no sobrecarregar este diretrio.
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
67
um circulo de raio r."""
try:
r=float(r)
return 2*3.14*r
except:
print 'O argumento da funcao deve ser um numero.'

def area(r):
"""Esta funcao calcula a area de
um circulo de raio r."""
try:
r=float(r)
return 3.14*(r**2)
except:
print 'O argumento da funcao deve ser um numero.'

def potencia(x,y=2):
"""potencia(x,y) eleva x a potencia y.
Default: y=2."""
try:
return x**y
except:
print 'Argumentos invalidos'

def nada():
"""Esta funcao nao faz nada.
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
68
So serve para mostrar doc strings."""
pass

No pressione F5 para executar este programa! Pode fechar a janela,
inclusive. Abra uma nova janela de IDLE (voc pode fazer isso pela janela do
programa, em Run > Python Shell) e tente usar alguma das funes recm criadas.

>>> potencia(2,3)

Traceback (most recent call last):
File "<pyshell#9>", line 1, in -toplevel-
potencia(2,3)
NameError: name 'potencia' is not defined

A funo ainda no est definida no escopo deste programa. Uma das formas
de usar as funes importando o mdulo:

>>> import circulos

Se voc salvou o mdulo na pasta C:/Python23 ou em qualquer outra que
esteja no path, a importao do mdulo deve dar certo. Uma vez importado o mdulo,
a sintaxe para utiliza-lo

modulo.funo(parmetros)

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
69
Agora sim, podemos utilizar a funo potencia:

>>> circulos.potencia(2,3)
8
>>> print circulos.potencia.__doc__
potencia(x,y) eleva x a potencia y.
Default: y=2.

>>> print circulos.nada.__doc__
Esta funcao nao faz nada.
So serve para mostrar doc strings.

>>> circulos.perimetro(33.)
207.24000000000001

>>> circulos.outrafuncao(1,2)

Traceback (most recent call last):
File "<pyshell#6>", line 1, in -toplevel-
circulos.outrafuncao(1,2)
AttributeError: 'module' object has no attribute 'outrafuncao'

Este erro ocorre porque no existe a funo outrafuncao no mdulo circulos.

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
70
Outra forma de usar as funes importa-las diretamente, em vez de
importar o mdulo que as contm. Para evitar problemas, abra outra janela do IDLE. A
forma agora :

from mdulo import funo1, funo2, ...

Se usarei as funes potencia e nada,

>>> from circulos import potencia,nada
>>> potencia(2,3)
8
>>> potencia(3)
9
>>> print potencia.__doc__
potencia(x,y) eleva x a potencia y.
Default: y=2.

>>> nada()

Usando a sintaxe

from modulo import *

so importadas todas as funes do mdulo.
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
71
>>> from circulos import *
>>> perimetro(4.2)
26.376000000000001
>>> area(-1.)
3.1400000000000001
>>> print area.__doc__
Esta funcao calcula a area de
um circulo de raio r.

Uma das preciosidades de Python que esta linguagem possui milhares de
mdulos para resolver muitos dos seus problemas. Por isso em Python deve-se ter
cuidado para no "reinventar a roda, isto , talvez voc perca um tempo precioso
para desenvolver um programa que faa algo quando j existe um mdulo pronto que
o faa. Antes de comear a escrever seu script, se voc suspeitar que algum talvez j
tenha feito algo parecido, procure no Google - ele seu amigo! (Nosso amigo: o
Google escrito em Python!).
Nas funes perimetro e area acima, usamos o valor aproximado de pi, 3.14.
O valor preciso de pi uma das coisas que pode ser obtido do mdulo nativo math:

>>> import math
>>> pi

Traceback (most recent call last):
File "<pyshell#1>", line 1, in -toplevel-
pi
NameError: name 'pi' is not defined
>>> math.pi
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
72
3.1415926535897931
>>> from math import pi
>>> pi
3.1415926535897931

Assim como as principais relaes matemticas:

>>> from math import sin,cos
>>> sin(pi)
1.2246063538223773e-016
>>> cos(pi)
-1.0
>>> sin(cos(sin(pi)))
0.8414709848078965
>>> from math import *
>>> log(1) # o log usado aqui o logaritmo neperiano (base e)
0.0
>>> log10(2) # log10, por sua vez, o logaritmo de base 10.
0.3010299956639812
>>> pow(2,4)
16.0
>>> print pow.__doc__
pow(x,y)

Return x**y (x to the power of y).
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
73
Tambm h um similar cmath muito eficiente para trabalhar com nmeros
complexos, e diversos outros. No endereo http://docs.python.org/modindex.html
voc pode consultar a relao e descrio de todos os mdulos que j esto
disponveis quando voc instala o interpretador de Python. No incio deste captulo
usamos outro deles, o mdulo sys. Este mdulo contm uma funo path que retorna
uma lista contendo todos os diretrios do seu computador que esto no path. D uma
olhada novamente naquele pequeno cdigo da pgina 66 que agora voc entender
melhor.

5. Um pouco de teoria: Escopo

Em algumas ocasies, um programador pode, acidentalmente ou de
propsito, nomear seus objetos com nomes que j esto sendo usados ao longo do
programa. Neste caso, qual a hierarquia reconhecida pelo interpretador? Qual a
importncia do cuidado na definio de nomes?
A hierarquia reconhecida pelo interpretador (em ordem decrescente): locais
- globais - builtins, sendo locais os nomes definidos dentro de funes, classes e
mdulos, globais os nomes definidos ao longo do programa e builtins os nomes j
utilizados nativamente por Python.
Veja um caso simples:

>>> x=1000
>>> def f(x):
return x**2
>>> x
1000
>>> f(9)
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
74
81
>>> x
1000

O nome x definido na primeira linha do script global, enquanto o x dentro da
funo f local. Quando executamos f(argumento1), o interpretador tem que lidar com
dois valores associados ao mesmo nome x: argumento1 e 1000. Qual deles o
interpretador escolher vai depender da hierarquia. Neste caso, o nome x =
argumento1 local (definido dentro da funo), enquanto x = 1000 global (definido
ao longo do script). A hierarquia faz com que o interpretador reconhea argumento1
como sendo o valor associado ao nome x naquele momento e faz finalmente
(argumento1)**2. Depois disso, o usurio consulta o valor de x. Agora s existe o
valor global de x definido, que vale 1000.
Outro exemplo, agora com nomes builtins:

>>> type(12)
<type 'int'>
>>> def type(m):
print 'Digitastes',m

>>> type(12)
Digitastes 12
>>> def tipologia(x):
def type(y):
print 'Voc digitou',y
type(x)

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
75
>>> tipologia(12)
Voc digitou 12
>>> type(12)
Digitastes 12

Aqui, tnhamos o objeto builtin type, que nos retorna o tipo do objeto
fornecido como argumento. Definimos globalmente uma nova funo type que executa
um procedimento diferente e, dentro da funo tipologia (quer dizer, localmente), este
nome foi redefinido para um terceiro procedimento, que s vale no escopo da funo.
Ao usar a funo tipologia, sua funo interna type no se torna global. Globalmente,
continua valendo a type que imprime "Digitastes tal, em sobreposio builtin de
mesmo nome.
Sempre que aparece algum nome no programa que no foi definido
localmente, o interpretador procura por ele entre os nomes globais. Se ele tambm
no foi definido globalmente, o ltimo local de busca entre os nomes builtins. S
ento informado o erro de que o nome no foi definido. Veja o exemplo. Dentro da
funo, usamos um nome global e um builtin, alm dos nomes locais (argumentos da
funo). Na segunda funo, usamos o nome no definido t, que gera um erro.
Observe a ltima linha da mensagem de erro - "O nome global 't' no definido.

>>> from math import pi
>>> r=2.3
>>> def area(incremento):
return pi*(r+incremento)**2

>>> area(.7)
28.274333882308138
>>> def volume(inc):
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
76
return (pi*(t+inc)**3)/3.

>>> volume(.4)

Traceback (most recent call last):
File "<pyshell#108>", line 1, in -toplevel-
volume(.4)
File "<pyshell#107>", line 2, in volume
return (pi*(t+inc)**3)/3.
NameError: global name 't' is not defined

Por outro lado - como j vimos, no possvel contar globalmente com os
nomes definidos localmente. A seguir, define-se um nome t dentro do escopo da
funo volume, que s existe localmente funo. Tentar acessar este nome
globalmente tambm d erro.

>>> def volume(inc):
t=0.6
return (pi*(t+inc)**3)/3.

>>> volume(.4)
1.0471975511965976
>>> t

Traceback (most recent call last):
File "<pyshell#112>", line 1, in -toplevel- t
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
77
NameError: name 't' is not defined

Se for necessrio tomar um nome local de uma funo para uso no restante
do script, possvel torn-lo global assim:

>>> def volume(inc):
global t
t=0.6
return (pi*(t+inc)**3)/3.

>>> volume(0.4)
1.0471975511965976
>>> t
0.59999999999999998

Deve-se usar este recurso com cautela e somente quando indispensvel.
Transformar nomes locais em globais pode gerar conflitos com os nomes globais e
builtins j existentes. Pelos mesmos motivos, evite usar a sintaxe

from modulo import *

para usar funes de qualquer mdulo, principalmente os que no foram criados por
voc. Os mdulos podem conter dezenas de funes e valores, inclusive com nomes
que voc desconhece, o que pode gerar conflitos com os nomes que voc definiu ao
longo do script. Imagine o caso hipottico do sujeito que resolve definir uma funo sin
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
78
(uma abreviao inocente de "sintaxe), e ao final do programa resolve calcular um
cosseno qualquer, importando para isso todo o pacote math.

>>> def sin(pronome):
print 'D-%s ajuda!' %pronome

>>> sin('lhe')
D-lhe ajuda!
>>> from math import *
>>> cos(pi)
-1.0
>>> sin('me')

Traceback (most recent call last):
File "<pyshell#131>", line 1, in -toplevel-
sin('me')
TypeError: a float is required

E assim se perde uma funo definida com tanto carinho... A perda da funo
sin poderia ser evitada se o usurio tivesse importado o mdulo math e usado a
sintaxe math.cos(math.pi) para calcular o cosseno de pi.







I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
79
Parte VII - Alguns truques...

1. Manipulao de arquivos

Sempre que o resultado da execuo de um programa for importante demais
para ser simplesmente impressa na tela, interessante salv-lo num arquivo. A funo
usada para abrir um arquivo open. A sintaxe utilizada por esta funo
open(endereo/nome_do_arquivo.extenso,modo_de_abertura). Os modos de
abertura so os seguintes:

r - abrir o arquivo somente para ler ("r de read, ler);
a - abrir o arquivo somente para escrever ("a de append, porque o texto
concatenado ao final do arquivo);
w - abre o arquivo somente para escrever ("w de write, escrever - sem concatenar).
Cuidado que este modo apaga o contedo anterior do arquivo! Por isso ele serve
tambm para criar um arquivo novo.

Para facilitar o trabalho com o arquivo, salvamos o resultado da funo open
sob um nome. Assim, ao trabalhar com o nome, estamos trabalhando com o resultado
da funo. Por exemplo, o mtodo close serve para fechar o arquivo. Assim,
abertura.close() o mesmo que open('c:/tabela.txt','w').close(), se
tivermos feito

>>> abertura=open('c:/tabela.txt','w')

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
80
Cuidado! Antes de executar a linha acima, v at sua pasta C: e verifique se
voc j no tem um arquivo chamado tabela.txt. Se tiver, seu contedo ser apagado
pelo cdigo anterior! Copie o arquivo para outra pasta.
V sua pasta C e veja: acabou de ser criado um arquivo tabela.txt. Para
fechar o arquivo, usa-se o mtodo close:

>>> abertura.close()

No se esquea: sempre que acabar de trabalhar com um arquivo, voc
precisa fecha-lo antes de fazer qualquer coisa com ele. Se no for fechado, o arquivo
continua como um objeto sendo usado por Python. Se voc tentar deletar o arquivo
tabela.txt antes de executar abertura.close(), seu sistema operacional dar uma
mensagem de violao de compartilhamento por causa disso. Se simplesmente abri-lo
sem ter executado close, no conseguir ver o que acabou de ser escrito nele.
Vamos digitar novamente a tabela de dlares, porm desta vez num arquivo
que poderemos usar vrias vezes, imprimir, mandar por e-mail, etc.

>>> abrindo=open('c:/tabela.txt','a')

Podemos abrir no modo append porque este arquivo agora j existe, no ?
Para escrever no arquivo aberto, usamos o mtodo write(s), sendo s uma string:

>>> abrindo.write('Tabela de dlares\n')

Usando os conceitos de formatao de strings fica assim:

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
81
>>> abrindo.write('%s\n' %'Tabela de dlares')

Isto serve ainda para reforar o que j vimos antes, que a formatao de
strings no se aplica somente aps um print, mas tambm em qualquer lugar onde
houver uma string. Dentro das funes write e raw_input, por exemplo. Ah! bom
lembrar que a string '\n' corresponde a pular uma linha.

Estranho... Abrindo o arquivo tabela.txt que est em
C:, no consigo ver o texto que acabei de escrever nele,
Tabela de dlares. Voc sabe o que aconteceu? A resposta
est na pgina anterior.

>>> abrindo.close()
>>> vamosdigitar=open('c:/tabela.txt','a')
>>> for i in range(100):
vamosdigitar.write('%i dlares valem %f reais\n' %(i,i*2.98))

>>> vamosdigitar.close()

D uma olhada do contedo do arquivo `tabela.txt em C:...
Usamos agora o modo r para ler o contedo de um arquivo.

>>> abertura=open('c:/tabela.txt','r')

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
82
H dois mtodos para ler o contedo do arquivo recm-aberto: readline l o
contedo do arquivo linha por linha. Quanto acabar o arquivo, retorna '', uma string
vazia.

>>> abertura.readline()
'Tabela de d\xf3lares0'
>>> abertura.readline()
'0 dlares valem 0.00 reais'
>>> abertura.close()

O outro mtodo, readlines, retorna todo o contedo do arquivo em uma lista;
cada termo da lista uma linha do arquivo. Readlines interessante porque gera uma
lista, com a qual j sabemos trabalhar muito bem.

>>> w=open('c:/tabela.txt','r')
>>> lst=w.readlines()
>>> print lst[0]
Tabela de dlares

>>> print lst[-1]
44 dlares valem 131.1

Voc pode escrever em diversos formatos alm de txt, mas alguns podem
apresentar formatao insatisfatria. Se voc escrever num arquivo do MsExcel, por
exemplo, todo o texto ser empacotado na primeira clula do arquivo.
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
83
Entre os formatos interessantes para se escrever, est o .bat, em que voc
pode escrever um cdigo de execuo do DOS, o .scr, em que voc pode escrever um
script de AutoCAD, como veremos adiante, etc.

2. Mdulo OS - Mexendo no Sistema Operacional

Que tal se, alm de escrever o resultado do seu programa num arquivo, aps
a execuo do seu programa o arquivo com os dados de sada fosse aberto para o
usurio? O mdulo os, especialmente desenvolvido para manipulaes no seu sistema
operacional, qualquer que seja ele, possui uma funo que faz isso: startfile.

>>> import os
>>> atalho=os.startfile
>>> atalho('c:/tabela.txt')

Na segunda linha, criamos o que chamamos de "alias - atribumos um
mdulo, mtodo(s) e/ou funes a um nome para facilitar sua utilizao. O que
escrevemos na terceira linha corresponde ento a os.startfile('c:/tabela.txt').
Se o arquivo for um executvel (como um .bat ou .exe por exemplo), o
aplicativo ser executado.
Outro mtodo interessante do mdulo os system. Este mtodo executa uma
string como se ela estivesse sendo digitada no prompt do MsDOS, ou na linha de
comando, se voc um usurio Linux.

>>> import os
>>> a=os.system
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
84
Voc tambm pode usar este recurso para abrir arquivos ou executar
programas:

>>> a('c:/tabela.txt')
0

E tambm pode usa-lo para causar problemas (cuidado!):

>>> a('format c:')

Deixando o terrorismo de lado, digamos que voc desenvolveu um programa
com vrios mdulos que devem ser copiados para a pasta C:/Python23, alguns
arquivos de dados em texto que devem ser copiados diretamente para C: e outros que
ficariam melhor se estivessem bem vista, em INICIAR > PROGRAMAS, por
exemplo, e salvou todos eles em um disquete para distribuir para seu cliente.
Neste exemplo, temos:

meumodulo.py - deve ser copiado para C:/Python23, seno no
funcionar;
meuprograma.py - o programa que supostamente vai usar o mdulo
meumodulo.py. Este programa dever ficar na pasta C:/Python-NOME, onde
"NOME o nome do seu cliente;
leiame.txt - deve ser aberto para o usurio depois da instalao dos
itens acima.

Crie estes arquivos num disquete. No importa o que eles faam; podem ser
arquivos vazios. Neste exemplo, importar somente o que faremos com eles.
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
85
Agora precisamos criar um novo programa (este com contedo) que instalar
todos os itens acima nos seus devidos lugares. Podemos chama-lo de "instalar, ou
"setup, algo assim:

#instalar.py
import os
comando=os.system
comando('copy a:\meumodulo.py c:\Python23')
NOME=raw_input('Seu nome: ') # Linha 4
NOME='Python-'+NOME
comando('md c:\''+NOME) # Linha 6
comando('copy a:\meuprograma.py c:\''+NOME)
abrir=os.startfile
abrir('a:/leiame.txt')

Cabe uma pequena explicao sobre a linha 6 do programa. O comando DOS
"md serve para criar um novo diretrio. Neste caso criamos um novo em C chamado
"Python-NOME; "NOME o valor informado pelo usurio na quarta linha do
programa.
Com os recursos que voc viu neste ltimo captulo, j d pra criar um
pequeno instalador, que espalha seus programas, mdulos e leia-mes nas pastas
adequadas, inclusive abrindo para o usurio os arquivos de instruo de uso.

Agora com voc! Escreva um 'desintalar.py que
apague todos os diretrios e programas que voc espalhou
pelo computador do cliente!
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
86
3. Time e Random

Voc pode inserir a hora certa ou calcular o tempo de execuo do seu
programa com o mdulo time. O mtodo asctime mostra a data e hora locais como
uma string, enquanto localtime mostra esta informao em forma de tupla.

>>> import time
>>> time.asctime()
'Thu May 20 11:35:40 2004'
>>> time.localtime()
(2004, 5, 20, 11, 36, 45, 3, 141, 0)

J temos certo traquejo com endereamento, ento podemos, entre outras
coisas, fazer:

>>> salve=time.localtime()
>>> print 'Hoje ',salve[2],'do',salve[1],'de',salve[0]
Hoje 20 do 5 de 2004

J o mtodo time mostra o tempo em segundos a partir de uma referncia
meio estranha, no muito legvel para ns, terrqueos, mas interessante quanto
trabalhamos com ele para medir variaes de tempo. Para medir quanto tempo
demorou a execuo do seu programa, voc pode salvar o tempo inicial nas primeiras
linhas de cdigo com

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
87
>>> from time import time
>>> t0=time()

e ao final do programa,

>>> print 'A execuo durou', time()-t0, 'segundos'
A execuo durou 50.6560001373 segundos

O mdulo random pode ser til para fazer jogos e sorteios diversos. Dois
mtodos muito interessantes so choice e random. O primeiro sorteia um elemento de
uma seqncia, enquanto o segundo escolhe um nmero aleatrio entre 0 e 1.

>>> import random
>>> sorteio=random.choice
>>> a=[]
>>> for i in range(10):
a.append(raw_input('Nome dos candidatos: '))

Nome dos candidatos: Woiski
Nome dos candidatos: Barata
Nome dos candidatos: Labaki
Nome dos candidatos: Bestinha
Nome dos candidatos: Osvaldo
Nome dos candidatos: Fred
Nome dos candidatos: Thiago
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
88
>>> a
['Woiski', 'Barata', 'Labaki', 'Bestinha', 'Osvaldo', 'Fred', 'Thiago']
>>> sorteio(a)
'Fred'
>>> sorteio(a)
'Ricardo'
>>> sorteio(a)
'Labaki'

Estou com sorte hoje...
Vejamos o mtodo random. O resultado gerado ( [0,1]) pode ser
trabalhado normalmente - multiplicado por um inteiro, transformado em inteiro, etc.:

>>> import random
>>> num=random.random
>>> num()
0.8077947641664176
>>> num()
0.23901444156442075
>>> int(100*num())
43
>>> for i in range(5):
print int(10*num()),

0 5 3 9 4
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
89
4. Python e AutoCAD: bons amigos

H um recurso interessante do AutoCAD - a execuo de scripts - que
permite que voc crie um cdigo simples num arquivo e execute uma srie de
comandos de uma vez. O arquivo precisa ter extenso .scr e conter os comandos do
AutoCAD como se voc os estivesse digitando na linha de comandos do programa.
Assim, o script abaixo desenha um quadrado. Digite este cdigo no bloco de notas e
salve-o como .scr, v ao AutoCAD em Tools > Run Script..., procure por este arquivo
onde voc o salvou e confirme OK.

Line
0,0
10,0
10,10
0,10
0,0


Por falta de algo mais representativo, uso o smbolo para representar linha
em branco. Se voc no der esta linha em branco no seu script, ao terminar o desenho
do quadrado, a linha vai continuar espera do prximo ponto. Por outro lado,
inserindo uma linha em branco a mais, como se voc estivesse dado outro ENTER na
linha de comandos aps o trmino do desenho do quadrado, ou seja, chamou o
comando "line de novo.
Para ver melhor o quadrado, execute o Zoom Extents (ou simplesmente z
ENTER e ENTER).
Um script para fazer o mesmo desenho de maneira mais simples pode ser:
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
90
rectangle
0,0
10,10

necessrio que voc pressione ENTER aps "10,10. como se estivesse
pressionando ENTER na linha de comandos para confirmar este ponto final do
retngulo.
J imaginou como deve dar trabalho para desenvolver um script para
desenhar 50 quadrados "concntricos tendo cada um o dobro da rea de seu interno?
Voc teria que calcular o incremento de rea de cada um e converter isso em termos
de pontos coordenados; o script ficaria imenso.
A entra nosso bom e velho Python: j sabemos como escrever o resultado de
um programa num arquivo, inclusive .scr. Basta ento desenvolver um programa que
calcule os pontos dos retngulos e escreva o script para ns.
Uma das solues o programa abaixo:

#retangulos.py
import math
raiz=math.sqrt
A=float(raw_input('Area inicial: '))
w=open('c:/nosso_script.scr','w')
for i in range(1,51):
a=raiz(A)
w.write('rectangle\n')
pontoi=str(-a/2)+','+str(-a/2)+'\n'
pontof=str(a/2)+','+str(a/2)+'\n'
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
91
w.write(pontoi)
w.write(pontof)
A=2*A
w.write('Zoom\n')
w.write('Extents\n')
w.close()

Analisemos o programa:
Linha 4: assim criamos o arquivo nosso_script.scr em C:.
Linha 6: "a o comprimento da aresta do quadrado, igual raiz quadrada da
sua rea. A rea do quadrado inicial informada pelo usurio.
Linha 7: escrevemos o comando a ser interpretado pelo AutoCAD, "rectangle
e pulamos uma linha.
Linha 8: escrevemos o ponto inicial do retngulo. A funo str transforma -
a/2 em uma string. Concatenamos a vrgula a essa string, concatenamos a
coordenada y do ponto inicial, e concatenamos por fim o caracter para pular
uma linha (`\n). Faa um teste interativo usando o IDLE que voc entender
melhor. Para uma rea inicial (A) igual a 20, a string resultante :
'-2.2360679775,-2.2360679775\n'
Linha 9: escrevemos o ponto final da mesma forma, porm as coordenadas
agora so (a/2,a/2).
Linha 10: escrevemos o ponto inicial do retngulo no arquivo (j com o
comando para pular linha) e
Linha 11: a mesma coisa com o ponto final.
Linha 12: Duplicamos a rea para que no prximo item da varredura for o
retngulo desenhado tenha o dobro da rea.
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
92
Linha 13 e 14: Nestas linhas, ajustamos os retngulos desenhados tela,
para facilitar sua visualizao.

Reescreva o programa para desenhar crculos
concntricos. Tente faze-los com o dobro da rea do
anterior, depois com o dobro do raio.

5. Msica, maestro!

T certo, no l um concerto sinfnico, mas seria interessante inserir uns
sons do PC nos programas, no ?
O mdulo winsound, e o mtodo, Beep(freqncia,durao), sendo
freqncia a freqncia do som, em Hertz, no intervalo 37 - 32767, e a durao em
milissegundos. Ambos os parmetros devem ser nmeros inteiros.

>>> import winsound
>>> b=winsound.Beep
>>> b(1000,1000)
>>> b(500,500)

Ouviu?
Pode ser til a funo sleep(s) do mdulo time, que d uma pausa de s
segundos no programa. Para uma volta nostlgica aos tempos de SuperNintendo,

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
93
>>> import time
>>> s=time.sleep
>>> for i in range(1,5):
for j in range(1,5):
b(100*j*i,50)
s(0.01)
s(0.01)

Que tipo de erro ocorrer se em vez de range(1,5)
colocssemos range(4)? Tente descobrir sem executar o
cdigo.

6. Calendar

E para trabalhar com datas, o mdulo calendar mais eficiente que o time. O
mtodo isleap(y), por exemplo, testa se o ano y bissexto
4
:

>>> import calendar
>>> calendar.isleap(2004)
True
>>> calendar.isleap(2055)
False

4
Leap year: Ano Bissexto.
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
94
O mtodo monthrange(x,y) retorna uma tupla contendo em que dia da
semana (segunda-feira=1, tera-feira=2, etc.) comea o ms y do ano x e quantos
dias tem esse ms.

>>> calendar.monthrange(2004,5)
(5, 31)

E um muito til, prmonth(x,y), que imprime de forma bem comportada o
calendrio do ms y do ano x. Para voc no se esquecer de quando aconteceu a
Semana de Arte Moderna, a vai:

>>> calendar.prmonth(1922,2)
February 1922
Mo Tu We Th Fr Sa Su
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28





I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
95
Parte VIII - Exemplos
5



Tente entender como estes programas funcionam, implementando-os se
necessrio. Tente tambm sugerir melhorias nestes cdigos de forma a torn-los mais
eficientes. H comentrios oportunos sobre algumas linhas mais interessantes.

10.1. numanalise.py - Trabalhando com funes

Este programinha recebe um nmero inteiro do usurio e faz uma anlise
completa sobre ele: testa se par ou mpar, se primo ou no, se perfeito ou no,
imprime seus divisores e de quebra calcula qual a soma dos seus algarismos. Ele foi
desenvolvido com base em funes, embora no fora necessrio.

def testa_par(x):
if x % 2 == 0:
print x,' um nmero par'
else:
print x,' um nmero mpar'

def testa_primo(valor):
teste=0
for individuo in range(2,valor):
if valor % individuo == 0:

5
No perca tempo digitando estes exemplos: eles esto disponveis para download em http://labaki.tk
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
96
teste=teste+1
if teste <> 0:
print valor,'no primo'
else:
print valor,' primo'

def testa_perfeito(gretagarbo):
verifica=1
for qualquerum in range(1,gretagarbo):
if gretagarbo % qualquerum == 0:
verifica=verifica+qualquerum
if verifica == gretagarbo:
print gretagarbo,' perfeito'
else:
print gretagarbo,'no perfeito'

def procura_divisores(n):
lista_de_divisores=[]
for i in range(1,n):
if n % i == 0:
lista_de_divisores.append(i)
if len(lista_de_divisores)==0:
print n,'No tem divisores'
else:
print 'Divisores de',n,':'
for i in lista_de_divisores:
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
97
print i,
def soma_algarismos(n):
n=str(n)
while len(n)>1:
m=0
for i in n:
m=m+int(i)
n=str(m)
print n

n=int(raw_input('Digite o nmero a ser analisado: '))
testa_par(n)
testa_primo(n)
testa_perfeito(n)
procura_divisores(n)
soma_algarismos(n)

Alguns comentrios sobre a funo soma_algarismos: na primeira linha da
funo, transformamos n em uma string porque mais simples somar os termos de
uma seqncia. At que n tenha somente um algarismo (while len(n) > 1),
somamos os termos da string n (quarta e quinta linhas da funo) e salvamos esta
soma novamente no nome n.

necessrio encapsular o programa inteiro dentro de
um while 1: para que sejam testados vrios nmeros
diferentes?
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
98
10.2. catch_mail.py - Trabalhando com strings

Este programa serve tambm para mostrar como fcil a vida de um
spammer com milhares de colaboradores que mandam e-mail para todos seus amigos
no campo "Para: e no em "Cco:, ou encaminham mensagens empacotando para o
destinatrio uma leva enorme de endereos de e-mail. Este programa recebe um texto
do usurio e recolhe dele todos os endereos de e-mail, imprimindo-os na tela j no
formato certinho para que voc recorte e cole no seu programa de mensagens e
mande algo para todos eles. Uma cpia destes endereos tambm adicionada a um
arquivo mailcollection.txt em C: para que voc v colecionando os endereos que
conseguiu com a execuo deste programa.

try:
w=open('c:/mailcollection.txt','a')
except:
w=open('c:/mailcollection.txt','w')
lista=raw_input('Mail: ')
lista=lista.split()
for i in range(len(lista)):
lista[i]=lista[i].replace('<','').replace('>','').replace(',','')
mail=[]
for i in range(len(lista)):
if lista[i].__contains__('@'):
mail.append(lista[i])
for i in range(len(mail)):
mail[i]=mail[i]+','
print 'Enderecos capturados:\n'
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
99
for i in mail:
print i,
w.write(i)
w.close()

Teste o programa: escolha algum e-mail que voc recebeu encaminhado
(aqueles com subject repleto de Fwd, Re, etc.), pressione CTRL+A no seu navegador
para selecionar tudo e CTRL+C para copiar e cole isto quando o programa pedir
"Mail:. Viu s quantos endereos so capturados?
Valem alguns comentrios: o bloco de try tenta abrir o arquivo
mailcollection.txt, que estar em C: se voc j usou este programa alguma vez. Se der
errado (dar, se o arquivo ainda no existir), ento um novo arquivo com este nome
criado.
Na sexta linha vemos um mtodo de strings, split(w), que serve para separar
uma string nos caracteres w e colocar os termos separados numa lista. O caracter w
o espao em branco por default.

>>> 'araraquara'.split('a')
['', 'r', 'r', 'qu', 'r', '']

Assim cortamos a string `araraquara em todos os caracteres `a que
aparecem, e colocamos os termos separados em uma lista.

>>> a='Boa tarde!'
>>> a.split()
['Boa', 'tarde!']

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
100
J na oitava linha usamos o mtodo a.replace(b,c) que substitui todos os
valores `b da string a por `c:

>>> a='Boa tarde!'
>>> a.replace('Boa','Pssima')
'P\xe9ssima tarde!'

Finalmente, na linha 11 aparece sequencia1.__contains__(termo1). Contains
serve para verificar se h termo1 em sequencia1.

>>> a='Good Night Vietnam'
>>> a.__contains__('Vie')
True
>>> a.split().__contains__('Vie')
False
>>> a.split()
['Good', 'Night', 'Vietnam']
>>> a.split().__contains__('Vietnam')
True

10.3. matrizes.py - Cadeias de for e listas

Este programa l uma matriz de ordem n pedindo qual termo o usurio deve
inserir (Termo a11, Termo a12, ..., Termo ann) e a imprime na tela de forma
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
101
comportada - as colunas alinhadas, as linhas espaadas, mesmo nmero de casas
decimais dos valores, etc.

ordem=int(raw_input('Ordem da matriz: '))
matriz=[]
print 'Digite os termos da matriz A'
for i in range(ordem):
matriz.append([])
for j in range(ordem):
termo='A'+str(i+1)+str(j+1)
matriz[i].append(float(raw_input('Termo'+termo+': ')))
print '\n'
print 'Matriz A\n'
for k in range(ordem):
for w in range(ordem):
print '%7.2f' %matriz[k][w],
print '\n'

Neste programa temos um bloco de for dentro de outro. Para cada valor de i,
for i insere na lista matriz uma linha vazia (na verdade, uma lista vazia). O for j
(que executado para cada valor de i por causa da indentao!) adiciona os n termos
a esta linha e o for i ainda imprime uma linha em branco (o print '\n' tambm
est indentado sob o for i). J a linha print 'Matriz A\n' no ser impressa para
cada valor de i porque no est mais na indentao de for.
A indentao tambm acontece no ltimo bloco de for. As trs ltimas linhas
do programa so executadas para cada valor de k: o bloco de for w imprime uma
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
102
linha da matriz (fixa o valor de k e varia w de 0 a ordem-1). Ento terminado o for
w, uma linha em branco impressa e o processo se repete para o prximo valor de k.

10.4. morse_code.py - Dicionrios e sons

Mais um exemplo interessante. Tente descobrir o que ele faz.

from winsound import Beep
from time import sleep
print 'Escolha a velocidade de traduo'
print 'Rpido (1)'
print 'Lento (2)'
if int(raw_input('Velocidade: '))==1:
vel=0.4
else:
vel=1
texto=raw_input('Texto a ser traduzido (minsculas, sem acentos): ')
morse={'m': '--', ',': '--..--', '.': '.-.-.-', '1': '.----', '0': '-----
', '3': '...--', '2': '..---', '5': '.....', '4': '....-', '7': '--...',
'6': '-....', '9': '----.', '8': '---..', '?': '..--..', 'a': '.-', 'c':
'-.-.', 'b': '-...', 'e': '.', 'd': '-..', 'g': '--.', 'f': '..-.', 'i':
'..', 'h': '....', 'k': '-.-', 'j': '.---', 'l': '.-..', 'o': '---', 'n':
'-.', 'q': '--.-', 'p': '.--.', 's': '...', 'r': '.-.', 'u': '..-', 't':
'-', 'w': '.--', 'v': '...-', 'y': '-.--', 'x': '-..-', 'z': '--..', '
':'\n'}
for i in texto:
print i,morse[i]
for j in range(len(morse[i])):
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
103
if morse[i][j]=='.':
Beep(500,50*vel)
sleep(0.1*vel)
elif morse[i][j]=='-':
Beep(500,150*vel)
sleep(0.1*vel)
else:
sleep(0.3*vel)
sleep(0.3*vel)

Conseguiu descobrir? Este programa um gerador de cdigo Morse. Ele
traduz o texto do usurio para traos e pontos, e tambm toca a traduo. O
processamento de verdade est todo neste bloco de for. Toda a parte anterior, que
ocupa mais da metade do programa, s pr-processamento, quando recebemos os
dados do usurio e informamos ao programa o dicionrio morse, que o alfabeto
Morse retirado do site WikiPedia.
O primeiro for varre a string informada pelo usurio e executa os
procedimentos indentados debaixo dele para cada letra dessa string. O primeiro
procedimento imprimir esta letra (representada por i) e o valor associado chave i
no dicionrio morse. Por exemplo, se o texto do usurio amerindio, o primeiro valor
assumido por i "a. Ento ser impresso "a e morse[`a], que vale ".-" (veja o
dicionrio). O bloco for j varrer o valor associado chave i transformando pontos (.)
em sons curtos e hfens (-) em sons com o triplo da durao, todos eles com 500 Hz. A
ltima linha, sleep(0.3*vel), uma pausa de 0.3*vel segundos dada ao final do
bloco de for j, ou seja, entre uma letra e outra do texto. O else do bloco de if
identifica os valores do dicionrio que no so nem pontos nem hfens (os espaos) e
tambm d a mesma pausa que dada entre uma letra e outra. Certamente mais
fcil entender o cdigo olhando pra ele do que lendo este pargrafo... , comparado
com Python, at o Portugus difcil!

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
104
10.5. newton-raphson.py - Escrevendo em arquivos

Eis um programa simples para encontrarmos a raiz de uma funo qualquer
tendo como dados de entrada a funo, sua derivada e um ponto inicial. Como sada,
aberto um arquivo com os resultados das 10 iteraes e outros dados numa forma
elegante, pronta para ser impressa, alm de um script para plotar no AutoCAD um
esboo da funo, em vermelho.
Esta uma implementao simples do Mtodo Iterativo de Newton-Raphson.
Voltando um pouco ao Clculo Numrico, uma aproximao da raiz da funo, dada
pela iterao n+1 calculada por Newton-Raphson pela frmula:
) ( '
) (
1
n
k
k k
x f
x f
x x =
+


from math import *
from os import startfile
from time import time,localtime

print 'Operadores especiais disponveis:'
print 'sin, cos, log (neperiano),'
print 'log10 (base 10), e sqrt (raiz quadrada).\n'
funcao=raw_input('Funo: ')
derivada=raw_input('Derivada: ')
x0=float(raw_input('Valor inicial: '))

t0=time()

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
105
Aqui comea o processamento de verdade, por isso imediatamente antes
marcamos o tempo para conferir depois quanto tempo levou a resoluo do problema.

f='x-(('+funcao+')/('+derivada+'))'

Esta string f contm a equao geral de Newton-Raphson, j mostrada.

w=open('c:/newton-raphson.txt','w')
w.write(' Newton-Raphson\n\n')

if localtime()[3]<=12:
w.write(' Bom dia!\n\n')
elif 12<localtime()[3]<18:
w.write(' Boa tarde!\n\n')
else:
w.write(' Boa noite!\n\n')

As linhas anteriores abrem o arquivo newton-raphson.txt em C:, que conter
os nossos dados de sada, e escreve nele o ttulo e um pequeno cumprimento ao
usurio. Voc se lembra, o mtodo localtime() retorna uma tupla, cujo endereo 3
contm a hora local.

w.write('Procedimentos para encontrar a raiz de '+funcao+'\n\n')
w.write('Valor inicial: '+str(x0)+'\n\n')
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
106
Aqui escrevemos com que funo estamos trabalhando e tambm o valor
inicial escolhido. Como x0 um float, precisamos transforma-lo numa string antes de
concatena-lo string "Valor inicial: e por fim string '\n\n' (duas linhas em
branco).

x=x0
for p in range(10):
w.write('Iterao '+str(p+1)+':\n')
x=eval(f)
w.write(str(x)+'\n')
w.write('\n')

E assim escrevemos os valores obtidos em 10 iteraes sobre a equao de
Newton-Raphson. A funo eval(f) avalia a string f desde que ela contenha o termo "x
e se anteriormente tivermos definido um valor para x. Veja um exemplo (as prximas
cinco linhas no fazem parte do programa newton-raphson!):

>>> string='2+a+b'
>>> a=1
>>> b=5
>>> eval(string)
8

Continuando o programa...
O valor atual de x corresponde a x
10
obtido pelo Mtodo e um float. Se
quisermos escreve-lo no arquivo, devemos transforma-lo tambm em string. Perceba
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
107
que sempre somamos '\n' ao final das strings usadas pelo mtodo write. Se no
fizermos isso, o prximo texto ser empilhado ao final deste e o arquivo ficar ilegvel.

w.write('Valor aproximado da raiz: '+str(x)+'\n\n')

E como time() retorna o tempo atual, time()-t0 nos dar o tempo decorrido
deste que definimos t0:

w.write('Tempo para clculos: '+str(time()-t0)+'\n')

No h mais nada para escrevermos no arquivo, ento o fechamos usando o
mtodo close(), e o abrimos para o usurio usando startfile.

w.close()
startfile('c:/newton-raphson.txt')

Faamos o script para plotar o grfico da funo. Para facilitar sua busca pelo
script, j salvaremos este arquivo na pasta que aberta por default quando voc
executa Run Script no AutoCAD. Se voc estiver usando uma verso do AutoCAD ou do
Windows que no seja a 2000, pode haver pequenas variaes neste endereo.

t=open('c:/Arquivos de Programas/ACAD2000/graficos.scr','w')

J que a funo range s gera uma lista de inteiros, criamos uma nova funo
arange que gera uma lista de floats, por motivos que veremos adiante.
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
108
def arange(xi,xf,i):
a=[]
while xi<=xf:
a.append(xi)
xi=xi+i
return a

O script `color serve para mudar a cor usada pelo AutoCAD. A cor 20, por
exemplo, o vermelho.

t.write('color\n')
t.write('20\n')

Escrevemos ento o comando que desenhar o grfico, e logo depois os
pontos que a linha ter que percorrer, exatamente (x,f(x)), para x variando do valor
aproximado da raiz at o valor inicial x0. Depois um Zoom e pronto!

t.write('line\n')
funcao=funcao.replace('x','elemento')
for elemento in arange(x,x0,0.1):
t.write(str(elemento)+','+str(eval(funcao))+'\n')
t.write('\n')
t.write('Zoom\n')
t.write('Extents\n')
t.close()
I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
109
Aps executar o programa, no AutoCAD v a Tools > Run Script e execute
graficos.scr.

10.6. memoria.py - Um joguinho simples de memria

Este programa sorteia um nmero entre 0 e 9. O usurio tem que informar
todos os nmeros que o programa escolheu at o momento, sem errar nenhum da
seqncia. Um jogo-exemplo:

Programa: 0
Jogador: 0
Programa: 4
Jogador: 04
Programa: 7
Jogador: 047
Programa: 3
Jogador: 0453 - Errou!

import random
r=random.random
print 'Memoria\n'
print 'Nao joque usando IDLE\n'
print 'Digite todos os numeros que forem'
print 'informados pelo programa'

Aqui comea o processamento. O objeto "escolha um inteiro entre 0 e 9.

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
110
escolha=int(10*r())
print escolha
a=str(escolha)
user=str(int(raw_input('Tente: ')))

Aps receber a primeira tentativa do usurio, o programa testa se ele acertou
e comea o jogo de memria at que o jogador erre.

while user==a:
escolha=int(10*r())
print escolha
a=a+str(escolha)
user=str(int(raw_input('Tente: ')))
print '\n'*100

A linha print '\n'*100 imprime 100 linhas em branco que limpam a tela de
forma que o usurio no consegue ver as escolhas feitas anteriormente pelo jogo.
Assim, ter que recorrer memria mesmo. por isso que este jogo no pode ser
executado no IDLE, porque rolando a tela o jogador poderia ver os nmeros sorteados
anteriormente.
Se a condio do while no for mais satisfeita, quer dizer que a ltima
resposta dada pelo usurio tem ao menos um termo no correspondente srie de
nmeros que o computador escolheu at o momento, ou seja,

print 'Voce perdeu!'

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
111
E o usurio pode saber quanto foi seu ltimo acerto:

print 'Seu saldo:',len(a)

Como este programa ser rodado no prompt do DOS e no pelo IDLE, assim
que terminar toda a impresso anterior a janela ser fechada, e o usurio no saber
seu saldo. Assim, para manter a janela aberta podemos fazer

raw_input('Pressione ENTER para sair')


Parte IX - Exerccios

Fceis Mdios
Por que no exemplo numanalise, a funo testa_primo faz uma varredura
sobre range(2,...) e testa_perfeito faz uma varredura sobre range(1,...)? Por
que ambas no fazem os testes sobre range(x), por exemplo?
Aproveitando os recursos do mdulo calendar, desenvolva um programa para
calcular quantos dias de vida um usurio est completando hoje, se informado
o dia de nascimento.
Em vez de imprimir nmeros, modifique o exemplo memoria para tocar o
nmero sorteado. Se o computador escolher 4, sero tocados 4 bips, e assim
por diante. E o usurio continua informando nmeros. Faa tambm com que
seja salvo um ranking de jogadores num arquivo de texto e com que o jogador
seja informado sempre que bater um recorde. Melhor ainda se o recorde for
acompanhado com msica (veja o som da pg. 53).


I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
112
Desenvolva um banco de dados simples de forma que o usurio possa inserir
um produto e seu preo, alm de poder consultar o preo de um produto, tudo
isso sem ter que acessar o arquivo de texto.
"Leitura instrumental a tcnica com a qual se pode compreender uma
leitura em um idioma desconhecido aprendendo apenas as palavras mais
utilizadas do idioma. O rol das palavras mais utilizadas feito por pesquisa em
centenas de livros famosos no idioma, que obviamente no feita
manualmente. Desenvolva um programa que vasculhe a obra "Os Lusadas e
retorne um arquivo com o ranking das 200 palavras mais utilizadas neste
livro. Voc pode encontrar um e-book de "Os Lusadas facilmente na internet.
Tente prever que resultados sero gerados pelo seguinte script, sem execut-
lo:

x, y = 5, 3
print x
print y
def one():
x = 1
print x
two(x)
print x
def two(y):
print y
y = 2
print y
z = one
y = z()
print x
print y

I N T R O D U O A P Y T H O N - M D U L O A
B E M- V I N D O A P Y T H O N !

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
113
Vem a...


Como dissemos na primeira parte deste mdulo, Python uma linguagem
orientada a objetos, mas que permite a programao procedural. O que voc viu at
agora a parte mais bsica, em que Python se assemelha um pouco s outras
linguagens de script. agora, no Mdulo B - Python Orientado a Objetos, que vem o
pulo do gato. Principalmente se voc j programa usando este paradigma, vai se
surpreender com a facilidade com que a nossa linguagem (agora sua tambm!) se
integra com a Orientao a Objetos (OO). Programar orientado a objetos, em Python,
como respirar!
Quando seus projetos comearem a tomar grandes propores, a OO
importante para garantir a estabilidade e facilidade de manuteno do cdigo, por
exemplo. A OO tambm evita as montanhas de variveis globais que causam conflitos
como os que vimos na nossa discusso sobre escopo.
No prximo mdulo voc tambm entender o que significam aquelas
sintaxes do tipo modulo.funo, lista.append, string.split, etc.
E finalmente, a Orientao a Objetos ser uma introduo indispensvel para
o Mdulo C - a to esperada programao de interfaces grficas.
Nos vemos no Mdulo B!
Sua participao muito importante para a constante
melhoria deste material. Ficarei muito honrado em
conhecer suas opinies, sugestes, crticas ou dvidas
sobre ele. Para isso, posso ser encontrado em
labaki@feis.unesp.br.
Agradeo a todos que j colaboraram, em especial ao Prof.
E. R. Woiski, Ph.D, pelas observaes e a toda a lista
python-brasil por diversas mensagens que ajudaram a
melhorar muitos pontos ao longo do texto.

J. Labaki
labaki@feis.unesp.br
http://labaki.tk
Este documento pode ser distribudo livremente, desde que mantidos os crditos do autor.
C Cr ru up po o P Py yt th ho on n a ap pr re es se en nt ta a: :
I In nt tr ro od du u o o a a P Py yt th ho on n - - h h d du uI Io o



























J Jo os su u L La ab ba ak kI I E E. . P P. . W Wo oI Is sk kI I
I Ia ab ba ak kI It tu ur rb bo o@ @g gm ma aI II I. .c co om m w wo oI Is sk kI I@ @d de em m. .f fe eI Is s. .u un ne es sp p. .b br r






UNESP - ILHA SDLTEIPA
UNIVERSIDADE ESTADUAL PAULISTA
JLI O DE MESQUI TA FI LHO
I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
2
Apresentao

Este material foi desenvolvido para apoiar os cursos da srie "Introduo
a Python" ministrados pelo Grupo Python para nossos mais diversos tipos de
audincia. O guia inteiro composto por trs volumes que correspondem aos mdulos
dados nos nossos cursos: Mdulo A - Bem-vindo a Python!, Mdulo B - Python
Orientado a Objetos e Mdulo C - Tkinter. Todos eles podem ser encontrados na
internet, nas pginas do Grupo Python (http://grupopython.cjb.net), na pgina do
autor (http://labaki.tk) e na pgina da comunidade Python no Brasil
(http://www.python-brasil.com.br).
Desenvolvemos este guia pensando tambm nos autodidatas que no
participaram dos nossos cursos e baixaram este material da internet. Se voc est
nesta situao, pode tirar dvidas por e-mail.
Lembramos que o nosso objetivo no ensinar programao, e sim guiar
voc nos passos bsicos em Python. Se sua inteno aprender a programar, prefira o
excelente material do prof. Luciano Ramalho em (http://www.magnet.com.br).
Recomendamos que voc acompanhe e implemente os exemplos, tente
entender os erros que podem ocorrer e tente resolver as questes que eventualmente
aparecem ao longo deste material. Ao final, h alguns exemplos e exerccios de
fixao.
Mande suas dvidas, sugestes, crticas ou comentrios por e-mail! Sua
opinio sobre o guia muito importante para ns.

Josu Labaki & Emanuel R. Woiski
Grupo Python
Departamento de Engenharia Mecnica
UNESP - Campus de Ilha Solteira
labakiturbo@gmail.com
woiski@dem.feis.unesp.br
I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
3



ndice

Parte I - Python Orientado a Objetos 4
1.Habemus OO! 4
2.Primeira tentativa: usando desenhos. 5
3.Segunda tentativa: exemplos do mundo real. 6
4.Terceira tentativa: OO no cdigo. 7
5.Quarta tentativa: O que OO afinal? 8
Parte II - Classe: o Objeto Elementar 9
1.Sintaxe. 9
2.Atributos e mtodos. 14
3.O mtodo especial __init__. 19
4.Os atributos especiais __doc__ e __module__. 22
Parte III - Herana 25
Parte IV - Por Que Usar Classes 37
Parte V - Convenes sobre Nomes 41
Parte VI - Exerccios 41
Vem a... 43





I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
4
Parte I - Python Orientado a Objetos

1. Habemus
1
OO!

Voc se lembra da introduo do Mdulo A, quando dissemos que Python
uma linguagem Orientada a Objetos - um paradigma que facilita entre outras coisas o
controle sobre a estabilidade dos projetos quando eles comeam a tomar grandes
propores, etc?
L dissemos que, como a Orientao a Objetos (OO) ainda vista como um
paradigma de experts, resolveram possibilitar ao programador de Python tambm
programar de forma imperativa (procedural), se quisesse. Dessa forma, a curva de
aprendizado da linguagem fica bem suave; no necessrio que se comece a escrever
cdigo orientado a objetos logo de incio, como acontece com linguagens
exclusivamente OO. A forma imperativa de Python o que voc viu ao longo de todo
o mdulo anterior, que deve ter aprendido sem grandes problemas.
Agora veremos porque a OO permite desenvolver projetos mais estveis, de
manuteno mais fcil, mais reutilizveis, mais extensveis e mais compatveis. Este
mdulo tambm dar a base indispensvel para o desenvolvimento de interfaces
grficas com Tkinter (o Mdulo C do presente curso).
J adiantando: mais fcil programar orientado a objetos em Python do que
definir Orientao a Objetos. Mas prometemos que tentaremos...




1
Aluso clebre frase Habemus Papa!, proclamada por um cardeal na baslica de So Pedro (Vaticano)
sempre que um novo papa acaba de ser eleito.
I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
5
2. Primeira tentativa: usando desenhos.

Paradigmas so formas de enxergar o mundo, os problemas, a vida, um
cdigo de um programa. Sendo a Orientao a Objetos um paradigma de programao
(tal como a programao imperativa - ou Orientada a procedimentos), pode-se
encara-la como uma forma de pensar o seu projeto, deste a arquitetura at a
implementao.
O paradigma Orientado a Procedimentos a que voc est acostumado encara
o cdigo de maneira que os dados possuem um estado que compartilhado pelas
funes ou subrotinas que operam sobre eles, como simplificado na figura abaixo:

Neste fluxo de dados esto todas as variveis. Uma funo toma um conjunto
delas como argumento e retorna o resultado para o fluxo de dados, para ser usado por
outra funo ou simplesmente para ser visto pelo usurio.
J a Orientao a Objetos v o problema de outra forma. No existem funes
nem dados da forma mostrada acima, e sim objetos que se comunicam entre si por
meio de mensagens trocadas em suas interfaces, como na figura adiante. Cada objeto
responde s mensagens recebidas de uma maneira prpria, os chamados mtodos, de
acordo com procedimentos internos, a implementao, que s ele conhece. No
interessa ao objeto 2 a maneira como uma determinada mensagem foi tratada pelo
objeto 1 nem como ele fez para chegar resposta. Ele simplesmente recebe a
mensagem e cumpre seu papel de responder ao objeto 3. Note que os objetos podem
ser criados e destrudos a qualquer momento por fora do programa.
I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
6
Na programao imperativa, o usurio manipula os dados atravs de uma
seqncia de procedimentos que levam a um estado final dos dados. Na programao
orientada a objetos, o que interessa no o estado final dos dados, e sim o estado (e
a existncia ou no) dos objetos num dado momento.


3. Segunda tentativa: exemplos do mundo real.

Digamos que voc tenha que desenvolver um cdigo que faa a alimentao
em um zoolgico. Seu algoritmo procedural fica assim:
Procedimento 1: comprar uma banana;
Procedimento 2: aguardar meio-dia;
Procedimento 3: servir a banana.
Se suas variveis so macacos, timo. Macacos comem bananas e ao meio-
dia. No entanto, este cdigo no vale para todas as variveis do zoolgico, j que
elefantes no se contentam com somente uma banana, lees no comem bananas,
corujas no comem ao meio-dia, etc.
O mesmo algoritmo, agora orientado a objetos, poderia ficar assim:
I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
7
Mensagem: alimente-se!
Desta vez, cada objeto, que conhece seus atributos (se herbvoro,
carnvoro, se est com fome ou no) e mtodos (se prefere caar ou esperar a fruta
cair do p, se um animal noturno ou no), vai se virar para se alimentar do seu jeito,
seja como for (talvez alguns objetos comam uns aos outros...) ou se fosse uma pedra,
talvez emitisse uma exceo, j que pedras no se alimentam.
Outra forma de perceber o que orientao a objetos pensar em como seria
um programa para calcular o permetro de uma figura geomtrica plana usando os dois
paradigmas. Proceduralmente, talvez se pensasse em somar os lados da figura.
Isso funciona perfeitamente para qualquer figura geomtrica que tenha um nmero
finito de lados. O procedimento de somar os infinitos lados de um crculo, por exemplo,
geraria um erro ou no retornaria um resultado satisfatrio. Neste caso seria melhor
usar a frmula conhecida 2r. O mesmo programa orientado a objetos simplesmente
enviaria uma mensagem ao objeto figura geomtrica plana: Calcule seu permetro.
Os pentgonos irregulares somariam seus lados enquanto os crculos usariam a
frmula, e talvez os quadrados fizessem um bom uso do seu atributo de ter quatro
lados iguais para simplesmente multiplicar o comprimento de um lado por quatro...

4. Terceira tentativa: OO no cdigo.

Vamos colocar a mo na massa e escrever um cdigo que, a partir de um
valor b, calcule a raiz quadrada de b e salve o resultado em a. O cdigo procedural fica
assim:
a = sqrt(b)
Isto , aplique a funo sqrt tomando b como argumento e salve o resultado
na varivel a. Foi esta sintaxe que usamos no Mdulo A, a partir da funo sqrt do
mdulo math.
I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
8
Agora, usando orientao a objetos, surge uma nova forma totalmente
estranha. Ser que d pra calcular raiz quadrada desse jeito em Python?
a = b.sqrt()
O cdigo acima est dizendo: b aplica sobre si seu mtodo sqrt e retorna o
resultado para o objeto a. Esta sintaxe no soa familiar? Veja este trecho do Mdulo A:

>>> a='araraquara'
>>> a.split('a')
['', 'r', 'r', 'qu', 'r', '']

No cdigo acima, como em muitos outros em todo o mdulo anterior, voc
esteve usando orientao a objetos! Em particular neste exemplo, dissemos ao objeto
a, um objeto da classe (cuja definio veremos depois) das strings, para aplicar sobre
si o seu mtodo split, tendo como argumento 'a'. A resposta a esta mensagem a
lista ['', 'r', 'r', 'qu', 'r', ''].
Atravs de uma das nossas mais poderosas ferramentas de introspeco em
Python, a funo dir, podemos conhecer todos os atributos de um objeto da classe de
strings, como o objeto a:

>>> dir(a)
['__add__', '__class__', '__contains__', '__delattr__', '__doc__',
'__eq__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__',
'__getslice__', '__gt__', '__hash__', '__init__', '__le__', '__len__',
'__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__',
'__str__', 'capitalize', 'center', 'count', 'decode', 'encode',
'endswith', 'expandtabs', 'find', 'index', 'isalnum', 'isalpha',
'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust',
'lower', 'lstrip', 'replace', 'rfind', 'rindex', 'rjust', 'rstrip',
'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title',
'translate', 'upper', 'zfill']

I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
9
Use sempre a funo dir para conhecer os mtodos de um objeto. Com uma
simples checagem sobre o objeto a, descobrimos 62 mtodos cuja maioria voc
certamente desconhece, embora muitos deles possam ajuda-lo a economizar vrias
linhas de cdigo nos seus projetos. Aproveite a deixa e use o IDLE para descobrir
quantas manipulaes interessantes se pode fazer sobre uma string usando seus
mtodos!

5. Quarta tentativa: O que OO afinal?

Enfim, Orientao a Objetos um paradigma que considera que um programa
um grande e animado dilogo entre entidades chamadas objetos, produzidas e
destrudas a todo momento. Os objetos conhecem muito bem a si mesmos e
respondem s mensagens de acordo com seus atributos (suas caractersticas) e com
seus prprios mtodos.
Da voc j percebe como um cdigo orientado a objetos mais flexvel. Se
voc no gosta da reao de um objeto a uma mensagem, basta troc-lo por outro ou
corrigi-lo - somente o indivduo em questo; no necessrio reescrever o programa
todo.
Por esta introduo voc foi posto a par de algumas palavras-chave da OO,
como objetos, atributos, interfaces e mtodos. Na Parte II veremos na prtica o que
elas querem dizer.

Sejam dois objetos a='araraquara' e b=[1,2,3]. Quando fazemos
b.reverse(), o objeto b modificado (cheque isso!), mas se aplicarmos
por exemplo a.upper(), um valor retornado mas o objeto a no sofre
alteraes. Voc consegue se lembrar por que isso acontece? Isto ocorre
somente com upper e reverse ou mais mtodos (ou todos os mtodos)
apresentam este comportamento?
I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
10
Parte II - Classe: o Objeto Elementar

Os objetos isoladamente no tm muita utilidade, pois teramos que definir
todos os atributos e mtodos de cada um. Alm disso, em um programa OO tpico,
como j dissemos, objetos so criados e destrudos durante a execuo do programa.
As classes, que representam colees de objetos com caractersticas e mtodos
semelhantes (mas no necessariamente iguais), resolvem a questo de criao de
objetos: por meio das classes podemos definir os atributos e mtodos comuns a todos
os objetos e, tambm por meio delas, produzir os seus representantes - as instncias.
As classes podem ento ser consideradas uma espcie de frma (template) para a
produo de instncias.
As classes, como tudo o mais em Python, so objetos de primeira classe, isto
, classes podem ser fornecidas como argumento de funes, ser elementos de tuplas,
se tornar chaves de dicionrios, ser atributo de objetos, etc. Vejamos como fcil em
Python a criao destes objetos to preciosos...

1. Sintaxe.

A criao de classes em Python se d atravs da palavra reservada class. A
seguir, definimos uma classe que no faz nada por meio da palavra tambm reservada
pass:

>>> class Cachorros:
pass

Pronto, basta isso e est criada a classe dos Cachorros! Veja:
I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
11
>>> Cachorros
<class __main__.Cachorros at 0x00B04360>

Usamos nossa velha tcnica de introspeco (dir) e descobrimos que a classe
recm-criada Cachorros j possui dois atributos:

>>> dir(Cachorros)
['__doc__', '__module__']

Voc j sabe que os objetos instncias so definidos a partir de suas classes.
Em geral no so as classes que usamos na execuo um programa, e sim suas
instncias. Pois bem, a sintaxe necessria para produzir uma instncia algo como
Nome_da_classe(parmetros). Nossa recm-criada classe de Cachorros pode ser
instanciada assim: Cachorros(), visto que esta classe no contm "parmetros
(veremos adiante o motivo). No perca os dois parnteses de vista:

>>> Cachorros ()
<__main__.Cachorros instance at 0x00CF3D50>

Entretanto:

>>> id(Cachorros()) == id(Cachorros())
False

A funo id(obj1) retorna um inteiro particular (hexadecimal) que identifica o
obj1 e permite compar-lo com outros objetos. Usamos esta funo acima sobre duas
I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
12
instanciaes da classe Cachorros para que voc perceba que cada vez que usamos a
expresso Nome_da_classe(parmetros) invocamos uma nova instncia. Sabemos
ainda que, em nosso caso as instncias criadas so gmeas idnticas umas s outras,
pois, embora sejam distintas, no h como distingui-las... Em Python, para que
possamos fazer referncia a uma dada instncia criada, atribumos a instncia a um
nome (uma varivel), no momento de sua criao. Veja um exemplo deste tipo de
atribuio, no qual o nome d aponta para uma instncia da classe Cachorros.

d = Cachorros ()

Dissemos anteriormente que classes so objetos de primeira classe, e por isso
poderiam ser utilizadas como argumento de funes, chaves de dicionrios, etc. Crie
seus prprios exemplos para verificar isso; ser um teste muito instrutivo e,
garantimos, voc se surpreender mais uma vez com Python. De qualquer forma, aqui
vai o nosso exemplo, ainda usando a classe Cachorros:

>>> Dogs = Cachorros
>>> Dogs
<class __main__.Cachorros at 0x00B04360> # O mesmo id de Cachorros!
>>> Dogs.__name__
'Cachorros'

O atributo interno __name__, se existir, retorna o nome do objeto sobre o
qual aplicado. Classes, mdulos e funes so alguns dos objetos que respondem a
este atributo. Desenvolveremos a seguir uma funo que nos informa se o objeto
passado como argumento tem ou no um __name__, fornecendo-o, se tiver, bem
como seu id.

I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
13
>>> def nome_do_objeto(c): Voc sabe dizer qual o tipo de c?
try:
print 'Nome do objeto: %s. Id: %d.' % (c.__name__, id(c))
except:
print """O objeto " %s " no tem atributo __name__
mas seu id %d.""" % (str(c), id(c))

>>> ndo=nome_do_objeto
>>> ndo(Dogs)
Nome do objeto: Cachorros. Id: 10756032.
>>> ndo('abacaxi')
O objeto " abacaxi " no tem atributo __name__
mas seu id 10738400.

Perceba que passamos naturalmente uma classe (no uma instncia, a
prpria classe) como argumento da funo ndo. Em Python, os mtodos, funes,
mdulos, etc., no tentaro descobrir o tipo do objeto para saber se o procedimento
permitido. Eles simplesmente tentaro executar suas rotinas, retornando erro caso no
seja possvel. Aqui voc viu que a funo ndo no checa se o objeto c possui o atributo
__name__. Simplesmente tenta executar o que foi solicitado. Quando isto no
possvel, ela retorna o erro prescrito no bloco except.
Funes tambm so objeto de primeira classe, ento
tambm permitido fazer ndo(ndo). Que resposta o
interpretador daria a isto? Procure descobrir sem
implementar.
Se em vez do nome do objeto, a funo tivesse que
retornar o seu tipo, seria necessrio o uso do try? Por
qu?
I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
14
2. Atributos e mtodos.

Atributos so objetos inerentes s classes, ou seja, comuns a todas as suas
instncias. Imagine que queiramos agrupar cachorros e galinhas em classes conforme
suas caractersticas. As caractersticas que todas as instncias destas classes possuem
so seus atributos. Veja o exemplo:

>>> class Cachorros:
cobertura='pelos'
alimento='carne'
patas=4
habitat='domestico'
nome='Rex'

>>> class Galinhas:
cobertura='penas'
alimento='graos'
patas=2
habitat='domestico'
bico='pequeno'

>>> dir(Cachorros)
['__doc__', '__module__', 'alimento', 'cobertura', 'habitat', 'nome', 'patas']
>>> dir(Galinhas)
I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
15
['__doc__', '__module__', 'alimento', 'bico', 'cobertura', 'habitat', 'patas']

Como vemos, as classes Cachorros e Galinhas possuem quatro atributos em
comum: cobertura, alimento, patas e habitat. Cachorros possui ainda o atributo nome
enquanto Galinhas possui o atributo bico, alm de __doc__ e __module__ que ainda
discutiremos. Vamos definir instncias para elas e voc vai comear a perceber que
instncias podem ser vistas como indivduos de uma classe, possuindo os atributos de
sua classe, etc.

>>> Snoopy=Cachorros()
>>> Lala=Galinhas()
>>> Snoopy.alimento
'carne'
>>> Lala.alimento
'graos'
>>> Lala.bico
'pequeno'
>>> Snoopy.bico

Traceback (most recent call last):
File "<pyshell#28>", line 1, in -toplevel- Snoopy.bico
AttributeError: Cachorros instance has no attribute 'bico'

Snoopy, como membro da classe Cachorros, no possui o atributo bico.
Claro que os atributos podem ser usados em qualquer parte do programa:
I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
16
>>> print '%s late sem parar!' % Snoopy.nome
Rex late sem parar!

U! O nome no era Snoopy? Fique atento para distinguir o nome (ou
varivel) atribudo instncia - Snoopy - e o atributo de classe 'nome, que "Rex!
Para verificar que `nome mesmo um atributo da classe Cachorros, voc pode dar
uma olhada na definio da classe, ou simplesmente requisitar:

>>> Cachorros.nome
'Rex'

Mtodos so funes definidas dentro da classe e, em geral, ligadas (bound) a
cada instncia da classe, como veremos. Eles so usados para definir que aes que
sero executadas por uma instncia dessa classe. No prximo exemplo, Circulos possui
como atributo somente o raio de um crculo, alm de dois mtodos: calcula_Area e
calcula_Volume:

>>> class Circulos:
raio = 25.4
def calcula_Area(self):
self.area = 3.14*(self.raio**2)
def calcula_Volume(self,altura):
self.volume = 3.14*(self.raio**2)*altura

I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
17
A seguir, atribumos uma instncia da classe Circulos ao nome C1.
Inicialmente, s o atributo raio existe. Por outro lado, se aplicarmos o mtodo
calcula_Area sobre C1, ento esta instncia ter mais um atributo, que area:

>>> C1=Circulos()
>>> C1.raio
25.399999999999999
>>> C1.area

Traceback (most recent call last):
File "<pyshell#44>", line 1, in -toplevel- C1.area
AttributeError: Circulos instance has no attribute 'area'
>>> dir(C1)
['__doc__', '__module__', 'calcula_Area', 'calcula_Volume', 'raio']

>>> C1.calcula_Area()
>>> C1.area
2025.8024
>>> dir(C1)
['__doc__', '__module__', 'area', 'calcula_Area', 'calcula_Volume', 'raio']

A pergunta voc: "Mas o que aconteceu com aquele argumento self que
deveria ser passado ao mtodo Calcula_Area??? (voc pergunta com trs
interrogaes mesmo, porque est espantado com este aparente absurdo).
O argumento self - que no uma palavra reservada - aparece como
primeiro argumento na definio da maioria dos mtodos de classes e uma maneira
I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
18
muito apropriada de fazer referncia prpria instncia a qual o mtodo se aplica.
Quando invocamos o mtodo, o argumento self est implcito como primeiro
argumento. Como a nossa instncia se chama C1, o mtodo C1.calcula_Area() est
dizendo: C1.area = 3.14*(C1.raio**2). Assim, ao aplicar este mtodo sobre C1,
passar a existir o atributo C1.area que antes no existia. Verifique tambm que:

>>> C1.calcula_Area() == Circulos.calcula_Area(C1)
True

Isto indica que em lugar de C1.calcula_Area() poderamos ter usado a forma
Circulos.calcula_Area(C1).
Outros nomes que no self podem ser usados, mas um favor a voc mesmo
e aos leitores do seu cdigo se voc no mudar isto. Qualquer programa OO em
Python que voc encontrar quase certamente far uso deste termo.
H ainda outro mtodo na classe Circulos, calcula_Volume, que alm do self
obrigatrio possui tambm outro argumento: altura. Sendo assim, deveremos passar
este argumento quando formos aplicar este mtodo, ao contrrio do mtodo
calcula_Area que utilizamos sem parmetro explcito algum.

>>> C1 = Circulos()
>>> C1.calcula_Volume()

Traceback (most recent call last):
File "<pyshell#19>", line 1, in -toplevel- C1.calcula_Volume()
TypeError: calcula_Volume() takes exactly 2 arguments (1 given)

I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
19
Observe o que acontece se suprimirmos tambm o argumento altura que
deveria ser passado explicitamente ao mtodo calcula_Volume. O erro resultante
indica que o mtodo toma exatamente dois argumentos e apenas um foi fornecido. O
argumento "dado o self implcito!

>>> C1.Calcula_Volume(12.)
>>> C1.volume
24309.628799999999

Classe intil essa, hein? Ela s calcula a rea e volume de um crculo de raio
25.4! Como ser que faramos para que cada instncia se referisse a um crculo
diferente? Alis, aquela velha classe Cachorros tambm bem montona, uma vez
que todos os seus indivduos (as instncias como "Snoopy) tm o mesmo atributo
nome, "Rex. Como faramos para que cada cachorro desta classe tivesse um nome
diferente? Utilizaremos um mtodo especial, __init__.

3. O mtodo especial __init__.

Na definio das classes veremos que muito comum encontrarmos um
mtodo especial chamado __init__ (Esses traos horizontais so duplos underlines).
Ele o mtodo construtor da classe, que usamos sempre que queremos definir
atributos e mtodos para uma instncia no momento em que ela for criada. Com o
__init__ podemos diferenciar uma instncia de outra, isto , um indivduo de outro da
mesma classe j no momento de sua criao. Redefinindo a classe Cachorros, para que
cada indivduo desta classe tenha um nome, quando for criado:


I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
20
>>> class Cachorros:
cobertura='pelos'
alimento='carne'
patas=4
habitat='domestico'
def __init__(self, nome): # Jamais nos esqueceremos do self!
self.nome= nome

>>> d1 = Cachorros('Dog1')
>>> d1.nome
'Dog1'

Como vemos, os valores para os argumentos dentro do __init__ devero ser
fornecidos no momento exato da criao de cada instncia. Nem sempre precisaremos
fornecer valores para todos os argumentos, como veremos adiante com o uso de
valores default.
Para tornar as coisas interessantes, vamos supor que temos a necessidade de
manipular uma infinidade de objetos "na tela, de forma a que cada um deles tenha
um nome, um tamanho, uma cor, um nmero de arestas. Por outro lado, a posio
mutvel (x,y) de cada um ser dada por um nmero real aleatrio dentro de um
quadrado de 10x10. Para gerarmos a posio aleatria, usaremos o mdulo random.
No Mdulo A j vimos que a funo random deste mdulo gera um float x aleatrio tal
que 0 x 1. Um dos cdigos possveis est mostrado na pgina seguinte.




I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
21
>>> from random import random
>>> class Sprites:
def __init__(self, nome,
tamanho = 'grande',
cor = 'amarelo',
arestas = 5): # self sempre o primeiro argumento!
self.nome = nome
self.tamanho = tamanho
self.cor = cor
self.arestas = arestas
def update_position(self):
self.position = random()*10,random()*10 # posies x e y
print '%s est agora em %s.' %(self.nome,self.position)

Na criao da primeira instncia, usamos o argumento aresta como default,
ou seja, como no passamos este argumento explicitamente, o inteiro 5 definido pelo
mtodo __init__ assumido. A instncia s2 foi criada para que voc veja que os
argumentos podem ser dados em qualquer ordem, como j sabemos fazer com
funes.

>>> s1 = Sprites('Star1', 'pequeno', 'vermelho')
>>> s1.nome, s1.tamanho, s1.cor, s1.arestas
('Star1', 'pequeno', 'vermelho', 5)
>>> s2 = Sprites('Star2', arestas=6, cor='azul')
>>> s2.nome, s2.tamanho, s2.cor, s2.arestas
('Star2', 'grande', 'azul', 6)
I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
22
>>> s1.update_position(), s2.update_position()
Star1 est agora em (0.43251725889582815, 9.5024820736664353).
Star2 est agora em (0.50694145748064412, 1.6160935722866276).
(None, None)
>>> s1.position
(0.43251725889582815, 9.5024820736664353)
>>> s2.position
(0.50694145748064412, 1.6160935722866276)

Voc viu que aps a aplicao do mtodo update_position sobre uma
instncia, passar a existir - ser atualizado - o atributo position daquela instncia, que
distinto para cada uma das instncias s1 e s2. Os indivduos dessa classe
compartilham os atributos definidos normalmente dentro da classe, mas no os
atributos definidos pelo mtodo __init__.

A tupla (None, None) deve ter soado uma campainha no seu
crebro, fazendo voc se lembrar de uma discusso importante do
Mdulo A. Voc consegue explicar porque essa tupla apareceu e o
que ela quer dizer?

4. Os atributos especiais __doc__ e __module__.

Anteriormente, pudemos perceber que qualquer classe possui nativamente
dois atributos com duplo underline, __doc__ e __module__. Assim como as funes,
os mdulos e as packages, as classes e os mtodos em Python tambm podem conter
docstrings, cujo contedo imediatamente assumido por um atributo pr-definido
I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
23
chamado __doc__. Ele pode ser acessado tanto atravs da classe, da instncia ou do
mtodo vinculado instncia. Veja:

>>> class Fausto:
"""Fausto um romance de Goethe
que Beethoven transformou em pera."""
def review(self):
"""
Este mtodo responde com a avaliao dos crticos
"""
print 'Um romance excepcional'

>>> print Fausto.__doc__
Fausto um romance de Goethe
que Beethoven transformou em pera.

>>> print Fausto().__doc__
Fausto um romance de Goethe
que Beethoven transformou em pera.

>>> print Fausto().review.__doc__
Este mtodo responde com a avaliao dos crticos




I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
24
Alm da funo dir, o Mdulo A j havia nos apresentado a outra importante
ferramenta de introspeco, a funo help. Observe como ela se torna especialmente
til na introspeco de classes. Todos os mtodos so exibidos de uma vez s,
juntamente com suas respectivas docstrings. Pela primeira linha exibida pela funo
help, descobrimos a qual mdulo a classe pertence. Como aqui estamos usando o
IDLE, o "mdulo __main__.

>>> help(Fausto)
Help on class Fausto in module __main__:

class Fausto
| Fausto um romance de Goethe
| que Beethoven transformou em pera.
|
| Methods defined here:
|
| review(self)
| Este mtodo responde com a avaliao dos crticos

Responda rpido: qual a diferena entre Fausto.__doc__ e Fausto().__doc__?

Falando em __main__, o atributo especial __module__ guarda o nome do
mdulo a que a classe pertence. Se criarmos uma classe num programa ou no IDLE, e
no mesmo programa solicitarmos ins1.__module__ (sendo ins1 uma instncia da
classe), a resposta ser '__main__, ou seja, a classe est no script corrente cujo
__name__ sempre '__main__ como no exemplo da classe Fausto acima. A seguir
observamos este atributo de uma classe criada no IDLE e de outra classe importada:
I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
25
>>> class So_Acredito_Vendo: pass

>>> sav = So_Acredito_Vendo()
>>> sav.__module__
'__main__'
>>> from math import sin
>>> sin.__module__
'math'


Parte III - Herana

Assim como a classe biolgica de galinhas herda as asas do grupo das aves e
os cachorros herdam os dentes caninos do grupo dos candeos, tambm as classes em
Python podem herdar atributos de outras classes. Veja outro exemplo:

Tanto o ao, quanto o ferro-fundido, o alumnio e o titnio herdam a
caracterstica de conduzir calor. Destes, somente o ao e o ferro-fundido so ferrosos,
e dos ltimos, somente o ao possui o atributo de ser dctil... Certo. E da?
I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
26
Imagine que voc esteja definindo classes to repletas de atributos quanto as
classes de materiais. So centenas de atributos a serem definidos, como condutividade
trmica e eltrica, permissividade magntica, tenacidade fratura, eletronegatividade,
etc. etc. No fosse o recurso de herana, que permite a voc fazer uma classe herdar
atributos de outra, cada um dos atributos teria que ser definido classe a classe!
Neste exemplo de materiais, a classe dos materiais ferrosos herda da classe
dos condutores trmicos o atributo de conduzir calor. Por isso, diz-se que a classe
Condutores_Trmicos superclasse (ou "pai, "mestre, ou "base) da classe
Materiais_ Ferrosos. Por sua vez, a classe Materiais_Ferrosos subclasse (ou "filha,
ou "derivada) da classe Condutores_Trmicos.
Em Python, quando queremos dizer a uma classe quem so suas superclasses
(pode haver mais de uma!), aparece um novo item na sintaxe - os parnteses aps o
nome da classe. Observe como simples fazer as classes de materiais herdarem
atributos dos seus mestres:

class Condutores_Trmicos:
atributos1....
class Materiais_Ferrosos(Condutores_Trmicos):
atributos2.....
class Materiais_Dcteis(Materiais_Ferrosos):
atributos3.....

Assim, embora s os atributos2 estejam definidos no corpo da classe
Materiais_Ferrosos, ela tambm passa a possuir os atributos1 que herdou da sua
superclasse. Da mesma forma, a classe Materiais_Dcteis herda atributos1 e
atributos2 da superclasse Materiais_Ferrosos.
Mo na massa! Criaremos trs classes. Uma, chamada Pai, possui trs
atributos que so herdados pela classe Filha. A terceira classe, Neta, herda de Filha e
por conseqncia tambm herda os atributos de Pai. Quer ver?
I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
27
>>> class Pai:
Nome = 'Carlos'
Sobrenome = 'Oliveira'
Residencia = 'Ilha Solteira'

>>> class Filha(Pai):
Nome = 'Luciana'
Olhos = 'castanhos'

>>> class Neta(Filha):
Nome = 'Maria'

>>> Pai.Nome, Filha.Nome, Neta.Nome
('Carlos', 'Luciana', 'Maria')
>>> Pai.Residncia, Filha.Residncia, Neta.Residncia
('Ilha Solteira', 'Ilha Solteira', 'Ilha Solteira')
>>> Pai.Olhos, Filha.Olhos, Neta.Olhos
('azuis', 'castanhos', 'castanhos')

Veja como o atributo Nome distinto para Pai, Filha e Neta; a Residncia de
Pai foi herdada pelas suas subclasses Filha e Neta; esta, por sua vez herdou o atributo
Olhos de sua superclasse imediata Filha.
possvel determinar rapidamente se uma classe Alfa herda de outra classe
Beta atravs da sintaxe issubclass(Alfa,Beta), mas uma forma mais prtica cuja
resposta no um booleano, Alfa.__bases__. A desvantagem que esta ltima
forma diz somente quem so as classes de quem Alfa herda diretamente. Veja:
embora Neta herde indiretamente os atributos de Pai, o interpretador diz que ela
I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
28
subclasse de Filha. Por outro lado, Neta.__bases__ informa somente a classe da qual
Neta herda atributos diretamente:

>>> issubclass(Neta,Pai)
True
>>> Neta.__bases__
(<class __main__.Filha at 0x00A48030>,)

A seguir, voc pode ver uma classe que herda de vrias outras diretamente.
Todas estas classes-base so retornadas pelo mtodo __bases__.

>>> class Atlantico:
carater1 = ' um oceano '

>>> class Indico:
carater2 = 'perigoso, '

>>> class Pacifico(Indico):
carater3 = 'cheio de tsunamis '

>>> class Artico(Atlantico, Indico, Pacifico):
carater4 = 'e muito gelado!'

>>> print Artico.carater1 + Artico.carater2 + Artico.carater3 +\
Artico.carater4
I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
29
um oceano perigoso, cheio de tsunamis e muito gelado!
>>> Indico.__bases__
()
>>> Pacifico.__bases__
(<class __main__.Indico at 0x00A48060>,)
>>> Artico.__bases__
(<class __main__.Atlantico at 0x00A481E0>, <class __main__.Indico at
0x00A48060>, <class __main__.Pacifico at 0x00A48180>)

(Voc sabia que pode usar a barra invertida \ em Python para quebrar uma
linha e continuar o cdigo na de baixo? Isso evita cdigos de linhas quilomtricas
chatos de ler.)
Alm dos atributos, as classes tambm herdam os mtodos de suas
superclasses. A seguir, definimos duas classes - s a primeira possui os mtodos soma
e multiplicacao. No entanto, como a classe Op_Avancadas herda desta classe, qualquer
instncia de Op_Avancadas tambm pode fazer uso dos mtodos da classe-pai.
Aproveitando a deixa, voc aprender ao longo dos prximos exemplos um
recurso amplamente utilizado com Python orientado a objetos, que o uso de mtodos
especiais como __add__, __mul__ e __div__.
Voc sabe que operadores como +, - e * podem ser aplicados a objetos como
inteiros e strings gerando diferentes resultados dependendo do tipo do objeto. O sinal
+ aplicado a dois inteiros resulta na sua soma, enquanto sobre strings resulta na sua
concatenao. Podemos emular o comportamento deste operador sobre duas
instncias definindo-o dentro de sua classe. Analogamente, os mtodos __mul__ e
__div__ correspondem aos operadores * e /, respectivamente.
Veremos ainda o uso do mtodo call para tornar uma instncia callable (difcil
traduzir sem perder o contexto tcnico, mas o significado seria algo como "chamvel).

I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
30
>>> class Op_Basicas:
def __init__(self, entrada):
self.valor = entrada
def __add__(self, other): # mtodo especial!
return self.valor + other.valor
def __mul__(self, other): # mtodo espeial!
return self.valor * other.valor

>>> a = Op_Basicas(56)
>>> b = Op_Basicas(-23)
>>> a + b
33
>>> a * b
-1288

O conceito a ser notado destas ltimas inocentes linhas a sobrecarga de
operadores. Fizemos com que o operador que antes s podia ser aplicado a inteiros,
floats, strings, listas etc., agora possa ser aplicado sobre duas instncias, retornando
como resultado a soma dos seus atributos self.valor. Se estes atributos so strings, o
valor retornado sua concatenao:

>>> str1 = Op_Basicas('56')
>>> str2 = Op_basicas('-23')
>>> str1 + str2
'56-23'
>>> str1 * str2
Traceback (most recent call last):
I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
31
File "<pyshell#21>", line 1, in ?
str1 * str2
File "<pyshell#15>", line 7, in __mul__
return self.valor * other.valor
TypeError: can't multiply sequence to non-int

Ops! No definimos multiplicao de strings... Mas a multiplicao de inteiros
por strings j assumida pelo operador *.

>>> str2 = Op_Basicas(34)
>>> str1 * str2
'56565656565656565656565656565656565656565656565656565656565656565656'

Eis uma regra fundamental de Python. Se o objeto puder responder
mensagem com algum mtodo, ele o far, sem mais perguntas. Se ele no puder
responder, seja porque ele no possui o mtodo, seja porque o mtodo ou os
argumentos fornecidos so inadequados, um aviso de exceo ser emitido. De fato,
cabe ao programador a captura da exceo e a realizao de alguma coisa til com
ela! Voc est habilitado a fazer isso usando try-except que vimos e revimos mo
Mdulo A e mesmo neste.
Mas estamos falando de Herana. Seja a classe Op_Avancadas a ser definida
como subclasse de Op_Bsicas. Nela, o operador de diviso tambm sobrecarregado
para que a sentena inst1 / inst2 retorne um resultado, sendo inst1 e inst2 duas
instncias desta classe.



I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
32
>>> class Op_Avancadas(Op_Basicas):
def __init__(self, entrada):
self.valor = entrada
def __div__(self, other): # mtodo especial!
return float(self.valor) / other.valor


Se no transformssemos self.valor num float, haveria alguma
situao em que o mtodo geraria um valor insatisfatrio? Qual? H alguma
razo especial para no termos feito o mesmo com other.valor?


>>> c = Op_Avancadas(4)
>>> c / a
0.071428571428571425
>>> c / b
-0.17391304347826086
>>> c + a
60
>>> c * b
-92

Veja que por causa da herana, a sobrecarga dos operadores de soma e
multiplicao tambm esto disponveis para as instncias da classe Op_Avancadas.
I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
33
Em outras palavras, os mtodos __add__ e __mul__ foram herdados da sua classe-
base.
Falando nisso, mesmo o mtodo construtor pode ser omitido, se ele for
exatamente igual ao da classe-base. A classe abaixo herda tudo das superclasses,
inclusive o __init__ :

>>> class Op_Extras(Op_Avancadas):
def quadrado(self):
return self.valor * self.valor

>>> d = Op_Extras(6)
>>> d.quadrado()
36
>>> d + a
62
>>> c + d
10
>>> d / b
-0.2608695652173913

Parece e simples. Em virtude da herana, a instncia recm-criada, d, j
vem equipada com os mtodos __add__, __mul__, e __div__, alm do mtodo
construtor __init__. Alis, exatamente por ter herdado o __init__, esta nova classe
Op_Extras exige um argumento no ato da sua instanciao (aqui, usamos como
argumento o inteiro 6).
So chamados callable em Python todos os objetos capazes de carregar um
nmero indeterminado de argumentos. Podemos ento relembrar que funes, classes
I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
34
e mtodos so sempre callable. Para sabermos se um objeto callable, usaremos a
funo booleana callable(objeto):

>>> callable(str1) # str1 uma instncia da classe Op_Basicas...
False
>>> callable(Op_Basicas)
True
>>> callable(d.quadrado)
True
>>> callable('abacaxi')
False

Por outro lado, embora tenhamos descoberto que instncias no so
normalmente callable, podemos faz-las ter este comportamento, utilizando o mtodo
especial __call__ na definio da sua classe. Vamos redefinir a classe Op_Basicas para
que suas instncias sejam callable:

>>> class Op_Basicas:
def __init__(self, entrada):
self.valor = entrada
def __add__(self, other):
return self.valor + other.valor
def __mul__(self, other):
return self.valor * other.valor
def __call__(self, qualquer_coisa): # mtodo especial!
return qualquer_coisa
I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
35
>>> a = Op_Basicas(56)
>>> a('Vejam, eu sou uma instncia callable')
Vejam, eu sou uma instncia callable
>>> b = Op_Avancadas(-23)
>>> b('Eu tambm sou!')
Eu tambm sou!
>>> d = Op_Extras(6)
>>> d('E eu, ento, no sou?')
E eu, ento, no sou?
>>> a(a.valor), a(b.valor), b(d.valor)
(56, -23, 6)
>>> callable(a), callable(b), callable(d)
(True, True, True)

Por ltimo, aproveitamos que atributos de instncia so objetos de primeira
classe e passamos como argumento das instncias. Como agora estas so chamveis e
retornam qualquer coisa, os atributos de instncia so argumentos vlidos.
Observe com ateno que, por causa do mtodo __call__ na definio da
classe Op-Basicas, no apenas as suas instncias se tornaram callable, mas, devido
herana, as instncias de Op_Avancadas e Op_Extras passaram a ser tambm callable
atravs do mesmo mtodo. Obviamente, se desejssemos, o mtodo __call_ poderia
ser distinto para cada subclasse.

Explique a seguinte composio:
Op_Basicas('abacaxi')(6) * Op_Extras(16)('bola')
I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
36
Finalmente, o mtodo especial __str__ sobrecarrega a representao da
instncia. Com ele, voc pode determinar o que deve ocorrer quando o usurio
solicitar print inst1, sendo inst1 uma instncia da classe. Quem vai nos ajudar nesta
explicao mais uma vez a classe Op_Basicas.

>>> class Op_Basicas:
def __init__(self, entrada): # mtodo especial!
self.valor = entrada
def __call__(self, texto): # mtodo especial!
return texto
def __str__(self): # mtodo especial!
return 'Sou uma orgulhosa instncia de %s' % self.__class__

>>> a = Op_Basicas(56)
>>> print a
Sou uma orgulhosa instncia de __main__.Op_Bsicas
>>> a('Hello!')
'Hello!'
>>> b = Op_Avancadas('abacaxi')
>>> print b
Sou uma orgulhosa instncia de __main__.Op_Avancadas
>>> d = Op_Extras(6)
>>> print d
Sou uma orgulhosa instncia de __main__.Op_Extras
>>> b(a.valor)
56
I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
37
>>> d('And from me ' + str(b.valor))
'And from me -23'

Repare que as instncias no deixam de ser callable, j que mantivemos o
mtodo __call__.
O comportamento apresentado na execuo do cdigo print foi definido por
ns mesmos por meio do mtodo __str__. Esta uma das ferramentas do canivete
suo que Python nos oferece atravs da orientao a objetos. Usando herana com
sabedoria, poderemos acrescentar funcionalidades facilmente.
No so estes os nicos mtodos especiais. Existem aqueles que fazem com
que as instncias de uma classe se comportem como seqncias, tais como strings,
listas e tuplas ou ento como mapeamentos (mappings), tais como os dicionrios.
Demos aqui os conceitos indispensveis sobre mtodos especiais. Com estes conceitos
voc capaz de descobrir sozinho os que citamos acima. No deixe de pesquisar este
assunto porque estes procedimentos sero encontrados com freqncia nos programas
de terceiros.

Parte IV - Porque Usar Classes

Certa vez um sujeito expressou na lista c.l.py o que muita gente sente no
primeiro contato com OO. Ele disse que esperava que Python se mantivesse sempre
simples do jeito que ele aprendeu quando era iniciante, mas que no valia a pena usar
Orientao a Objetos porque parecia complicada demais.
Davor, outro participante da lista, mostrou de uma forma quase teatral que a
Orientao a Objetos era usada justamente para evitar complicaes. Veja uma
traduo adaptada da resposta do Davor:
I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
38
Concordo com voc! Orientao a Objetos o capeta! Acho melhor usar
variveis isoladas...

>>> nome1 = 'Oliveira'
>>> idade1 = 35
>>> sexo1 = 'masculino'
>>> nome2 = 'Cardoso'
>>> idade2 = 23
>>> sexo2 = 'feminino'
>>> print nome1, idade1, sexo1, nome2, idade2, sexo2

Hm... Que coisa chata reescrever todos os nomes das variveis! Ainda bem
que em Python temos as listas!

>>> p1 = ['Oliveira', 35, 'masculino']
>>> p2 = ['Cardoso', 23, 'feminino']
>>> for e in p1:
print e
>>> for e in p2:
print e

Pera! O termo 2 da lista p1 era a idade, ou era sexo? Ah, mas a no vale,
porque a indexao das listas no a melhor ferramenta para este caso. Os
dicionrios resolvem essa parada! Vou usar dict para converter uma lista de keywords
do tipo key = value em um dicionrio:

I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
39
>>> p1 = dict{name = 'Oliveira', idade = 35, sexo = 'masculino'}
>>> p2 = dict{name = 'Cardoso', idade = 23, sexo = 'feminino'}
>>> for e in p1.keys():
print '%s: %s' % (e, p1[e])
>>> for e in p2.keys():
print '%s: %s' % (e, p2[e])

Tenho agora que criar os dicionrios de pessoas, os de notas fiscais e outros.
D muito trabalho fazer isso tudo um por um, melhor usar modelos de dicionrios
(templates):

>>> class Imprimivel:
def __str__(self):
"""mtodo mgico (especial) chamado por print, str()..."""
ps = ''
for e in self.__dict__.keys(): # outro mtodo especial!
ps += '%s: %s\n' % (e, str(self.__dict__[e]))
return ps

>>> class Pessoa(Imprimivel):
def __init__(self, nome, idade, sexo):
self.nome = nome
self.idade = idade
self.sexo = sexo

>>> class Nota_Fiscal(Imprimivel):
I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
40
def __init__(self, nome, produto, preo):
self.nome = nome
self.produto = produto
self.preo = preo

>>> pes = Pessoa(nome = 'Oliveira', idade = 35, sexo = 'masculino')
>>> nf = Nota_Fiscal(nome = 'Cardoso', produto = 'carro', preo = 300.0)
>>> print pes # as instncias so imprimveis
idade: 35
sexo: masculino
nome: Oliveira
>>> print nf # as instncias so imprimveis
preo: 300.0
produto: carro
nome: Cardoso

Alm deste tipo de manipulao ilustrada por Davor, use classes sempre que
estiver trabalhando com projetos grandes para evitar conflito de nomes. Como cada
classe possui um namespace prprio, voc pode dar praticamente qualquer nome aos
atributos de uma classe sem se preocupar com o resto do cdigo.





I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
41
Parte V - Convenes sobre Nomes

Ao longo de todo este (curto) mdulo, foi possvel observar alguns padres na
definio das classes, atributos e mtodos. No por acaso que todas os nomes de
classe comeam com letras maisculas enquanto os nomes dos mtodos comeam
com letras minsculas: uma recomendao do tutorial oficial de Python. Se voc se
acostumar com estas regras simples, ser mais fcil fazer manuteno nos seus
programas, alm de facilitar a vida de quem estudar seus cdigos. Veja algumas das
recomendaes:
Dentro das classes, refira-se s instncias sempre atravs do nome
self;
Use letras maisculas para a primeira letra dos nomes das classes;
Use letras minsculas para os nomes dos mtodos. Se o nome for
composto por mais de uma palavra, voc pode escrever a segunda,
terceira, etc. com letra maiscula, ou separa-las com underlines:
meuMetodo ou meu_metodo.
Nomeie os atributos com substantivos e os mtodos com verbos
(indicando ao). Atributos: raio, r, r2. Mtodos: calculaRaio, calcR,
calcular_raio, etc.


Parte VI - Exerccios

Fceis Mdios
Refine os exemplos dados neste Mdulo. Alguns mtodos definidos dentro das
classes podem ser herdados de classes nativas de Python - use a herana
para elimina-los do corpo da classe.

I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
42
Crie uma matilha de 100 cachorros, de modo que todos tenham nomes `Dogj,
sendo j = 1, 2, 3, ..., 100, e gere simultaneamente uma idade aleatria
diferente para cada um deles. Sugesto: use os recursos de list
comprehensions que vimos no Mdulo A.
Desenvolva uma classe de matrizes de ordem 33. A matriz dada dever ser
uma lista de listas (uma lista de trs listas com trs elementos cada uma), e
devero estar disponveis as operaes de soma, multiplicao e clculo do
determinante.
Escreva uma classe para resolver sistemas lineares de ordem 33 usando a
Regra de Cramer. Voc ter que calcular o determinante de algumas matrizes
- herde este mtodo da classe que voc desenvolveu no exerccio anterior. A
Regra de Cramer pode ser encontrada facilmente na internet. Google nela!
Desenvolva uma classe para trabalhar com nmeros complexos, na qual
estejam definidos os mtodos para realizar as quatro operaes bsicas com
este conjunto numrico. Estas operaes so:
Adio: i d b c a di c bi a ) ( ) ( ) ( ) ( + + + = + + +
Subtrao: i d b c a di c bi a ) ( ) ( ) ( ) ( + = + +
Multiplicao: i bc ad bd ac di c bi a ) ( ) ( ) ( ) ( + + = + + e
Diviso: i
d c
ad bc
d c
bd ac
di c
bi a

+
+
=
+
+
2 2 2 2
) (
) (
.
Adicione mais um mtodo sua classe de nmeros complexos para retornar
ao usurio o nmero em questo na forma polar, isto , passa-lo da forma
a+bi para a forma r . Lembre-se de que:
Raio:
2 2
b a r + = e ngulo:

=
b
a
arctan . A classe ter que herdar os
mtodos de raiz quadrada e arco-tangente de outra classe nativa de Python.
Qual voc usaria?
Reescreva os exemplos do Mdulo A usando Orientao a Objetos.






I N T R O D U O A P Y T H O N - M D U L O B
P Y T H O N O R I E N T A D O A O B J E T O S

L A B A K I & W O I S K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
43
Vem a...


Viu s? No doeu nada! Aposto que em menos de uma hora voc leu este
Mdulo e aprendeu o indispensvel para trabalharmos com OO em Python.
No se iluda: o contedo que voc viu aqui uma gota do oceano da
Orientao a Objetos (que potico!). Mesmo assim, de posse desses conceitos - que
voc j est dominando, se tentou fazer os exerccios recomendados - j podemos
partir para a to esperada programao de interfaces grficas com Tkinter.
No Mdulo C, voc ver que os widgets (os botes, menus, caixas de texto)
do Tkinter se comportam de uma forma muito familiar, agora que voc j sabe que
objetos recebem mensagens e respondem a elas por meio de seus prprios mtodos,
atributos, etc. Seria difcil reproduzir este comportamento com programao
procedural...
Nos vemos no Mdulo C!

Sua participao muito importante para a constante
melhoria deste material. Ficaremos muito honrados em
conhecer suas opinies, sugestes, crticas ou dvidas
sobre ele. Para isso, podemos ser encontrados em
labakiturbo@gmail.com e woiski@dem.feis.unesp.br.







Este documento pode ser distribudo livremente, desde que mantidos os crditos aos autores.
C Cr ru up po o P Py yt th ho on n a ap pr re es se en nt ta a: :
I In nt tr ro od du u o o a a P Py yt th ho on n - - h h d du uI Io o C C





T
T
k
k
I
I
n
n
t
t
e
e
r
r
!
!




J Jo os su u L La ab ba ak kI I
I Ia ab ba ak kI It tu ur rb bo o@ @g gm ma aI II I. .c co om m









UNESP - ILHA SDLTEIPA
UNIVERSIDADE ESTADUAL PAULISTA
JLI O DE MESQUI TA FI LHO
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
2
Apresentao

Este material foi desenvolvido para apoiar os cursos da srie "Introduo
a Python" ministrados pelo Grupo Python para nossos mais diversos tipos de
audincia. O guia inteiro composto por trs volumes que correspondem aos mdulos
dados nos nossos cursos: Mdulo A - Bem-vindo a Python!, Mdulo B - Python
Orientado a Objetos e Mdulo C - Tkinter. Todos eles podem ser encontrados na
internet, nas pginas do Grupo Python (http://grupopython.cjb.net), na pgina do
autor (http://labaki.tk) e na pgina da comunidade Python no Brasil
(http://www.python-brasil.com.br).
Desenvolvemos este guia pensando tambm nos autodidatas que no
participaram dos nossos cursos e baixaram este material da internet. Se voc estiver
nesta situao, pode tirar dvidas por e-mail.
Lembramos que o nosso objetivo no ensinar programao, e sim guiar
voc nos passos bsicos em Python. Se sua inteno for aprender a programar, prefira
o excelente material do prof. Luciano Ramalho em (http://www.magnet.com.br).
Recomendamos que voc acompanhe e implemente os exemplos, tente
entender os erros que podem ocorrer e tente resolver as questes que eventualmente
aparecem ao longo deste material. Ao final, h alguns exerccios de fixao.
Mande suas dvidas, sugestes, crticas ou comentrios por e-mail! Sua
opinio sobre o guia muito importante para ns.


Josu Labaki
Grupo Python
Departamento de Engenharia Mecnica
UNESP - Campus de Ilha Solteira
labakiturbo@gmail.com

I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
3
ndice
Parte I - Tkinter 4
1.Aumentando nosso vocabulrio 4
2.A classe Tk 5
Parte II - Montando a GUI 6
1.Hierarquia e pack 6
2.O continer frame e o widget boto 8
3.Posicionando widgets na GUI 11
Parte III - Binding 14
1.Eventos do mouse 14
2.Foco e eventos do teclado 17
3.Command binding 21
Parte IV - Campos de dados 23
1.O widget Entry 23
Parte V - Canvas 26
1.Coordenadas 27
2.Linhas 29
3.Polgonos, retngulos e textos 31
4.Elipses e arcos 35
5.Gerenciamento de objetos do Canvas 39
Parte VI - Recursos Diversos. 45
1.Mtodos da janela Top-level 45
2.Colorindo a GUI 47
3. Como descobrir a posio do mouse 50
4.Gerenciador de geometria Grid 54
Parte VII - Exerccios 58
ltimas Palavras. 61

I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
4
Parte I - Tkinter

Tkinter uma das ferramentas que Python oferece para desenvolvimento de
interfaces grficas. Milhares de recursos permitem criar interfaces grficas to
complexas quanto se queira (o IDLE o exemplo mais clssico), e outros recursos
ainda podem ser encontrados na internet para download. Sua documentao bem
vasta, embora quase completamente em ingls. Outra vantagem que a instalao do
pacote bsico de Python para Windows j carrega Tkinter a tiracolo - qualquer
computador que tenha o interpretador de Python instalado j permite criar interfaces
grficas em Tkinter (algumas distribuies Linux requerem a instalao de mdulos
especiais).

1. Aumentando nosso vocabulrio

Neste ltimo Mdulo do nosso guia, veremos alguns novos termos especficos
de Tkinter. O mais usado widget, uma palavra sem traduo. Ela usada para se
referir a um componente qualquer da interface grfica (GUI - Graphic User Interface):
um boto, um menu, uma caixa de texto, etc. Um clique do mouse sobre a janela da
GUI, seja num widget ou num espao vazio, ou o pressionamento de uma tecla do
teclado, chamado de evento.
H tambm os event handlers ("tratadores de eventos), que so
procedimentos programados para serem executados quando um evento especfico
acontece. Isto , ao clicar num boto "Sair, a rotina que fechar a janela (digamos
que ela se chame "fecha_Janela) o event handler correspondente a clicar neste
boto. Para que a rotina fecha_Janela seja executara a um clique no boto "Sair,
necessrio fazer binding deste boto com aquela rotina.
Veja na figura uma aplicao de Tkinter famosa, o IDLE. Ele se comporta
como se seu programador tivesse escrito um event handler que faz o menu File (um
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
5
widget) ficar saltado e tivesse ligado
1
o evento "Parar o mouse sobre o menu file a
este event handler. Quando o evento acontece (quando algum pra o mouse sobre
esse widget), o event handler se aciona e o menu fica saltado. Na verdade, no
necessrio fazer este tipo de atribuio com o widget Menu. Ele fica saltado
automaticamente.


2. A classe Tk

Sempre que trabalharmos com Tkinter, importaremos todo o contedo deste
mdulo. A classe Tk tambm importada, e dela que conseguimos tirar os widgets
com os quais montaremos nossa GUI. Nossas interfaces grficas sempre sero
estruturadas em forma de classes, e uma instncia da classe Tk, que abaixo
chamamos de raiz, sempre ser passada como argumento do mtodo construtor da
nossa GUI. Veja tudo isso no nosso primeiro exemplo:

from Tkinter import *
class Janela:
def __init__(self, instancia_de_Tk):
pass
raiz=Tk()
Janela(raiz)
raiz.mainloop()

1
To bind: ligar. Tambm nos referiremos ao processo de binding por fazer binding, ligar, relacionar,
atribuir, etc.
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
6
A ltima linha faz com a instncia o que chamamos de event loop. O mtodo
mainloop da instncia raiz faz com que essa GUI fique eternamente aberta esperando
pelo acontecimento de eventos. Se o evento ocorrido for, por exemplo, um clique
numa rea fora da GUI, nada ocorre, mas se o evento for algo como o pressionamento
de um boto, o event handler correspondente ser acionado. Com a aplicao do
mtodo mainloop, a janela fica aberta at que ocorra algum evento que a "destrua,
como um clique no boto X de fechar ou num boto "Fechar que eventualmente possa
existir.
Falando em boto X, veja como cmodo trabalhar com Tkinter. Assim que
voc implementar nosso exemplo
2
, ver que os botes de minimizar, maximizar e
fechar j so automaticamente colocados na sua GUI, alm da barra de ttulo e do
smbolo caracterstico do Tkinter - um Tk em vermelho na extrema esquerda da barra
de ttulo. Voc deve ter observado o mesmo smbolo na janela do IDLE.
Alis, como aplicao de Tkinter, o IDLE tambm possui seu prprio event
loop que entrar em conflito com o das suas interfaces grficas, por isso nunca rode
seus programas em Tkinter no IDLE. Em vez disso, prefira clicar diretamente no cone
do programa onde voc o salvou, ou simplesmente retire a sentena que impe o
mainloop s suas GUIs.

Parte II - Montando a GUI

1. Hierarquia e pack

To importantes quando os widgets so os contineres, que so os elementos
da GUI - nem sempre visveis - onde ajeitaremos os widgets. O mais comum o
frame.

2
No necessrio implementar os exemplos deste Mdulo. Todos eles esto disponveis para download a
partir de http://labaki.tk.
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
7
Como pode haver uma estrutura bem complexa de contineres (como um
continer dentro do outro), define-se uma estrutura hierrquica para no perdermos o
controle sobre esta estrutura. Digamos que na GUI o continer Beta esteja disposto
dentro do continer Alfa. Ao definirmos Beta, o primeiro argumento ser Alfa, o que
indica que Alfa "pai (ou "mestre) de Beta: continerBeta(continerAlfa,......).
Widgets seguem a mesma sintaxe: o primeiro argumento no instante da sua
definio deve indicar quem seu continer-pai - o continer dentro do qual o widget
dever estar situado.
O elemento mximo da hierarquia a prpria janela top-level, aquela que
vem com os botes de fechar, barra de ttulo, etc. Veja um esquema hierrquico:

Aps a definio de um continer ou widget, precisamos usar um gerenciador
de geometria para indicar em que posio ele aparecer dentro do seu mestre. Tkinter
oferece trs: grid, pack e place. Neste tutorial usaremos o pack, e bem no final
falaremos sobre grid, mas voc pode descobrir o gerenciador place consultando os
livros recomendados ao final deste Mdulo. Se nenhum gerenciador de geometria for
aplicado ao widget, ele existir, mas no ser visvel ao usurio! Neste caso o widget
chamado de virtual e serve, por exemplo, para criar uma GUI invisvel que mesmo
assim permitisse a atribuio de um evento a um procedimento.
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
8
2. O continer frame e o widget boto

Criaremos um exemplo que envolver os tipos mais comuns de continer e
widget: Frame e Button. No exemplo, observe como o mestre do frame (a janela top-
level) e do boto (o frame que chamamos de fr1) so passados como primeiro
argumento. A sintaxe self.fr1 indica que o frame, com qualquer widget, tratado
como um atributo da instncia da classe Tk. Observe tambm a utilizao do pack para
tornar os widgets e contineres visveis.
A sintaxe para criar um widget qualquer Nome_do_widget(mestre, opes
de configurao). Ao longo deste Mdulo conheceremos as principais opes de
configurao disponveis para alguns widgets. Por enquanto vamos configurar somente
a cor e o texto do boto.

from Tkinter import *
class Janela:
def __init__(self,toplevel):
self.fr1 = Frame(toplevel)
self.fr1.pack()
self.botao = Button(self.fr1, text='Oi!', background='green')
self.botao.pack()

raiz=Tk()
Janela(raiz)
raiz.mainloop()

Resultado:

I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
9
Alm desta janela, deve ter aparecido tambm uma janela preta do script de
Python. Caso voc no queira que ela seja visvel, basta salvar seu arquivo com
extenso pyw.
A opo `background muda a cor de fundo do boto. Em vez de `background,
poderamos ter abreviado o nome como `bg.
Os widgets guardam suas opes de configurao em forma de dicionrios.
Por isso, tambm poderamos configurar as opes do boto por meio de:
self.botao['bg']='green'
Um fato notvel que a janela diminuiu de tamanho em relao ao exemplo
anterior. No primeiro exemplo, o tamanho da janela era o tamanho padro de janelas
sem widgets. A partir do momento em que um frame adicionado, a janela passa a
ter o tamanho do frame. Por outro lado, os frames so elsticos: seu tamanho
exatamente o tamanho dos widgets que eles contm.
Faa um teste. Use o mesmo exemplo, mas retire o boto (voc no precisa
apagar as linhas que o definem, basta no aplicar o mtodo pack). A janela agora se
reduz ao tamanho mnimo, no ?
Por outro lado, a adio de mais um boto faz o frame se esticar para
comporta-los, como no exemplo seguinte. Neste exemplo, aproveite para observar a
configurao de mais quatro opes do widget Button:
height - serve para configurar qual a altura do boto em nmero de
linhas de texto;
width - especifica a largura do boto em quantidade de letras;
font - com esta voc pode configurar a fonte do texto do boto
atravs de uma tupla: ("tipo da fonte, "tamanho, "negrito, "itlico,
....);
fg - o mesmo que foreground. Serve para configurar a cor do texto.





I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
10
from Tkinter import *
class Janela:
def __init__(self,toplevel):
self.fr1 = Frame(toplevel)
self.fr1.pack()

self.botao1 = Button(self.fr1,text='Oi!')
self.botao1['background']='green'
self.botao1['font']=('Verdana','12','italic','bold')
self.botao1['height']=3
self.botao1.pack()

self.botao2 = Button(self.fr1,bg='red', font=('Times','16'))
self.botao2['text']='Tchau!'
self.botao2['fg']='yellow'
self.botao2['width']=12
self.botao2.pack()

raiz=Tk()
Janela(raiz)
raiz.mainloop()

Resultado:

Veja como o frame ajusta seu tamanho automaticamente para comportar os
dois botes. Observe a fonte do boto verde, Verdana tamanho 12 em itlico e negrito
(bold), e a fonte do boto vermelho, Times New Roman tamanho 16. O boto verde
possui agora trs linhas de altura enquanto o vermelho tm 12 letras de largura, alm
do seu texto ser amarelo, como foi configurado atravs da opo "fg. Antes de
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
11
prosseguirmos, faa seus prprios testes com as seis opes que aprendemos at
agora. Crie vrios botes com vrias cores, fontes e tamanhos. Ser bom que voc
tenha traquejo nestas configuraes, porque elas so muito usadas.

3. Posicionando widgets na GUI

O mais importante a observarmos no exemplo anterior a disposio que os
botes assumiram no frame. Quem determinou que o botao2 se posicionasse sob o
botao1 foi o gerenciador de geometria que usamos, o pack.
Imagine que um frame seja uma cavidade onde encaixamos os widgets. O
mtodo pack possui um argumento side capaz de assumir quatro valores, LEFT
(esquerda), RIGHT (direita), TOP (em cima) e BOTTOM (embaixo), que determinam
em que lugar da cavidade o widget deve se posicionar.
Assim que um widget posicionado, o espao restante passa a ser a nova
cavidade onde o prximo widget ser posicionado, quando aplicarmos sobre ele o
mtodo pack. No to simples observar isso porque o frame se encolhe sobre o
primeiro widget, ento o "espao restante simplesmente imaginrio. Quem sabe a
figura a seguir no esclarea um pouco a questo?

O valor padro do argumento side TOP. Por isso, quando aplicamos o
mtodo pack sobre os botes do exemplo anterior, o boto "Oi! se posiciona no topo
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
12
da cavidade, e o boto "Tchau! se posiciona no topo da cavidade restante, isto ,
abaixo do primeiro boto. Nunca aplique diferentes posicionamentos de widgets no
mesmo frame! O efeito pode ser desastroso principalmente quando o usurio resolver
redimensionar a janela (clicando no boto de maximizar, por exemplo). Em vez disso,
crie vrios frames, como no exemplo a seguir. Dentro de cada um deles, s um valor
aplicado opo side, e mesmo assim conseguimos colocar os botes em posies
variadas na GUI.

from Tkinter import *
class Packing:
def __init__(self,instancia_Tk):

self.container1=Frame(instancia_Tk)
self.container2=Frame(instancia_Tk)
self.container3=Frame(instancia_Tk)
self.container1.pack()
self.container2.pack()
self.container3.pack()

Button(self.container1,text='B1').pack()
Button(self.container2,text='B2').pack(side=LEFT)
Button(self.container2,text='B3').pack(side=LEFT)
self.b4=Button(self.container3,text='B4')
self.b5=Button(self.container3,text='B5')
self.b6=Button(self.container3,text='B6')
self.b6.pack(side=RIGHT)
self.b4.pack(side=RIGHT)
self.b5.pack(side=RIGHT)

raiz=Tk()
Packing(raiz)
raiz.mainloop()



I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
13
Resultado:

Criamos trs frames, como voc pde ver. Aplicamos pack(side=TOP) sobre
os trs, ento eles esto empilhados um sobre os outros. Como o valor padro do
argumento side TOP, no precisvamos passar isso explicitamente. Novamente
usando pack(side=TOP), criamos um boto posicionado no primeiro frame, que se
dispe no topo da sua cavidade. Dois outros botes so criados e posicionados no
segundo frame, mas desta vez com a opo pack(side=LEFT). por isso que o boto
"B2 se posiciona esquerda no frame e o boto "B3 se posiciona esquerda da
cavidade restante.
Agora preste ateno no que fizemos no terceiro frame. Trs botes foram
criados numa ordem (b4, b5, b6) e o mtodo pack(side=RIGHT) foi aplicado sobre eles
em ordem diferente. Veja que eles foram se posicionando direita na cavidade do
frame container3 na ordem em que o mtodo foi aplicado (b6, b4, b5).
Experimente! Crie vrios botes e frames, e coloque-os em disposies
diferentes na GUI; aplique o mtodo pack em ordem diferente da que os widgets
foram criados.
H vrias formas de alterao que voc pode fazer no exemplo
anterior de forma a deixa-lo como a figura a seguir. Eu consigo fazer isso
alterando apenas dois caracteres! E voc?


I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
14
Parte III - Binding

J vimos que event handlers so as aes executadas em resposta a um
evento. Estruturando nossa interface grfica em classes, podemos escrever event
handlers na forma de mtodos - funes definidas dentro da classe.
O ltimo passo atribuir o evento ao event handler. Para isso usamos o
mtodo bind atravs da sintaxe widget.bind( evento , event handler).

1. Eventos do mouse

O "evento como um clique do mouse ou o pressionamento da tecla ENTER
passado como argumento do mtodo bind como uma string. Por exemplo, se o evento
um clique com o boto esquerdo do mouse, a string "<Button-1>", e a string
correspondente ao pressionamento da tecla ENTER "<Return>".
Digamos que um mtodo chamado muda_cor deva ser executado quando
algum clicar com o boto esquerdo do mouse sobre o boto botaoverde. A sintaxe
para fazer essa conexo evento/event handler seria:
self.botaoverde.bind("<Button-1>", self.muda_cor)
o que fazemos no exemplo abaixo. Aproveitamos nosso poder de manipular
caractersticas de widgets por meio de dicionrios para alterar a cor de um boto assim
que ele clicado.
Aproveitamos a deixa para mostrar mais um tipo de widget, Label, com o qual
podemos mostrar pequenos textos na tela. O Label possui todas as opes de
configurao que voc j conhece do Button (text, width, etc.).


I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
15
from Tkinter import *
class Janela:
def __init__(self,toplevel):

self.frame=Frame(toplevel)
self.frame.pack()

self.texto=Label(self.frame, text='Clique para ficar amarelo')
self.texto['width']=26
self.texto['height']=3
self.texto.pack()

self.botaoverde=Button(self.frame,text='Clique')
self.botaoverde['background']='green'
self.botaoverde.bind("<Button-1>",self.muda_cor)
self.botaoverde.pack()

def muda_cor(self, event):
# Muda a cor do botao!
if self.botaoverde['bg']=='green':
self.botaoverde['bg']='yellow'
self.texto['text']='Clique para ficar verde'
else:
self.botaoverde['bg']='green'
self.texto['text']='Clique para ficar amarelo'

raiz=Tk()
Janela(raiz)
raiz.mainloop()

Resultado:

I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
16
Um clique no boto verde chama o mtodo muda_cor e a cor de fundo do
boto muda para amarelo. Outro clique traz de volta a cor original.
Todo evento que ocorre em Tkinter gera um objeto evento. O objeto evento
um tipo especial de objeto contendo informaes importantes sobre o evento ocorrido.
Tais informaes so fundamentais para os event handlers, por isso estes exigem que
os objetos evento sejam passados como argumento, como voc observa em
muda_cor(self, event).
Como s associamos o evento <Button-1> ao mtodo, um clique com o boto
direito do mouse no possui efeito sobre a GUI. Se quisssemos o contrrio, teramos
que usar a string <Button-3>, correspondente ao boto direito do mouse.
O primeiro argumento do mtodo bind tambm pode ser uma tupla contendo
os eventos na ordem em que eles devem ocorrer para que o event handler seja
desencadeado. Se o cdigo fosse
self.botaoverde.bind(("<Button-1>","<Button-3>"), self.muda_cor)
somente um clique com o boto esquerdo seguido de um clique no boto
direito acionaria o mtodo. Esta tcnica interessante se voc quiser associar uma
combinao de teclas a um evento.
Os widgets tambm so capazes de responder a eventos de mouse como
simplesmente passar o ponteiro do mouse sobre o widget. Faa seus experimentos
para ficar craque nisso. A string "<ButtonRelease-X>" corresponde a soltar o boto X
do mouse (X pode ser igual a 1, 2 ou 3, mas nem todos os mouses possuem o boto
do meio). A string "<Motion>" representa o evento de mover o ponteiro do mouse
sobre o widget, enquanto "<Leave>" representa a retirada do ponteiro do widget.




I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
17
2. Foco e eventos de teclado

O foco o mecanismo que indica qual widget est respondendo em
determinado momento pelos eventos de teclado. D uma olhada no gerenciador de
arquivos do seu sistema operacional (Windows Explorer, por exemplo). Se voc clicar
no nome de um arquivo, ver que ele fica em destaque - com um retngulo pontilhado
ao seu redor, talvez em azul. Este destaque o meio escolhido pelo seu sistema
operacional para indicar que aquele arquivo est em foco. Na ocasio de ocorrer o
evento "pressionar DELETE, somente o arquivo em foco ser excludo. Voc pode
passar o foco para o arquivo seguinte pressionando TAB, ou voltar o foco para o
anterior pressionando SHIFT+TAB, ou ainda clicando sobre o arquivo. Todos estes
comportamentos exibidos pelos arquivos do seu sistema operacional so apresentados
pelos widgets de Tkinter.
Um mtodo importante quando se fala em foco em Tkinter
widg1.focus_force(), usado para passar o foco para o widget widg1.
Veja na tabela a string correspondente a alguns eventos comuns de teclado.

Evento String
ENTER
"<Return>"
DELETE
"<Delete>"
Backspace
"<BackSpace>"
ESC
"<Escape>"
Seta esquerda
"<Left>"
Seta direita
"<Right>"
Seta para cima
"<Up>"
Seta para baixo
"<Down>"
O widget ganha foco
"<FocusIn>"
O foco sai do widget
"<FocusOut>"

I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
18
Use a string "<KeyPress-ALFA>" para representar o pressionamento de uma
tecla ALFA, e "<KeyRelease-ALFA>" para representar o usurio soltando esta tecla.
Vale simplificar "<KeyPress-ALFA>" como "ALFA". Falando nisso, o interpretador
tambm entende "<Button-1>" como "<1>".
H uns modificadores de evento importantes. Podemos usar os modificadores
Double e Triple para representar duas ou trs repeties de um evento em rpida
sucesso. Isto , podemos usar "<Double-Button-1>" para representar duplo clique
com o boto esquerdo do mouse ou "<Triple-KeyPress-P>" para representar triplo
pressionamento consecutivo da tecla P. O modificador Any serve para indicar o
pressionamento de qualquer tecla ou boto do mouse; as strings correspondentes
"<Any-KeyPress>" so e "<Any-Button>", respectivamente.
Vejamos um exemplo com tudo o que acabamos de falar. Agora
aprenderemos ainda trs novas opes de configurao dos botes, relief, padx e
pady. Relief serve para mudar o relevo do boto. Os valores-padro a que estamos
acostumados so SUNKEN quando o boto pressionado e RAISED, caso contrrio.
Experimente os outros valores GROOVE, RIDGE e FLAT. J padx e pady so os espaos
extras que damos entre as bordas de widgets como Button e Label e o texto contido
neles, veja:

Vamos ao cdigo... A primeira linha adicionada para que a gente possa usar
caracteres especiais, como acentos, ao longo do programa. No deixe passar
despercebido o pack-unpack que usamos para agilizar a determinao das
caractersticas dos botes.


I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
19
# -*- coding: cp1252 -*-
from Tkinter import *
class Janela:
def __init__(self,toplevel):
self.frame=Frame(toplevel)
self.frame.pack()
self.frame2=Frame(toplevel)
self.frame2.pack()

self.titulo=Label(self.frame,text='VIDENTE 2005',
font=('Verdana','13','bold'))
self.titulo.pack()

self.msg=Label(self.frame,width=40,height=6,
text = 'Adivinho o evento ocorrido!')
self.msg.focus_force()
self.msg.pack()
# Definindo o boto 1
self.b01=Button(self.frame2,text='Boto 1')
self.b01['padx'],self.b01['pady'] = 10, 5
self.b01['bg']='deepskyblue'
self.b01.bind("<Return>",self.keypress01)
self.b01.bind("<Any-Button>",self.button01)
self.b01.bind("<FocusIn>",self.fin01)
self.b01.bind("<FocusOut>",self.fout01)
self.b01['relief']=RIDGE
self.b01.pack(side=LEFT)
# Definindo o boto 2
self.b02=Button(self.frame2,text='Boto 2')
self.b02['padx'],self.b02['pady'] = 10, 5
self.b02['bg']='deepskyblue'
self.b02.bind("<Return>",self.keypress02)
self.b02.bind("<Any-Button>",self.button02)
self.b02.bind("<FocusIn>",self.fin02)
self.b02.bind("<FocusOut>",self.fout02)
self.b02['relief']=RIDGE
self.b02.pack(side=LEFT)

I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
20
def keypress01(self,event): self.msg['text']='ENTER sobre o Boto 1'
def keypress02(self,event): self.msg['text']='ENTER sobre o Boto 2'
def button01(self,event): self.msg['text']='Clique sobre o Boto 1'
def button02(self,event): self.msg['text']='Clique sobre o Boto 2'
def fin01(self,event): self.b01['relief']=FLAT
def fout01(self,event): self.b01['relief']=RIDGE
def fin02(self,event): self.b02['relief']=FLAT
def fout02(self,event): self.b02['relief']=RIDGE

raiz=Tk()
Janela(raiz)
raiz.mainloop()

Resultado:

Ao definirmos o label msg, aplicamos sobre ele o focus_force. Por isso,
quando o programa iniciado, o foco imediatamente passado para este widget. Voc
pode verificar que pressionar ENTER neste instante no chama event handler algum.
Ao pressionarmos TAB, o foco ento passado para o widget definido logo aps msg,
que o Boto 1. Voc poderia ver isto pelo retngulo que circundaria o texto do boto.
Agora sim, como relacionamos o pressionamento de ENTER sobre o Boto 1 ao event
handler keypress01, este mtodo ser chamado, alterando o label msg.
No deixe de notar que ligamos os eventos <FocusIn> e <FocusOut> ao
Boto 1. por isso que o relevo do boto muda no instante que o foco dado ou
retirado dele.
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
21
Conseguimos a disposio mostrada pela GUI (texto sobre texto e boto ao
lado de boto) por meio da definio de dois frames. Lembre-se de nunca misturar a
orientao do mtodo pack no mesmo frame!

3. Command binding

Talvez voc tenha percebido que quando se associa <Button-1> a um event
handler, no necessrio soltar o boto do mouse para que o mtodo seja executado.
O pressionamento do boto do mouse j chama o event handler. Isto ocorre porque os
eventos de clicar e soltar o boto do mouse num widget so eventos diferentes em
Tkinter. A propsito, se voc precisar associar o evento de soltar o boto do mouse a
um event handler, a string "<ButtonRelease>".
O evento mais comum, mais esperado, quando se fala em interfaces grficas,
o clique do mouse (desta vez, falamos de clique "completo - clicar e soltar o boto
do mouse), ento deve haver uma forma mais rpida de se associar este evento
corriqueiro a um event handler, sem a necessidade de aplicar o mtodo bind... De fato,
h: o command binding. Este recurso permite associar o clique do mouse sobre um
widget durante a prpria definio do widget, como a seguir:
Widget(master, ...., command = self.event_handler)
No fim das contas, este binding se comporta como uma opo de
configurao do widget, podendo ser designada atravs da sintaxe de dicionrios:
self.nome_do_widget['command']=self.event_handler
Uma caracterstica importante quando se usa este processo de associao
que desta vez o objeto evento (event) no precisa ser passado como argumento do
event handler.
O exemplo seguinte confronta as duas maneiras de associao de eventos que
agora conhecemos.

I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
22
from Tkinter import *
class Janela:
def __init__(self,toplevel):

self.frame=Frame(toplevel)
self.frame.pack()

self.b1=Button(self.frame)
self.b1.bind("<Button-1>", self.press_b1)
self.b1.bind("<ButtonRelease>", self.release_b1)
self.b1['text'] = 'Clique em mim!'
self.b1['width'], self.b1['bg'] = 20, 'brown'
self.b1['fg']='yellow'
self.b1.pack(side=LEFT)

self.b2=Button(self.frame)
self.b2['width'], self.b2['bg'] = 20, 'brown'
self.b2['fg']='yellow'
self.b2.pack(side=LEFT)

self.b3=Button(self.frame, command=self.click_b3)
self.b3['width'], self.b3['bg'] = 20, 'brown'
self.b3['fg']='yellow'
self.b3.pack(side=LEFT)

def press_b1(self,event):
self.b1['text']=''
self.b2['text']='Errou! Estou aqui!'
def release_b1(self,event):
self.b2['text']=''
self.b3['text']='OOOpa! Mudei de novo!'
def click_b3(self):
self.b3['text']='Ok... Voc me pegou...'

instancia=Tk()
Janela(instancia)
instancia.mainloop()
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
23
Resultado:

O boto da esquerda chama um event handler da forma que j conhecamos.
Clique nele sem soltar o boto do mouse e voc ver que o texto do boto central j
modificado. Solte o boto do mouse e os textos mudaro novamente. O mesmo no
acontece com o boto da direita. Clique nele sem soltar e voc ver que nada acontece
at que o boto do mouse seja solto.

Parte IV - Campos de Dados

1. O widget Entry

O widget Entry um meio de recolher entradas de dados do usurio. Os
dados informados pelo usurio neste campo so captados em forma de string,
exatamente como a nossa conhecida funo raw_input faz. Atravs do mtodo get,
fornecido pelo Entry, podemos trabalhar com os dados de entrada dentro do cdigo.
O Entry aceita todas as opes de configurao que j vimos com botes e
labels, exceto height (porque a altura dos campos de dados sempre de uma linha).
Em campos de entrada de senhas, em que o texto digitado no pode aparecer na tela,
podemos usar a opo show. Por exemplo, show = '*' exibir um asterisco na tela,
em vez do caractere que o usurio est digitando.
O exemplo seguinte mostra um dispositivo para checagem de senhas.
Observe como o mtodo get usado para recolher os valores fornecidos pelo usurio
nos campos e a aplicao do mtodo show para esconder a senha. Note que podemos
usar a opo pady na configurao de um frame para dar um espao extra entre suas
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
24
bordas e os widgets dentro dele (caso contrrio o boto ficaria colado ao campo de
entrada de dados).

from Tkinter import *
class Passwords:
def __init__(self,toplevel):

self.frame1=Frame(toplevel)
self.frame1.pack()
self.frame2=Frame(toplevel)
self.frame2.pack()
self.frame3=Frame(toplevel)
self.frame3.pack()
self.frame4=Frame(toplevel,pady=10)
self.frame4.pack()

Label(self.frame1,text='PASSWORDS', fg='darkblue',
font=('Verdana','14','bold'), height=3).pack()

fonte1=('Verdana','10','bold')
Label(self.frame2,text='Nome: ',
font=fonte1,width=8).pack(side=LEFT)
self.nome=Entry(self.frame2,width=10,
font=fonte1)
self.nome.focus_force() # Para o foco comear neste campo
self.nome.pack(side=LEFT)

Label(self.frame3,text='Senha: ',
font=fonte1,width=8).pack(side=LEFT)
self.senha=Entry(self.frame3,width=10,show='*',
font=fonte1)
self.senha.pack(side=LEFT)

self.confere=Button(self.frame4, font=fonte1, text='Conferir',
bg='pink', command=self.conferir)
self.confere.pack()
self.msg=Label(self.frame4,font=fonte1,
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
25
height=3,text='AGUARDANDO...')
self.msg.pack()

def conferir(self):
NOME=self.nome.get()
SENHA=self.senha.get()
if NOME == SENHA:
self.msg['text']='ACESSO PERMITIDO'
self.msg['fg']='darkgreen'
else:
self.msg['text']='ACESSO NEGADO'
self.msg['fg']='red'
self.nome.focus_force()

instancia=Tk()
Passwords(instancia)
instancia.mainloop()

Resultado:


Responda rpido: o que digitei no campo de senha no caso acima?
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
26
Parte V - Canvas

O Canvas um widget importantssimo para a rea cientfica e engenharia.
Com ele podemos fazer simulaes, plotagens, desenhos, criar nossos prprios
widgets, e at mesmo pequenas animaes, respeitando a velocidade de
processamento do seu amigo PC. Imagine o canvas como uma prancheta onde voc
pode desenhar objetos como linhas, arcos, crculos e polgonos vontade. Aqui
veremos os principais tipos de objetos oferecidos pelo canvas do Tkinter: arco, linha,
elipse, polgono, retngulo e texto.
Define-se um Canvas como se define qualquer outro widget. Ele tem as
mesmas opes de configurao que botes e labels, inclusive duas que veremos no
prximo exemplo: bd e cursor. Com a opo bd podemos especificar a espessura da
borda de um widget, em pixels. Cursor, por sua vez, diz ao interpretador como deve
aparecer o ponteiro do mouse quando ele estiver sobre o widget. Alguns valores
disponveis so X_cursor, circle, dot, dotbox, fleur e target. So 77 opes de cursor
vlidas para qualquer widget e voc pode conhecer todas elas atravs dos livros
recomendados ao final deste Mdulo.
No exemplo voc percebe que no somos escravos do continer frame. J que
s definimos dois widgets simples, pudemos cria-los diretamente na janela top-level.
Aqui voc aprende duas novas cores para enriquecer o seu vocabulrio.

from Tkinter import *
class Kanvas:
def __init__(self,raiz):

self.canvas1 = Canvas(raiz, width=100, height=200,
cursor='X_cursor', bd=5,
bg='dodgerblue')
self.canvas1.pack(side=LEFT)
self.canvas2 = Canvas(raiz, width=100, height=200,
cursor='dot', bd=5,
bg='purple')
self.canvas2.pack(side=LEFT)
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
27
instancia=Tk()
Kanvas(instancia)
instancia.mainloop()

Resultado:

O espao cinza que separa os cnvases e d uma folga entre eles e a borda
da janela devido opo bd que utilizamos.
uma pena que no d para mostrar os cursores na figura acima, mas
implemente o exemplo e voc ver como fica bonita a combinao - parece at um
jogo, um pingue-pongue ou batalha naval...

1. Coordenadas

Tragicamente, o sistema de coordenadas do Canvas no igual ao cartesiano.
Isso torna um pouco trabalhoso desenhar a maioria das figuras.
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
28

Costumo usar um recurso para contornar este problema. Ao definir um par
contendo as coordenadas x e y de um desenho, lembre-se de que o par (x, yc) em
coordenadas cartesianas corresponde a (x, altura - yc) em coordenadas do Canvas,
sendo altura a altura do canvas. Difcil? Veja o exemplo:

A altura desse canvas 100. As coordenadas cartesianas do ponto P so (10,
90). Assim, a converso para coordenadas do Canvas ficar (10, 100 - 90) = (10, 10).
Usar esta forma ou simplesmente determinar as coordenadas diretamente nos
termos do sistema do Canvas apresentam mais ou menos a mesma dificuldade;
escolha a que mais agradar.
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
29
2. Linhas

A sintaxe para desenhar uma linha num canvas
self.nome_do_canvas.create_line(x1, y1, ...., xn, yn)
Esta linha comea no ponto (x1, y1), segue at o ponto (x2, y2), (x3, y3) e
assim por diante at terminar em (xn, yn). Os pontos podem ser passados
isoladamente, ou em grupos dentro de tuplas ou listas, desse jeito:
create_line(x1, y1, x2, y2, x3, y3, x4, y4, ......) ou
create_line((x1, y1), (x2, y2), (x3, y3), (x4, y4), ......) ou
create_line((x1, y1, x2, y2), (x3, y3, x4, y4), ......), e todas
estas tuplas tambm poderiam ser listas. Isto facilita imensamente o trabalho quando
os pontos de que dispomos j so tuplas ou listas. Ou seja, para desenhar uma linha
entre P1 = (x1, y1) e P2 = (x2, y2), basta fazer create_line(P1, P2). Sem este recurso,
teramos que usar a intragvel sentena create_line(P1[0], P1[1], P2[0], P2[1])...
Aps esta seqncia de pontos dizendo por onde a linha dever seguir, ainda
podem vir algumas opes de configurao. As principais so width, que determina a
espessura da linha e fill, para especificarmos sua cor.
No exemplo, h uma linha que comea no centro do canvas. Um trecho de
comprimento 10 desenhado na direo que o usurio indicar nos botes. Note que
definimos um atributo para instncia de Tk, self.last, que servir para guardar a ltima
posio assumida pela linha e incrementa-la mais facilmente.
Se vrios widgets compartilharo as mesmas opes de configurao, voc
pode salva-las todas num dicionrio e passa-lo como argumento na definio destes
widgets. Por ltimo, note que ordenamos que quando o ponteiro do mouse estiver
sobre o canvas, dever aparecer a ampulheta (watch).

I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
30

from Tkinter import *
class Linhas:
def __init__(self,raiz):
self.canvas = Canvas(raiz, width=400, height=400,
cursor='watch', bd=5)
self.canvas.pack()
self.frame=Frame(raiz)
self.frame.pack()

self.last=[200,200]

configs={'fg':'darkblue', 'bg':'ghostwhite', 'relief':GROOVE,
'width':11,'font':('Verdana','8','bold')}
self.b1=Button(self.frame, configs,
text='Esquerda', command=self.left)
self.b1.pack(side=LEFT)
self.b2=Button(self.frame, configs,
text='Para cima', command=self.up)
self.b2.pack(side=LEFT)
self.b3=Button(self.frame, configs,
text='Para baixo', command=self.down)
self.b3.pack(side=LEFT)
self.b4=Button(self.frame, configs,
text='Direita', command=self.right)
self.b4.pack(side=LEFT)

def left(self): # Desenha um segmento para a esquerda
x, y = self.last[0]-10, self.last[1]
self.canvas.create_line(self.last, x, y, fill='red')
self.last=[x,y]
def up(self): # Desenha um segmento para cima
x, y = self.last[0], self.last[1]-10
self.canvas.create_line(self.last, x, y, fill='yellow')
self.last=[x,y]
def down(self): # Desenha um segmento para baixo
x, y = self.last[0], self.last[1]+10
self.canvas.create_line(self.last, x, y, fill='blue')
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
31
self.last=[x,y]
def right(self): # Desenha um segmento para a direita
x, y = self.last[0]+10, self.last[1]
self.canvas.create_line(self.last, x, y, fill='purple')
self.last=[x,y]

instancia=Tk()
Linhas(instancia)
instancia.mainloop()

Resultado: a GUI resultante grande demais para ser mostrada aqui e sua
aparncia no to instrutiva quanto seu funcionamento. Implemente este exemplo e
veja quantos desenhos interessantes voc pode fazer com este pequeno cdigo
(pequeno relativo aos programas em Tkinter).
Aqui no usamos nossa ttica de converso cartesiano-canvas porque este
um exemplo simples. Usaremos em outros exemplos.

3. Polgonos, retngulos e textos

Desenhamos um polgono num canvas como desenhamos linhas. A diferena
que o mtodo aplicado ao canvas se chama create_polygon e que a linha dever
terminar no ponto em que comeou. O interpretador reconhece que a rea interna a
esse permetro fechado o interior do polgono e capaz de preench-lo com uma cor
definida pela opo fill. Se o que voc quer mudar a cor e espessura da linha
externa, pode usar as opes outline e width.
Retngulos so ainda mais fceis de desenhar. S precisamos informar as
coordenadas de dois vrtices opostos e pronto! O mtodo o create_rectangle e pode
ser aplicado ao desenho de quadrados. As opes fill, width e outline tambm esto
disponveis.
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
32
Podemos adicionar textos aos canvas de uma maneira bem simples. Sintaxe:
self.nome_do_canvas.create_text(x, y)
O texto, definido pela opo text, ser posicionado em (x,y). Imagine que o
texto a ser mostrado esteja contido num retngulo, como na figura abaixo.

Atravs da opo anchor, podemos especificar qual destes pontos do
retngulo est sobre a coordenada (x,y) que informamos. Digamos que anchor=SW e
definimos a posio do texto em (100, 100). Assim, a borda esquerda inferior do texto
ficar em (100, 100). O valor padro de anchor CENTER.
A opo font que j conhecemos dos botes e labels tambm pode ser
aplicada aqui, e a cor do texto pode ser mudada com a opo fill.
A menos que seja definido um valor para a opo width, o texto ser escrito
todo em uma nica linha. Com width determinamos o comprimento mximo que as
linhas de texto podem assumir. Se necessrio, a sentena quebrada entre as
palavras para cumprir esta configurao. Quando isto ocorre, pode ser interessante
definir que alinhamento as linhas devem assumir entre si. A opo que determina isso
justify, cujos valores so LEFT (alinhadas esquerda - o valor padro), CENTER
(centralizadas) e RIGHT (alinhadas direita).
No prximo exemplo usamos a tcnica de converso cartesinana-canvas.
Precisamos desenhar um pentgono usando create_polygon e nos pareceu maante ter
que pensar nas coordenadas das cinco pontas em termos do Canvas. Melhor projetar o
pentgono como estamos acostumados e depois converter os valores. Veja o projeto
em coordenadas cartesianas:
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
33

Este pentgono ser desenhado num canvas de altura 200. Dessa forma, a
coordenada (100, 10) ter que ser implementada como (100, 200-10) = (100, 190), e
assim por diante. Claro que no fizemos todas estas continhas para cada par
ordenado; simplesmente salvamos a altura 200 sob o nome altura e simplesmente
escrevemos nossas coordenadas cartesianas como (100, altura - 10), por exemplo.
Neste programa importante observar que atribumos toda a sentena
self.canvas.create_polygon a um nome, pol, para agilizar o uso deste mtodo.

from Tkinter import *
class SPFC:
def __init__(self,raiz):
self.canvas=Canvas(raiz, width=200, height=200, bg='dodgerblue')
self.canvas.pack()

altura = 200 # Altura do canvas

pol=self.canvas.create_polygon
ret=self.canvas.create_rectangle
pol(100, altura-10,
10, altura-145,
10, altura-190,
190, altura-190,
190, altura-145,
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
34
100, altura-10, fill='white')
ret(15, altura-150, 185, altura-185, fill='black')
pol(20, altura-140,
95, altura-140,
95, altura-30,
20, altura-140, fill='red')
pol(105, altura-30,
105, altura-140,
180, altura-140,
105, altura-30, fill='black')
self.canvas.create_text(100, altura-167.5, text='S P F C',
font=('Arial','26','bold'),
anchor=CENTER, fill='white')

instancia=Tk()
SPFC(instancia)
instancia.mainloop()

Resultado:

J vou avisando que no sou so-paulino! Simplesmente o logotipo me
pareceu fcil de desenhar. Alis, acho que um torcedor de verdade no desenharia seu
logotipo do corao to desproporcional...
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
35
Note que definimos as coordenadas do texto "SPFC como sendo o centro do
retngulo branco. Ao definirmos anchor = CENTER (no seria necessrio, j que este
o valor padro), garantimos de uma forma simples que o texto ficasse centralizado no
retngulo. Mude os valores da opo anchor e veja como o texto se comporta.

4. Elipses e arcos

Quando usamos o mtodo create_oval para desenhar elipses, trabalhamos
com os mesmos conceitos de create_rectangle. Desta vez, forneceremos as
coordenadas de vrtices opostos de um retngulo imaginrio, dentro do qual ficar a
elipse desejada, como mostra a figura seguinte.

Podemos fornecer as coordenadas de dois vrtices quaisquer do retngulo,
desde que eles sejam opostos.
Usa-se o mesmo recurso para desenhar crculos; a diferena que neste caso
o retngulo ser um quadrado.
O desenho de arcos acontece de forma semelhante. As coordenadas dos
vrtices do retngulo que contero o arco devem ser informadas, mas so as opes
de configurao que vo determinar a aparncia do arco. Considere o centro do
retngulo como o centro de curvatura do arco:

I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
36
Por meio da opo start, dada em graus a partir do eixo x positivo e em
sentido anti-horrio, determinamos qual a linha a partir da qual o arco comea a ser
desenhado. Exemplo: na figura acima, faramos start=60.
A outra opo fundamental extent, dada em graus a partir da linha de incio
e em sentido anti-horrio, para determinar at que linha o arco ser desenhado. Veja
na prxima figura o exemplo usando extent=90 e o arco j desenhado.

Por ltimo, h a opo style para determinar o estilo do arco. Os valores
podem ser ARC, CHORD e PIESLICE (o padro).

O exemplo seguinte um programinha para crianas aprenderem
porcentagens com tortas. Estamos acostumados a salvar o valor da altura do canvas
num nome para facilitar nosso senso de coordenadas. Como este valor tambm
usado dentro de um event handler, melhor transformar esta altura num atributo da
instncia por meio de self.altura. No deixe de notar tambm:
A tupla contendo as configuraes de fonte que seriam usadas em vrios
widgets foi salva sob um nome, s para no termos que reescreve-la toda
hora;
O valor de porcentagem p dado pelo usurio convertido em termos de
porcentagem do crculo (quantos graus equivalem a p por cento de 360?)
dentro do event handler. Para isso necessrio converter em float a string
informada. Nunca se esquea de que qualquer valor digitado no widget Entry
uma string!;
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
37
Logo depois de o arco ser desenhado, o event handler retorna o foco
para o campo de dados.

# -*- coding: cp1252 -*-
from Tkinter import *
class Fatias:
def __init__(self,raiz):
self.canvas=Canvas(raiz, width=200, height=200)
self.canvas.pack()
self.frame=Frame(raiz)
self.frame.pack()

self.altura = 200 # Altura do canvas

self.canvas.create_oval(25, self.altura-25,
175, self.altura-175,
fill='deepskyblue', outline='darkblue')
fonte=('Comic Sans MS', '14', 'bold')
Label(self.frame, text='Fatia: ',
font=fonte, fg='blue').pack(side=LEFT)
self.porcentagem=Entry(self.frame, fg='red',
font=fonte, width=5)
self.porcentagem.focus_force()
self.porcentagem.pack(side=LEFT)
Label(self.frame, text='%',
font=fonte, fg='blue').pack(side=LEFT)
self.botao=Button(self.frame, text='Desenhar',
command=self.cortar, font=fonte,
fg='darkblue', bg='deepskyblue')
self.botao.pack(side=LEFT)

def cortar(self):

arco=self.canvas.create_arc
fatia=float(self.porcentagem.get())*359.9/100.
arco(25, self.altura-25,
175, self.altura-175,
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
38
fill='yellow', outline='red',
extent=fatia)
self.porcentagem.focus_force()

instancia=Tk()
Fatias(instancia)
instancia.mainloop()

Resultado:

Na figura acima vemos o programa mostrando uma fatia de 56% da torta.
Veja como as letras so grandes e coloridas - tudo direcionado ao pblico infantil que
usaria esta GUI.
uma pena que toda vez que a gente queira representar uma nova
porcentagem, tenha que fechar esta janela e abrir outra. Como ser que faramos para
apagar o arco que representa essa fatia de 56% e desenhar outro com porcentagem
qualquer?


I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
39
5. Gerenciamento de objetos do Canvas

Assim que um objeto criado num canvas, recebe automaticamente um ID -
um nmero inteiro para diferencia-lo dos demais. O n-simo objeto desenhado tem ID
n. Quando se insere um objeto num canvas, ele se dispe sobre os desenhados
anteriormente. Assim, os menores IDs pertencem aos objetos que esto mais prximo
do fundo do canvas (o "background):

O canvas oferece dois mtodos muito importantes para gerenciar seus
objetos: find_all(), que retorna uma tupla com o ID de todos os objetos e delete(X1,
X2, ...., Xn) que apaga do canvas os objetos de ID X1, X2, ..., Xn. Este ltimo mtodo
capaz de receber os IDs em forma de strings de inteiros, isto , "1, "2, etc.
Num canvas com dezenas de objetos, algum pode ter relevncia grande
demais para ser identificado simplesmente com um nmero. Por isso, tambm
podemos identificar os objetos por meio de strings chamadas tags. A rigor, tag se
comporta como uma opo de configurao definida no instante em que os widgets
so criados. Se voc quer criar um crculo e cham-lo de "bola1, basta fazer
self.nome_do_canvas.create_oval(coord., opes, tag = "bola1")
A tag de um objeto tambm pode ser usada como argumento do mtodo
delete, alm do ID.
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
40
Discusso importante: quando desenhamos uma linha, ser que cada
segmento recebe um ID, ou a linha toda possui a mesma identificao? Uma forma de
no errar nunca este tipo de questo lembrar-se de que cada aplicao de um
mtodo como create_line e create_polygon gera somente um ID (ou tag, se voc
quiser) que nomeia toda a seqncia de segmentos, por maior que seja. Por isso tome
cuidado ao criar uma linha repleta de segmentos com uma nica aplicao do mtodo
gerador, porque o mtodo delete apagaria todos eles!
No prximo exemplo fazemos um relgio de verdade! Ele usa uma funo do
mdulo time para saber que horas so no seu computador, e mostra isso numa
simulao (feia, verdade) de um rdio-relgio. Veja como a opo outline = ''
usada para determinar que a borda das figuras seja transparente.

# -*- coding: cp1252 -*-
from Tkinter import *
from time import localtime
class Horas:
def __init__(self,raiz):

self.canvas=Canvas(raiz, width=200, height=100)
self.canvas.pack()
self.frame=Frame(raiz)
self.frame.pack()

self.altura = 100 # Altura do canvas

# Desenho do relgio-----------------------------
pol=self.canvas.create_polygon
ret=self.canvas.create_rectangle
self.texto=self.canvas.create_text
self.fonte=('BankGothic Md BT','20','bold')
pol(10, self.altura-10,
40, self.altura-90,
160, self.altura-90,
190, self.altura-10, fill='darkblue')
pol(18, self.altura-15,
45, self.altura-85,
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
41
155, self.altura-85,
182, self.altura-15, fill='dodgerblue')
ret(45, self.altura-35,
90, self.altura-60, fill='darkblue', outline='')
ret(110, self.altura-35,
155, self.altura-60, fill='darkblue', outline='')
self.texto(100, self.altura-50, text=':',
font=self.fonte, fill='yellow')
# Fim do desenho do relgio-----------------------

self.mostrar=Button(self.frame, text='Que horas so?',
command=self.mostra,
font=('Comic Sans MS', '11', 'bold'),
fg='darkblue', bg='deepskyblue')
self.mostrar.pack(side=LEFT)

def mostra(self):

self.canvas.delete('digitos_HORA')
self.canvas.delete('digitos_MIN')
HORA = str( localtime()[3] )
MINUTO = str( localtime()[4] )
self.texto(67.5, self.altura-50, text=HORA, fill='yellow',
font=self.fonte, tag='digitos_HORA')
self.texto(132.5, self.altura-50, text=MINUTO, fill='yellow',
font=self.fonte, tag='digitos_MIN')

instancia=Tk()
Horas(instancia)
instancia.mainloop()




I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
42
Resultado:

Quando perguntamos a hora, necessrio que o event handler
correspondente apague o valor mostrado, seno os textos ficariam sobrepostos. Por
isso, demos um nome (uma tag) aos textos correspondentes s horas e aos minutos.
Dessa forma, somos capazes de apagar somente estes dois objetos, sem ter que
redesenhar todo o rdio-relgio, que composto de vrios polgonos, retngulos e um
texto que mostra os dois pontos entre as horas e os minutos (em amarelo na GUI).

O chato nessa GUI que voc tem que esperar um minuto para o
valor mudar... Redesenhe o relgio para mostrar horas, minutos e segundos!
V pensando a como voc escreveria a GUI de um relgio de
ponteiros. No precisa implementar porque h um exerccio adiante que pede
isso, mas v separando na sua cabea os ingredientes necessrios!

Os widgets como botes e entries esto para o frame assim como os objetos
de desenho esto para o canvas. Isso faz do Canvas um continer de comportamento
semelhante ao frame, inclusive o foco de teclado no passa por ele. No entanto, por
meio da opo de configurao takefocus=1, podemos inclui-lo na lista dos widgets por
onde o foco passar. Assim podemos atribuir eventos de teclado sobre um canvas, por
exemplo, para mover um de seus objetos para a direita quando o usurio pressionar
[].
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
43
Quer dizer que possvel mover um objeto do Canvas??? Pois ... O Canvas
possui um mtodo, move(tag ou ID, incX, incY), que desloca o objeto cuja tag ou ID
foi dada de uma posio (X, Y) para uma nova posio (X + incX, Y + incY).
Opa!!! No vamos nos esquecer que o sistema de coordenadas do Canvas
de cabea para baixo! Um incremento Y positivo faria o objeto descer no canvas e
nosso crebro cartesiano pirar. Se voc quiser que o objeto suba incY em vez de
descer este valor, basta informar um valor negativo para este incremento.
O prximo exemplo mostra ainda o mtodo focus(tag ou ID), com o qual
podemos passar o foco para um objeto do canvas. Observe tambm uma tcnica
fantstica de "agrupar objetos: se atribuirmos a mesma tag a vrios objetos, qualquer
ao executada sobre a tag ser sentida por todo o grupo de objetos.

from Tkinter import *
class Pacman:
def __init__(self, raiz):
self.canvas=Canvas(raiz, height=200, width=200,
takefocus=1, bg='deepskyblue',
highlightthickness=0)
self.canvas.bind('<Left>', self.esquerda)
self.canvas.bind('<Right>', self.direita)
self.canvas.bind('<Up>', self.cima)
self.canvas.bind('<Down>', self.baixo)
self.canvas.focus_force()
self.canvas.pack()

# Desenho da carinha----------------------------------
self.canvas.create_oval(90, 90, 110, 110,
tag='bola', fill='yellow')
self.canvas.create_oval(93, 100, 98, 95,
tag='bola', fill='blue')
self.canvas.create_oval(102, 100, 107, 95,
tag='bola', fill='blue')
self.canvas.create_arc(92, 87, 108, 107, tag='bola',
start=220, extent=100, style=ARC)
# Fim do desenho da carinha----------------------------
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
44
def esquerda(self, event): self.canvas.move('bola', -10, 0)
def direita(self, event): self.canvas.move('bola', 10, 0)
def cima(self, event): self.canvas.move('bola', 0, -10)
def baixo(self, event): self.canvas.move('bola', 0, 10)

instancia=Tk()
Pacman(instancia)
instancia.mainloop()

Resultado:

A opo highlightthickness pode ser aplicada a qualquer widget e serve para
determinar a espessura da linha daquele retngulo que mostra que o widget est em
foco. Neste canvas, dizemos que a espessura dessa linha zero para evitar que a sua
cor padro (preto) estragasse a aparncia da GUI. Embora o retngulo no aparea, o
canvas aqui est sempre em foco.
Tanto a rosto amarelo quando os olhos azuis e a boca dessa carinha foram
atribudos mesma tag "bola. Assim, os event handlers podem mover todo o
conjunto de uma vez s, simplesmente se referindo a essa tag.
Ateno! O uso continuado do command binding pode nos fazer esquecer de
que quando usamos o processo de event binding (por meio do mtodo bind) somos
obrigados a passar o objeto evento como argumento dos event handlers. Este
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
45
argumento se faz necessrio neste exemplo porque atribumos o uso das quatro teclas
direcionais do teclado aos mtodos.

Parte VI - Recursos Diversos

Vejamos uma miscelnea de recursos interessantes que Tkinter oferece...

1. Mtodos da janela Top-level

A janela top-level tambm possui opes de configurao. Por exemplo, voc
tambm pode definir que tipo de cursor deve aparecer quando o ponteiro do mouse
estiver sobre ela, pode definir largura e altura da janela, ou ainda o seu relevo, tudo
exatamente como estamos acostumados a fazer com widgets.
H trs mtodos que dizem respeito ao tamanho da janela. Com o primeiro,
maxsize(width=largura_mxima, height=altura_mxima), escolhemos qual o tamanho
mximo admitido pela janela. possvel impedir, por exemplo, que um clique no boto
maximizar estenda a janela pela tela toda. O contrrio tambm vale. O mtodo
minsize(width=largura_mnima, height=altura_mnima) determina que a janela no
tenha dimenses menores que as dadas. Isto pode ser til para evitar que o usurio
redimensione a janela e esconda acidentalmente algum widget. Por fim, com o mtodo
resizable atribumos um booleano aos parmetros width e height para dizer se a janela
poder ou no ser redirecionada na largura ou na altura. Por exemplo,
resizable(width=True, height=False) determina que a janela pode ter somente sua
largura (width) aumentada ou diminuda pelo usurio.
Para completar, o mtodo title o responsvel pelo ttulo da janela, que
aparece tanto na barra de ttulo quanto no rodap do seu monitor quando a janela
minimizada. O parmetro esperado uma string.
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
46
O exemplo seguinte ilustra duas janelas. A primeira no pode ser
redimensionada e a outra possui tamanhos mximo e mnimo. O Canvas definido s
para que o tamanho inicial da janela no seja o padro. Note que criamos duas
classes, uma para cada janela, e tambm duas instncias diferentes da classe Tk. O
mtodo mainloop aplicado a cada uma delas.

# -*- coding: cp1252 -*-
from Tkinter import *
class Nao_Redimensiona:
def __init__(self,janela):
janela.resizable(width=False, height=False)
janela.title('No redimensiona!')
Canvas(janela, width=200, height=100, bg='moccasin').pack()

class Tamanhos_Limite:
def __init__(self,janela):
janela.maxsize(width=300, height=300)
janela.minsize(width=50, height=50)
janela.title('Tamanhos limitados!')
Canvas(janela, width=200, height=100, bg='moccasin').pack()

inst1, inst2 = Tk(), Tk()
Nao_Redimensiona(inst1)
Tamanhos_Limite(inst2)
inst1.mainloop()
inst2.mainloop()

Resultado:

I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
47
Repare: quando ordenamos que a janela no seja redimensionvel para lado
nenhum, o boto maximizar da barra de ttulo sequer aparece! Por outro lado, quando
clicamos no boto maximizar da outra janela, ela assume imediatamente o tamanho
mximo permitido, 300 por 300.
Repare tambm como o Canvas se mantm impassvel s mudanas de
tamanho da janela top-level. para que voc notasse isso que tornamo-lo colorido.

2. Colorindo a GUI

Ao longo dos exemplos deste Mdulo, voc ficou conhecendo algumas opes
de cores que o Tkinter admite para os itens da interface grfica. So elas: white, blue,
black, green, red, yellow, brown, pink, purple, darkgreen, e mesmo umas de nomes
esquisitos como moccasin, deepskyblue (azul cu profundo), dodgerblue (azul
"esquivo?) e ghostwhite (branco fantasma). Experimente tambm navajowhite
(parecida demais com o moccasin), limegreen (um verde bonito, mas muito berrante),
floralwhite e papayawhip. Todas estas cores de nomes compostos podem ser escritas
tambm como Navajo White, navajo white ou NavajoWhite. Voc pode encontrar mais
nomes de cores interessantes na internet.
Alm destes nomes prticos, Tkinter admite que as cores sejam dadas pelo
formato RGB. O sistema um pouco chato porque a intensidade das cores vermelho,
verde e azul que formaro a cor desejada tem que ser dada em nmeros
hexadecimais. H uma ttica para resolver isso apresentada pelo livro "An Introduction
to Tkinter. Simplesmente faa:
"#%02x%02x%02x" % (intens_vermelho, intens_verde, intens_azul)
A tupla contm a intensidade das cores bsicas na forma de inteiros entre 0 e
255. A string resultante (parecida com #38c602) pode ser usada como parmetro no
lugar do nome das cores, quando voc quiser definir um widget. Para produzir o
branco, basta usar intensidade mxima das cores - (255, 255, 255), e o preto
formado pela intensidade mnima - (0, 0, 0).
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
48
O programa seguinte no s um exemplo para aprendizado; ele servir
tambm para voc fazer combinaes de intensidade de cores bsicas at achar uma
combinao interessante para sua GUI. Nele, a cor do crculo central calculada por
meio da tcnica mostrada acima, a partir da intensidade de cores informadas pelo
usurio. Voc pode checar se o resultado ficou agradvel pelo prprio crculo. Se
gostar, s copiar a string mostrada direita do boto e usar no seu cdigo.

from Tkinter import *
class Palheta:
def __init__(self,raiz):

raiz.title("Palheta")
self.canvas=Canvas(raiz, width=200, height=200)
self.canvas.pack()
self.frame=Frame(raiz)
self.frame.pack()

self.canvas.create_oval(15, 15, 185, 185,
fill='white', tag='bola')

Label(self.frame,text='Vermelho: ').pack(side=LEFT)
self.vermelho=Entry(self.frame, width=4)
self.vermelho.focus_force()
self.vermelho.pack(side=LEFT)
Label(self.frame,text='Verde: ').pack(side=LEFT)
self.verde=Entry(self.frame, width=4)
self.verde.pack(side=LEFT)
Label(self.frame,text='Azul: ').pack(side=LEFT)
self.azul=Entry(self.frame, width=4)
self.azul.pack(side=LEFT)

Button(self.frame, text='Mostrar',
command=self.misturar).pack(side=LEFT)

self.rgb=Label(self.frame, text='', width=8,
font=('Verdana','10','bold'))
self.rgb.pack()
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
49
def misturar(self):
cor="#%02x%02x%02x" %(int(self.vermelho.get()),
int(self.verde.get()),
int(self.azul.get()))
self.canvas.delete('bola')
self.canvas.create_oval(15, 15, 185, 185,
fill=cor, tag='bola')
self.rgb['text'] = cor
self.vermelho.focus_force()

inst = Tk()
Palheta(inst)
inst.mainloop()

Resultado:

Se voc gostou desse amarelo meio esverdeado com um toque (pequeno) de
azul e quer coloca-lo como cor de fundo de um boto, s fazer bg = #fded62.
Faa um tratamento de erros adequado para evitar que o usurio entre
com valores fora da faixa 0-255 ou com tipos invlidos de dados.
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
50
3. Como descobrir a posio do mouse

Todos os widgets possuem quatro mtodos que atuando em conjunto
permitem determinar a posio em que um clique ocorreu. Os exemplos sero dados
atravs de cnvases porque nesse tipo de widgets estes procedimentos so mais teis,
mas os mesmos conceitos valem para qualquer widget.
Os mtodos winfo_rootx() e winfo_rooty() retornam as coordenadas x e y do
canto noroeste do canvas em relao a um sistema de coordenadas do seu mestre (um
frame ou a prpria janela top-level), cuja posio e orientao no vem ao caso. Os
outros dois, winfo_pointerx() e winfo_pointery(), do a posio em que ocorreu um
clique em relao ao sistema "desconhecido de coordenadas do seu mestre. O pulo do
gato que a simples subtrao do resultado destes quatro mtodos nos d a posio
do clique em termos do sistema de coordenadas do Canvas, nosso velho amigo.
Seja C1 um canvas na sua aplicao grfica. Seja
x_absoluto = C1.winfo_pointerx() e
x_origem = C1.winfo_rootx(). Ento, x_absoluto - x_origem o ponto em
questo no sistema de coordenadas do Canvas.
Passou pela sua cabea a utilidade de descobrir a posio em que ocorreu o
clique? Se no, veja uma das utilidades mais bsicas com o prximo exemplo. Nele,
usamos esta tcnica para permitir ao usurio desenhar linhas vontade, simplesmente
clicando em dois pontos na tela. As coordenadas de desenho da linha so retiradas da
posio dos cliques do usurio.

from Tkinter import *
class AutoCADE:
def __init__(self, raiz):
raiz.title('AutoCAD')
self.canvas=Canvas(raiz, width=300, height=300,
bg='#beff8c', cursor='hand2')
self.canvas.bind('<1>',self.desenhar)
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
51
self.canvas.pack()

def desenhar(self,event):
x_origem = self.canvas.winfo_rootx()
y_origem = self.canvas.winfo_rooty()
x_abs = self.canvas.winfo_pointerx()
y_abs = self.canvas.winfo_pointery()
try:
P = (x_abs - x_origem, y_abs - y_origem)
self.canvas.create_line(self.ultimo_P, P)
self.ultimo_P = P
except:
self.ultimo_P=(x_abs - x_origem, y_abs - y_origem)

inst = Tk()
AutoCADE(inst)
inst.mainloop()

Resultado:

I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
52
Em particular, o Canvas possui um mtodo para determinar que objeto est
mais prximo de onde houve um clique. O mtodo o find_closest, cujos argumentos
so as coordenadas (x,y) e o valor retornado o ID do objeto mais prximo de (x,y).
O prximo exemplo uma adaptao da antiga palheta de cores que fizemos.
Desta vez, o usurio deve clicar em um dos trs crculos contendo as cores bsicas. O
mtodo find_closest descobre em qual deles houve o clique. Se houve um clique num
crculo de cor x, ento a intensidade da cor x no crculo maior incrementada em 10.
Quando a janela aberta, o crculo grande preto (intensidade 0,0,0). Digamos que o
usurio d dois cliques no crculo azul e um no vermelho; o crculo maior ter
tonalidade 10, 0, 20 (devidamente convertido para hexadecimais como j
aprendemos).

# -*- coding: cp1252 -*-
from Tkinter import *
class Palheta2:

def __init__(self,raiz):
raiz.title('Palheta Grfica')
self.canvas=Canvas(raiz, width=200, height=200)
self.canvas.bind('<1>', self.misturar)
self.canvas.pack()
bola = self.canvas.create_oval
bola(20,180,70,130, fill='red', outline='')
bola(75,180,125,130, fill='green', outline='')
bola(130,180,180,130, fill='blue', outline='')
bola(45, 120, 155, 10, fill='white',
outline='', tag='bola')
self.tom=[0,0,0]

def misturar(self,event):
xo=self.canvas.winfo_rootx()
yo=self.canvas.winfo_rooty()
xa=self.canvas.winfo_pointerx()
ya=self.canvas.winfo_pointery()
cor=self.canvas.find_closest(xa-xo, ya-yo)[0]
self.tom[cor-1] = self.tom[cor-1]+10
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
53
cor="#%02x%02x%02x" %(self.tom[0],
self.tom[1],
self.tom[2])
self.canvas.delete('bola')
self.canvas.create_oval(45, 120, 155, 10, fill=cor,
outline='', tag='bola')

inst = Tk()
Palheta2(inst)
inst.mainloop()

Resultado:

Novamente, necessrio um tratamento de erros adequado. Veja que mais
de 26 cliques em qualquer dos crculos pequenos resulta um erro, porque exige
intensidades inexistentes da cor em questo, maiores que 255.
Use a tcnica do find_closest sempre que quiser permitir ao usurio mover
um objeto simplesmente clicando nele. Aqui especialmente interessante lembrar que
pressionar o boto do mouse e solt-lo so eventos diferentes. Voc pode usar o
evento "pressionar para descobrir qual objeto o usurio deseja mover e o evento
"soltar para ter as coordenadas da nova posio do objeto. Qualquer aplicativo para
desenho apresenta este procedimento, chamado drag-and-drop (arrastar-e-soltar).

I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
54
4. Gerenciador de geometria Grid

Quando uma GUI contm muitos widgets e eles devem ficar alinhados
verticalmente e/ou horizontalmente, o mtodo pack no d muita conta do recado.
bem mais fcil fazer isso com o mtodo grid, outro gerenciador de geometria oferecido
por Tkinter. O grid tem uma vantagem marcante que com ele podemos combinar
widget empilhados com widgets lado a lado sem para isso criar diversos contineres.
Este gerenciador funciona pela definio de clulas imaginrias no continer.
Pelos argumentos row (linha) e column (coluna), determinamos em qual destas clulas
o widgets estar disposto. Por exemplo, a aplicao de w1.grid(column=1, row=1) e
w2.grid(column=1, row=2) cria imediatamente duas linhas. O widget w1 ficar na
primeira linha e w2 ficar na segunda.

Criemos um terceiro widget que compartilhar a mesma linha de w2. Para
isto, necessria a criao de mais uma coluna: w3.grid(column=2, row=2). O widget
w3 ficar na linha 2, coluna 2.

Aqui ficou feio porque w1 s ocupa a clula onde foi definido. Para fazer com
que ele ocupe tambm a segunda coluna, usamos o argumento columnspan, que
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
55
determina quantas colunas ele deve ocupar. Se usssemos columnspan=2, a
disposio dos widgets seria essa:

Argumento semelhante, rowspan, pode ser usado para dizer que um widget
deve ocupar vrias linhas da sua coluna.
Quando definimos as clulas em que um widget dever se instalar, admite-se
que seu centro esteja no centro deste espao. Com a opo sticky podemos instala-lo
nas diferentes posies mostradas na figura abaixo.

Finalmente, a disposio de vrios widgets na tela no deixa espaos entre
eles. Para dar uma folga horizontal entre um widget e os que estiverem sua
esquerda ou direita, use a opo padx. A opo pady determina a folga vertical.
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
56
Desejando retirar um widget de cena, simplesmente aplique o mtodo
grid_forget() e ele desaparecer. O mtodo pack tambm possui seu oposto:
pack_forget().
Nosso ltimo exemplo ilustra o uso do mtodo grid para dispor widgets na
tela. Repare principalmente que toda a GUI desenvolvida sobre o mesmo continer,
a janela top-level, e que os widgets ficam mais bem comportados do que
conseguiramos com o mtodo pack. Note tambm que a ordem em que o mtodo grid
aplicado sobre a srie de widgets no tem a menor influncia sobre sua disposio
na tela, ao contrrio do que acontece com pack.
Um conceito novo que tambm aparece aqui o mtodo W.destroy(), que
destri o widget W e todos os seus subordinados. Se aplicarmos destroy a um frame,
por exemplo, todos os widget que o tm como mestre tambm desaparecero. A
aplicao do mesmo mtodo sobre a janela top-level, que o item de mxima
hierarquia na GUI, fecha toda a interface.

from Tkinter import *
class Griding:
def __init__(self,raiz):
self.raiz = raiz
self.raiz.title('Tchau!')

Label(self.raiz,text='Nome:').grid(row=1, column=1,
sticky=W, pady=3)
Label(self.raiz,text='Senha:').grid(row=2, column=1,
sticky=W, pady=3)
self.msg=Label(self.raiz,text='Descubra a senha!')
self.msg.grid(row=3, column=1, columnspan=2)

self.nome=Entry(self.raiz, width=10)
self.nome.grid(row=1, column=2, sticky=E+W, pady=3)
self.nome.focus_force()

self.senha=Entry(self.raiz, width=5, fg='darkgray',
show='l',font=('Wingdings','10'))
self.senha.grid(row=2,column=2, sticky=E+W, pady=3)
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
57

self.ok=Button(self.raiz, width=8, command=self.testar,
text='OK')
self.ok.grid(row=4, column=1, padx=2, pady=3)

self.close=Button(self.raiz, width=8, command=self.fechar,
text='Fechar')
self.close.grid(row=4, column=2, padx=2, pady=3)

def testar(self):
if self.nome.get()==self.senha.get()[::-1]:
self.msg['text']='Senha correta!'
else: self.msg['text']='Senha incorreta!'

def fechar(self): self.raiz.destroy()

inst1=Tk()
Griding(inst1)
inst1.mainloop()

Resultado:


E agora? Qual foi a senha que digitei? Voc consegue
descobri-la facilmente olhando o cdigo.

I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
58
Parte VII - Exerccios

As infinitas solues dos exerccios deste Mdulo C a que voc, leitor, poder
chegar, so especialmente interessantes. Por isso, gostaria que voc nos mandasse
sua soluo para que outros leitores possam estudar e comparar com suas prprias. O
e-mail para envio pode ser labakiturbo@gmail.com e as solues sero oferecidas na
pgina http://labaki.tk.

Fceis MdiosDifceis
Refine os exemplos dados neste Mdulo. A maioria precisa de um tratamento
de erros bem feito para evitar que o usurio cause problemas, como atravs
da entrada de dados invlidos.
Crie uma GUI que mostre teclas de um teclado musical e que toque o som da
tecla quando o usurio clicar nela. Veja no Mdulo A como funciona o mdulo
winsound.
Melhore o exemplo Palheta Grfica para que o usurio possa tambm
diminuir a intensidade de alguma cor bsica. Inclua alguns dispositivos que
permitam tornar o crculo grande rapidamente preto ou branco.
Fizemos um exemplo que mostra um relgio digital. Agora escreva uma GUI
que mostre um relgio analgico, com ponteiros, exibio de horas, minutos e
segundos, etc. Faa com que o relgio apresente ao usurio os cumprimentos
de bom dia, boa tarde e boa noite, dependendo do horrio.
Escreva um joguinho como o Pacman. Alguns crculos coloridos devem ser
exibidos em posies aleatrias na tela. Fique atento para que a posio
aleatria do crculo no esteja fora da rea visvel da GUI! O usurio deve ser
capaz de mover uma carinha como a do Pacman, e quando ele estiver sobre
um dos crculos, deve tocar um sonzinho caracterstico de congratulao e o
crculo deve desaparecer.





I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
59
Melhore o programa de ensino de porcentagem atravs de tortas para que o
usurio clique num boto e a fatia desenhada seja "retirada da torta, como na
figura a seguir.

Reescreva tambm os trechos necessrios para que o usurio no tenha que
abrir outra janela sempre que quiser entrar uma porcentagem diferente.
Escreva uma interface grfica na qual o usurio possa informar uma funo
simples e seu grfico seja plotado na tela. Adicione recursos como mais zoom
e menos zoom, possibilidade de escolher o intervalo de valores de x em que a
funo dever ser exibida, e outros que a sua criatividade indicar. Voc
precisar usar a funo eval que aprendemos no Mdulo A.
Crie um programa que permita a criao de desenhos por meio de cliques na
tela. Deve haver uma barra de botes por meio dos quais o usurio escolha
que objeto deseja desenhar: retngulos, crculos ou linhas, e outra barra para
o usurio escolher a cor do prximo objeto a ser desenhado. Para complicar
um pouco, o desenho de crculos deve ser feito assim: no ponto da tela onde
houve o primeiro clique do mouse deve estar o centro do crculo, e o segundo
clique deve determinar por onde a circunferncia passar. No se esquea das
ferramentas para apagar um objeto clicado e outras para limpar toda a tela.
Escreva uma GUI na qual algumas letras estejam espalhadas aleatoriamente
pela tela. A correta organizao destas letras capaz de formar uma palavra,
e quando isto ocorrer, dever tocar uma msica de congratulao. O usurio
selecionar uma letra que deseja mover, e clicar na posio onde deseja que
ela fique. Claro que deve haver um banco de dados grande de diferentes
palavras, seno o jogo no ter a menor graa. Lembre-se de implementar
dispositivos para reiniciar o jogo sem ter que fechar a janela.
A prova de fogo ser o desenho de um tabuleiro de xadrez em que as peas
possam se mover. No necessrio escrever o cdigo do jogo - para que o
usurio jogue contra o computador - simplesmente crie a interface para que





I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
60
duas pessoas possam jogar. Lembre-se que um jogo de xadrez possui
somente seis peas diferentes! No necessrio desenhar uma a uma em
suas posies. Simplesmente crie funes que desenhem as peas e tomem
como argumento a posio em que a pea ficar e sua cor (branca ou preta).
Observe que o programa no deve admitir movimentos consecutivos do
mesmo jogador. No se esquea de implementar o evento da captura de uma
pea: quando o jogador mover uma pea para uma casa onde j h outra, a
que originalmente ocupava o lugar deve sumir do tabuleiro.

ltimas Palavras...


Veja s! Com o que aprendemos neste Mdulo, somos capazes de
desenvolver at mesmo um tabuleiro de xadrez! Mesmo assim, Tkinter oferece
centenas de outros recursos que, com os conceitos aprendidos aqui, voc saber como
usar fcil, fcil. Para conhecer todos eles, recomendamos dois livros que so
excelentes se usados como dicionrios de widgets: "An Introduction to Tkinter de
Fredrik Lundh e "Tkinter Reference: A GUI for Python do New Mxico Tech Computer
Center (opinio pessoal: prefiro este). L est uma relao completa dos setenta e
tantos tipos de cursores e de todos os eventos possveis de teclado e mouse, h
widgets para criar menus, barras de rolagem, escalas, listboxes (que so caixas com
texto rolante como o campo onde voc determina o tamanho da fonte no seu
processador de texto), h a definio de absolutamente todas as opes de
configurao de todos os widgets, h instrues para uso de dezenas de mtodos que
podem ser aplicados a um Canvas, etc. Procure por estes livros no Google e tenha-os
sempre mo para consultar alguma opo de widgets.
Como j dizemos desde o Mdulo A, sua participao muito importante para
a constante melhoria deste material. Para voc ter uma idia, o Mdulo A era um guia
de 89 pginas e continha dois captulos sobre Classes e Tkinter. Os comentrios e
sugestes valiosssimos de muitas pessoas, principalmente do pessoal da lista Python-
Brasil, causaram uma verdadeira revoluo que transformou estes dois captulos em
dois volumes parte - os Mdulos B e este que voc acaba de ler, alm do fato de que
o Mdulo A pulou para 113 pginas. Por toda essa imensa ajuda, muito obrigado!
I N T R O D U O A P Y T H O N - M D U L O C
T K I N T E R

J O S U L A B A K I - G R U P O P Y T H O N - U N E S P - I L H A S O L T E I R A
61
Vocs todos tambm esto contribuindo para xodo do software, do conhecimento e
da documentao proprietrios.
Obrigado tambm aos leitores que tiram dvidas por e-mail, que contribuem
mesmo sem saber para que certos pontos do texto sejam mais bem explicados.
Tambm aprendo muito com vocs!
Um agradecimento especial ao meu orientador, Prof. Dr. Emanuel Rocha
Woiski, pela pacincia, incentivo e pelas oportunidades de aprendizado
multidisciplinares.
E no poderia deixar de agradecer meu novo parceiro na produo de
documentao livre, o Douglas Andrade, que foi o revisor deste Mdulo e estreante da
seo de exerccios resolvidos da minha pgina.
Finalmente, cabe um pequeno comentrio quanto s capas dos Mdulos deste
guia. No primeiro, o Hulk representa a programao procedural como um heri
poderosssimo, mas com desvios de humor e comportamentos s vezes imprevisveis.
O Batman do Mdulo B alude Orientao a Objetos como um poder igual ao do Hulk,
mas desta vez racional, capaz de trabalhar em conjunto e com um cinto de utilidades.
Por fim, a Super-Moa que fecha a srie, representando Tkinter, possui o poder e a
inteligncia dos anteriores, mas muito mais bonita, simptica e charmosa que aquele
morcego feioso e o monstrengo verde.
J. Labaki
labakiturbo@gmail.com
http://labaki.tk

Este documento pode ser distribudo livremente, desde que mantidos os crditos do autor.

Вам также может понравиться