Você está na página 1de 56

Aprenda a programar

por Luciano Ramalho


Porque aprender a programar?
A razo fundamental, que nos motivou a produzir este tutorial, uma s: programar divertido.
claro que nem todo mundo vai concordar com isso, assim como muita gente no acha graa nenhuma
em jogar adrez ou eplorar cavernas. Ao contr!rio do adrez e da espeleologia, a programao
tam"m uma ha"ilidade que tem forte demanda no mercado de tra"alho.
#as a dura realidade que somente com centenas ou milhares de horas de eperi$ncia programando
que voc$ estar! apto a incluir essa disciplina em seu curr%culo e se dar "em em uma entrevista de
emprego. &ortanto nosso o"jetivo aqui "em mais modesto do que transformar voc$ em um
programador profissional. ' que estamos te oferecendo uma introduo suave a esse tpico
fascinante. Ao final, esperamos que voc$ descu"ra se tem a vocao e a motivao necess!rias para
criar soft(ares, como ho"") ou profisso.
Antes de comear, apenas um aviso: o prazer de construir um programa pode causar depend$ncia
psicolgica. *o apenas por dinheiro que programadores do mundo inteiro varam noites escrevendo
cdigo.
Captulo 0
Porque aprender a programar?
#aterial necess!rio
+ap%tulo ,
+ap%tulo -
+ap%tulo .
+ap%tulo /
+ap%tulo 0
+ap%tulo 1
2emplos
3iagrama lunar
Material necessrio
&ara acompanhar esse tutorial voc$ precisar! de um computador qualquer onde tenha instalado um
interpretador da linguagem &)thon. *a p!gina http:44(((.p)thon.org4do(nload4 voc$ encontra lin5s
para "aiar o interpretador adequado para o seu computador. *o caso do 6indo(s, o do(nload da
verso atual tem cerca de 0#7, pois inclui tam"m a linguagem 8cl e o pacote de programao
gr!fica 85. 9e voc$ usa :inu, eiste uma alta pro"a"ilidade de j! ter o interpretador instalado.
2perimente digitar ;p)thon; no seu shell.
Porqu Python
*ossa meta no mostrar como se programa em uma linguagem espec%fica, mas sim como se
programa de uma forma geral. 'u seja, a linguagem para ns ser! um ve%culo, e no o destino.
#esmo assim, pensamos "astante antes de escolher a linguagem &)thon para os eemplos desse
tutorial.
+entenas de linguagens j! foram criadas desde que o computador eletr<nico foi inventado nos anos
/=. Algumas j! so l%nguas mortas. 'utras, como +>> e ?ava, so peas fundamentais no
desenvolvimento da economia digital. *o entanto, a compleidade dessas duas linguagens nos
motivou a descart!@las, e focalizar o universo das chamadas linguagens de ;scripting;, que so mais
simples e se prestam a um estilo de programao informal, mais sintonizado com um tutorial como
esse.
As tr$s linguagens de scripting mais populares atualmente so ?ava9cript, A79cript e &erl. 8odas so
utilizadas na construo de (e"@sites dinBmicos. As duas primeiras praticamente no t$m aplicao
fora desse dom%nio, e por isso foram descartadas. que, em"ora seja nosso o"jetivo a"ordar tam"m
esse tpico, achamos que compleo demais para comear, especialmente devido C dificuldade de se
diagnosticar erros de programao em p!ginas dinBmicas. 2 &erl uma linguagem esquisita demais,
criada para agradar programadores tarim"ados e hac5ers, segundo seu prprio criador.
Delizmente, "em perto de &erl no mapa das linguagens modernas eiste uma outra, no to conhecida,
mas igualmente poderosa. 9eu nome uma homenagem ao grupo humor%stico ingl$s #ont) &)thon,
adorado por gee5s de todo o mundo. Apesar da associao c<mica, &)thon vem sendo usada em
projetos srios por entidades como Eahoo, *A9A, Fnfo9ee5, #+F 6orldcom, F7# e Gi(a), a maior
empresa de hospedagem de (e"@sites do mundo. tam"em a "ase do Hope, a mais sofisticada
plataforma para construo de (e"@applications dispon%vel hoje como open@source.
Apesar de sua sintae simples e clara, &)thon oferece os seguintes recursos dispon%veis tam"m em
linguagens mais complicadas como ?ava e +>>:
programao orientada a o"jetos Iincluindo herana mJltipla, conceito apenas parcialmente
presente em ?avaK
eceLes, um moderno mecanismo para o tratamento de erros
mdulos, uma forma inteligente de acessar e organizar cdigo a ser reutilizado
coleta de lio autom!tica, sistema que elimina os erros causados pelo acJmulo de dados
inJteis na memria do computador Icaracter%stica presente tam"m em ?ava, mas no em +>>K
recursos avanados de manipulao de tetos, listas e outras estruturas de dados
possi"ilidade de eecutar o mesmo programa sem modificaLes em v!rias plataformas de
hard(are e sistemas operacionais Iuma virtude de ?ava, mas dif%cil de se conseguir em +>>K
2m resumo, &)thon nos oferece uma sintae simples mas ao mesmo tempo suporta a maior parte das
caracter%sticas importantes de linguagens modernas e amplamente utilizadas como ?ava, +>>, &erl e
A79cript. &or esse motivos acreditamos que seja a melhor escolha para quem quer comear a
programar hoje.
Abrindo e fechando o interpretador
A melhor forma de aprender e a programar usando um interpretador em modo interativo. 3essa
forma voc$ pode digitar comandos linha por linha, e o"servar a cada passo o como o computador
interpreta e eecuta esses comandos.
&ara fazer isso em &)thon, h! duas maneiras: voc$ pode eecutar o interpretador em modo teto
Ichamado ;&)hton Icommand lineK; no 6indo(sK, ou usar o F3:2, que um interpretador "aseado
em janelas. 9e voc$ usa 6indo(s, escolha o F3:2 para acompanhar esse tutorial.
9eja qual for o interpretador que voc$ escolheu, ao eecut!@lo voc$ ver! uma mensagem com
informaLes de cop)right mais ou menos como essa:
&)thon ,.0.- IM=, Apr ,. ,NNN, ,=:0,:,-K O#9+ .- "it IFntelKP on (in.-
+op)right ,NN,@,NN0 9tichting #athematisch +entrum, Amsterdam
QQQ
' s%m"olo ;QQQ; ei"ido pelo interpretador o que os americanos chamam de ;prompt;, que alguns
traduzem equivocadamente por ;aviso;, mas ns vamos chamar de ;deia; Iem teatro, o termo
;prompt; a deia que indica ao ator a hora de dizer ou fazer algoR em computao, o prompt informa
o usu!rio que o sistema est! pronto para rece"er um novo comandoK.
&ara sair do interpretador voc$ pode fechar a janela do F3:2, ou teclar O+8S:P>O3P Ino F3:2 ou no
interpretador em T*FUK ou O+8S:P>OHP Ino interpretador 3'9K.
Uma calculadora melhor
Aamos ento aproveitar a deia e escrever algo. 2perimente escrever uma epresso aritmtica "em
simples, como ->-:
>>> 2+2
4
>>>
A resposta reconfortante: para &)thon, ->- igual a /. Aoc$ pode eperimentar outras epressLes
mais compleas, mas "om sa"er que os quatro operadores "!sicos em &)thon Ie em quase todas as
linguagens modernasK so esses:
> adio
@ su"trao
V multiplicao
4 diviso
9e voc$ quiser operar com nJmeros decimais, deve usar o ponto e no a v%rgula como separador
decimal:
>>> 1.23 * 0.45
0.5535
>>>
2m muitas linguagens de programao, assim como em &)thon, os nJmeros inteiros t$m um
tratamento especial. Fsso fica evidente quando fazemos uma diviso:
>>> 7/2
3
>>>
2m vez de .,0, o resultado foi .. Fsso acontece sempre que todos os nJmeros de uma epresso so
inteiros. *este caso, &)thon imagina que se deseja um resultado inteiro tam"m Iesse comportamento
estranho na realidade muito conveniente em programaoK. &ara indicar que voc$ deseja resultados
no@inteiros, use um ponto decimal em algum dos operandos:
>>> 7.0/2
3.5
>>> 7/2.0
3.5
>>> 7/2.
3.5
>>>
*ote que "asta digitar um ponto aps o nJmero.
Aoc$ pode digitar espaos entre os nJmeros e operadores para fazer uma epresso longa ficar mais
leg%vel. Aeja esse eemplo:
>>> 1 + 2 * 3
7
>>>
*ote que o interpretador &)thon mais esperto que uma calculadora comum. 2le sa"e que a
multiplicao deve ser efetuada antes da adio. 9e voc$ teclar a mesma epresso em uma
calculadora qualquer o"ter! o resultado N, que incorreto. 2m &)thon, se voc$ realmente deseja
efetuar a soma antes da multiplicao, precisa usar par$nteses:
>>> (1 + 2) * 3
9
>>>
Ao contr!rio do que voc$ aprendeu na escola, aqui os s%m"olos OP e WX no servem para agrupar
epressLes dentro de outras epressLes. Apenas par$nteses so usados:
>>> ( 9 - ( 1 + 2 ) ) / 3.0
2.0
>>> ( 9 - 1 + 2 ) / 3.0
3.33333333333
>>>
3F+A: 9e voc$ escrever algo que o interpretador no reconhece, ver! na tela uma mensagem de erro.
*o crie o mau h!"ito de ignorar essas mensagens, mesmo que elas paream dif%ceis de entender num
primeiro momento. A Jnica vantagem de cometer erros aprender com eles, e se a preguia o impedir
de ler as mensagens, seu aprendizado ser! "em mais lento.
Aeja aqui como decifrar as mensagens de erro do &)thon.
Como ler uma mensagem de erro
A dura realidade que um programador profissional passa "oa parte de sua vida caando erros, e por
isso fundamental sa"er etrair o m!imo de informaLes das mensagens resultantes.
A essa altura voc$ talvez j! tenha provocado um erro para ver o que acontece. Aamos fazer isso
agora, e aprender a ler as mensagens resultantes. &ode parecer perda de tempo, mas
important%ssimo sa"er interpretar as mensagens de erro porque a melhor forma de aprender a
programar eperimentando, e ao eperimentar voc$ certamente vai provocar muitos erros.
+omo eemplo, vamos digitar uma epresso aritmtica sem sentido:
*o interpretador F3:2 voc$ ver! apenas o sinal de diviso assinalado em vermelho e a mensagem
Y9)nta2rror: invalid s)ntaZ, erro de sintae inv!lida.
*o interpretador de linha de comando voc$ ver! uma mensagem mais longa:
>>> 7 + / 2
File "", line 1
7 + / 2
^
SyntaxError: invalid syntax
>>>
A primeira linha da mensagem de erro informa o arquivo onde ocorreu o erro: File
"
Quando voc est usando o interpretador em modo interativo essa informao
intil, mas ao trabalhar com programas extensos ela se torna indispensvel. As
prximas duas linhas indicam onde ocorreu o erro:
7 + / 2
^
Note que o smbolo ^ est apontando exatamente a posio do sinal /. Foi a
partir desse ponto que a expresso deixou de fazer sentido para o interpretador.
Agora vamos provocar um outro tipo de erro:
>>> 7/0
Traceback (innermost last):
File "", line 1, in ?
7/0
ZeroDivisionError: integer division or modulo
>>>
S mais tarde poderemos explicar completamente a primeira linha de uma mensagem
como essa, mas a parte mais importante a ltima linha, que nesse caso bem
fcil de entender: ZeroDivisionError: integer division or modulo
Do lado esquerdo aparece o nome do erro:ZeroDivisionError, ou erro de diviso
por zero. Aps o sinal : vem informaes adicionais sobre o contexto onde
ocorreu o erro: em uma diviso inteira ou modulo (em ingls, modulo o nome do
operador %, que apresentamos acima). O / e o % so os dois operadores que podem
causar um ZeroDivisionError.
Conversor de dlares
3igamos que voc$ tem uma loja de discos importados, e precisa constantemente converter dlares em
reais. ' valor do dlar para venda em -=4=04,NNN de ,.1[1. &ara converter T9\N,N0 e T9\,,,N0 em
reais voc$ pode digitar:
>>> 9.95 * 1.686
16.7757
>>> 11.95 * 1.686
20.1477
>>>
#as h! uma forma melhor: em vez de digitar o valor ,.1[1 o tempo todo, voc$ pode armazenar esse
valor na memria do computador, assim:
>>> d = 1.686
>>>
*ote que o interpretador no respondeu nada Ia menos que voc$ tenha cometido um erroK, mas ele
guardou o nJmero em uma posio de sua memria, e associou o s%m"olo ;d; a essa posio. Agora,
fica mais confort!vel converter dlares em reais:
>>> 9.95 * d
16.7757
>>> 11.95 * d
20.1477
>>> 5 * d, 7 * d, 9 * d
(8.43, 11.802, 15.174)
>>>
*o Jltimo caso, convertemos de uma vez s os valores 0, ] e N em dlares. 2 se a cotao do dlar
mudou para ,.1,^ 7asta armazenar o novo nJmero e refazer os c!lculos:
>>> d = 1.61
>>> 5 * d, 7 * d, 9 * d
(8.05, 11.27, 14.49)
>>>
9e estiver usando o F3:2, voc$ no precisa digitar a segunda linha novamente. +lique so"re a linha
que digitamos no eemplo anterior e tecle O2*82SP. A linha ser! reproduzida na Jltima deia, e
"astar! um novo O2*82SP para process!@la.
abela de pre!os em d"lares e reais
Agora vamos mostrar como o interpretador &)thon muito mais poderoso que uma calculadora.
Fmagine que em sua loja de discos importados voc$ tem um "alco de ofertas com discos de \/ at \N.
9e quisesse fazer uma ta"ela de preos em reais voc$ poderia digitar:
>>> 4*d, 5*d, 6*d, 7*d, 9*d
(6.44, 8.05, 9.66, 11.27, 14.49)
>>>
#as isso um tanto chato e repetitivo, alm do que o resultado no muito apresent!vel. 2m
programao, sempre que voc$ fizer algo repetitivo porque no encontrou ainda a melhor soluo.
:idar com sries de nJmeros uma atividade comum, e &)thon pode ajudar muito nesses casos.
3igite o seguinte:
>>> lista = [5,6,7,8,9]
>>>
Aqui ns criamos uma lista de preos na memria do computador e associamos o nome ;lista; a esses
dados. 2m seguida, digite o seguinte Ivoc$ ter! que teclar O2*82SP duas vezes ao final dessa linhaR
depois sa"er! porqueK.
>>> for p in lista: p * d
8.05
9.66
11.27
12.88
14.49
>>>
Aqui ns instru%mos o interpretador a fazer os seguintes passos: @ para cada item sucessivo da lista: @
associe o nome p ao item em questo @ calcule p V d
Agora digamos que voc$ tem discos com valores de / a ,0 dlares. Aoc$ poderia digitar a lista de
novo, mas a coisa comea a ficar repetitiva novamente. G! uma forma melhor. A linguagem &)thon
possui uma palavra chamada ;range; que serve para gerar faias de nJmeros. Aamos usar essa
palavra. 3igite:
>>> range
<built-in function range>
>>>
_uando voc$ digita o nome de uma funo sem fornecer dados, &)thon limita@se a dizer a que se
refere o nome. *esse caso: ;"uilt@in function range;, ou funo em"utida range. Fsso quer dizer que a
palavra range o nome de uma funo, um tipo de comando que produz resultados a partir de dados
fornecidos. 2 trata@se ainda de uma funo em"utida, ou seja, inclu%da no prprio interpretador Ia
maioria das funLes da linguagem &)thon no so em"utidas, mas fazem parte de mdulos que o
programador precisa chamar eplicitamenteR isso ser! eplicado depois WVS2DXK.
Aca"amos de dizer que uma funo ;produz resultados a partir de dados fornecidos;, ento vamos
fornecer algum dado para ver que resultados a funo range produz. 3igite ;rangeI0K; e veja o que
acontece:
>>> range(5)
[0, 1, 2, 3, 4]
>>>
_uando apenas um dado fornecido, range gera uma lista de nJmeros de zero at o nJmero anterior
ao valor fornecido. um comportamento um pouco estranho, mas Jtil em programao Io primeiro
item de uma srie, na maioria das linguagens, o item nJmero zeroR isso ser! discutido mais
profundamente quando aprendermos mais so"re listas WVS2DXK.
Agora digamos que eu queira uma sequ$ncia a partir de -, e no zero. 3igite:
>>> range(2,5)
[2, 3, 4]
>>>
Agora para o"ter a lista de valores de discos podemos digitar:
>>> range(4,16)
[4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
>>>
2 usando o comando for, calcular de uma s vez todos os valores convertidos:
>>> for p in range(4,16): p * d
6.44
8.05
9.66
11.27
12.88
14.49
16.1
17.71
19.32
20.93
22.54
24.15
>>>
#as o ideal mesmo era ter os valores em dlares e reais lado a lado. Fsso f!cil:
>>> for p in range(4,16): p, p * d
(4, 6.44)
(5, 8.05)
(6, 9.66)
(7, 11.27)
(8, 12.88)
(9, 14.49)
(10, 16.1)
(11, 17.71)
(12, 19.32)
(13, 20.93)
(14, 22.54)
(15, 24.15)
>>>
Sesumindo o que foi feito at aqui, com apenas duas linhas de cdigo em &)thon, voc$ pode gerar
ta"elas de converso de qualquer tamanho. 2perimente:
>>> d = 1.686
>>> for p in range(50,150): p, p * d
&ara"ns, voc$ aca"a de construir seu primeiro programa`
Aprenda a programar
Captulo #
por Luciano Ramalho
*o final do primeiro cap%tulo desse curso digitamos o seguinte programa diretamente no interpretador
&)thon:
>>> d = 1.686
>>> for p in range(50,150): print p, p * d
' resultado desta seqa$ncia de comandos uma longa lista de nJmeros em duas colunas. 9a"emos
que a primeira coluna da esquerda contm preos em dlar e a outra, em reais. #as nada na listagem
indica isto. '"serve esse trecho:
95 160.17
96 161.856
97 163.542
98 165.228
99 166.914
100 168.6
101 170.286
102 171.972
103 173.658
104 175.344
105 177.03
Aqui podemos o"servar outras defici$ncias: as colunas no esto corretamente alinhadas, e os valores
em reais aparecem com uma, duas ou tr$s casas decimais. +omo se trata de uma ta"ela de preos, os
valores em am"as colunas deveriam ter sempre duas casas decimais. Aamos fazer algumas melhorias
em nosso programa gerador de ta"elas de preos.
$uatro tipos de dados
&ara evitar aquele degrau na segunda coluna entre o NN e o ,==, precisamos fazer um pequeno desvio
para comear a aprender a lidar com tetos, alm de nJmeros. 3igite eu b seguido do seu nome entre
aspas:
>>> eu = 'Fulano'
Aoc$ tem que digitar as aspas para evitar um erro. As aspas podem ser csimplesc ou ;duplas;. &)thon
guardar! uma cpia do seu nome na memria do computador, e associar! o identificador eu a esse
dado. Agora "asta digitar eu para ver o seu nome.
>>> eu
'Fulano'
>>>
Antes hav%amos criado a vari!vel d referindo@se C cotao do dlar, e no cap%tulo anterior tam"m
criamos uma vari!vel chamada lista, contendo uma lista de valores. Agora criamos a vari!vel eu para
se referir ao seu nome. 2stes so eemplos de tr$s tipos de dados que &)thon capaz de processar.
Aoc$ pode sa"er o tipo de uma vari!vel ou estrutura de dados usando a funo t)pe. Aeja estes
eemplos:
>>> eu = 'Luciano'
>>> d = 1.902
>>> type(eu)
<type 'string'>
>>> type(d)
<type 'float'>
>>>
&)thon aca"a de nos dizer que a vari!vel eu do tipo cstringc Iuma cadeia de caracteresK e d do tipo
cfloatc, palavra que se pronuncia como ;fl<ut; e que uma a"reviao do termo tcnico ;floating point
num"er; ou nJmero de ponto flutuante. 2ste nome estranho tem origem no fato de que em certas
linguagens, como +o"ol ou +lipper, os nJmeros tem pontos decimais em uma posio fia. *o caso
de &)thon, +>>, ?ava e outras linguagens modernas, o ponto normalmente no fio, mas sim
;flutuante;.
Aejamos mais alguns tipos de dados:
>>> type(1)
<type 'int'>
>>> type(1.)
<type 'float'>
>>> type([1,2,3])
<type 'list'>
>>>
'"serve que o nJmero , no cfloatc, mas cintc. ?! o nJmero ,. seguido de um ponto decimal
considerado um cfloatc. +omo j! dissemos no primeiro cap%tulo, inteiros e floats t$m tratamento
diferente em &)thon e na maioria das linguagens modernas. Tma diviso de inteiros Icomo ]4-K,
sempre fornece um resultado inteiro I., nesse eemploK. ' primo dado testado uma lista, O,,-,.P,
que &)thon chama de clistc.
Agora, eperimente fazer esses dois testes:
>>> type(range)
<type 'builtin_function_or_method'>
>>> type(range(4,7))
<type 'list'>
>>>
Ao perguntarmos qual o tipo associado ao nome range, &)thon responde:
c"uiltindfunctiondordmethodc. 8am"m j! vimos isso no cap%tulo anterior: o nome range refere@se a
uma funo em"utida no prprio interpretador. *o teste seguinte, fornecemos argumentos para a
funo range, e assim produzimos um resultado Ineste caso, a lista O/,0,1P, que foi criada na memria
do seu computador, mas no foi ei"idaK. so"re este resultado que a funo t)pe foi aplicada,
retornando a informao de que se trata de um dado do tipo clistc. 'u seja, range uma epresso do
tipo "uiltindfunctiondordmethod, mas rangeI/,]K uma epresso do tipo clistc. Daz sentido^ 9e no
faz, escreva reclamando`
+ada tipo de dados suporta operaLes diferentes. Daa algumas eperi$ncias e analise os resultados:
>>> n1 = 10
>>> n2 = 20
>>> n1 + n2
30
>>> n1 = 'abacate'
>>> n2 = 'banana'
>>> n1 + n2
'abacatebanana'
>>> n2 + n1
'bananaabacate'
>>>
&or eemplo, o operador > realiza uma soma quando aplicado a dados numricos, mas quando
aplicado a dados do tipo string, o sinal > faz uma operao de concatenao Ijuno de duas
seqa$ncias de caracteresK. Agora eperimente isto:
>>> x = 3.
>>> x * 5
15.0
>>> 'x' * 5
'xxxxx'
>>>
*ote que e cc so coisas totalmente diferentes. o nome de uma vari!vel que neste momento se
refere ao valor .. Ium floatK. ' resultado de V 0 ,0.= Ioutro float, como era de se esperarK. ?! cc
uma string com um caractere. _uando o sinal V aplicado entre uma string e um nJmero inteiro,
&)thon realiza uma operao de repetio. +omo voc$ pode notar, os operadores > e V fazem coisas
diferentes dependendo dos tipos de dados fornecidos na epresso.
um prazer tra"alhar com &)thon porque se trata de uma linguagem muito coerente. '"serve:
>>> [1,2] + [3,4]
[1, 2, 3, 4]
>>> '12' * 3
'121212'
>>> [1,2] * 3
[1, 2, 1, 2, 1, 2]
>>>
*o primeiro eemplo, vemos o operador > concatenando duas listas. 's outros dois eemplos
mostram a operao de repetio. *ote que c,-c no um nJmero, mas uma string composta pelos
caracteres c,c e c-c. &ara &)thon, strings e listas t$m muito em comum: am"as so seqa$ncias de itens.
2nquanto strings so seqa$ncias de caracteres, listas so seqa$ncias de itens quaisquer. *os dois
casos, concatenao e repetio funcionam de forma logicamente id$ntica.
%nfeitando a tabela
Agora que sa"emos so"re alguns tipos de dados, e que os operadores funcionam de forma diferente
conforme os dados da epresso, estamos prontos para aperfeioar nosso gerador de ta"elas usando o
poderoso operador cec, que em &)thon no tem nada a ver com porcentagens. &ara ver como ele
funciona, vamos criar uma string como esta:
>>> msg = 'um dlar vale %f real.'
>>>
Agora vamos ver o que acontece quando chamamos a vari!vel msg:
>>> msg
'um d\363lar vale %f real.'
>>>
&)thon representa var%aveis string dessa forma: entre aspas simples, e trocando os acentos por cdigos
especiais Iestamos falando do cdigo A9+FF em notao octal, algo que eplicaremos depoisK. 9e voc$
quiser ei"ir o conteJdo de msg de forma mais apresent!vel, use o comando print:
>>> print msg
um dlar vale %f real.
>>>
'f, hora de eplicar porque colocamos esse estranho ef dentro da mensagem. 8rata@se de um
marcador de posio para sinalizar onde &)thon dever! inserir um nJmero quando quisermos imprimir
a mensagem com o valor da cotao. 2perimente digitar o seguinte:
>>> d = 1.902
>>> print msg % d
um dlar vale 1.902000 real.
>>>
Aeja o que aconteceu: &)thon su"stituiu a marca ef pelo valor da vari!vel d. assim que funciona: a
partir de uma string com marcas de posio e um ou mais valores, o operador e produz uma nova
string com os valores inseridos nas respectivas posiLes. Aeja agora um eemplo com dois valores:
>>> msg2 = 'Um dlar vale %f real e um real vale %f dlar.'
>>> print msg2 % (d, 1/d)
Um dlar vale 1.902000 real e um real vale 0.525762 dlar.
>>>
*ote que os valores d e ,4d esto entre par$nteses. Fsso o"rigatrio quando queremos passar mais de
um valor para o operador e Iuma sequ$ncia de valores entre par$nteses um ;tuplo;, um tipo
especial de lista que eplicaremos em um outro cap%tuloK.
' s%m"olo ef serve para informar a &)thon que o valor a ser inserido naquela posio um float. 9e
voc$ quiser limitar o nJmero de casas aps o ponto decimal, "asta usar um formato como esse:
>>> d = 1.685
>>> '%.2f' % d
'1.69'
>>>
Aps o marcador e, a indicao .- determina que devem aparecer duas casas decimais aps o ponto.
*ote que o resultado arredondado: ,.1[0 virou ,.1N. Aamos usar esse recurso na nossa ta"ela:
>>> for p in range(4,16): print 'US$ %.2f = R$ %.2f' % (p,p*d)


US$ 4.00 = R$ 6.74
US$ 5.00 = R$ 8.43
US$ 6.00 = R$ 10.12
US$ 7.00 = R$ 11.80
US$ 8.00 = R$ 13.49
US$ 9.00 = R$ 15.17
US$ 10.00 = R$ 16.86
US$ 11.00 = R$ 18.55
US$ 12.00 = R$ 20.23
US$ 13.00 = R$ 21.92
US$ 14.00 = R$ 23.60
US$ 15.00 = R$ 25.29
>>>
2st! quase linda. Dalta s consertar o degrau que acontece entre a linha do N e do ,=. *o marcador de
posio voc$ tam"m pode colocar um nJmero C esquerda do ponto para definir a largura total do
espao que ser! reservado. *a faia de preos de / a ,0, os maiores valores tem cinco caracteres de
comprimento Iincluindo o ponto decimalK, por isso vamos usar ce1.-fc. Agora podemos fazer uma
verso "em melhor da ta"ela:
>>> for p in range(4,16): print 'US$ %5.2f = R$ %5.2f' % (p,p*d)


US$ 4.00 = R$ 6.74
US$ 5.00 = R$ 8.43
US$ 6.00 = R$ 10.12
US$ 7.00 = R$ 11.80
US$ 8.00 = R$ 13.49
US$ 9.00 = R$ 15.17
US$ 10.00 = R$ 16.86
US$ 11.00 = R$ 18.55
US$ 12.00 = R$ 20.23
US$ 13.00 = R$ 21.92
US$ 14.00 = R$ 23.60
US$ 15.00 = R$ 25.29
>>>
%ntendendo melhor o for
+omo voc$ perce"eu, no comando for tudo aquilo que aparece aps os sinal ;:; repetido v!rias
vezes, uma vez para cada item da lista de valores indicada aps a palavra in. #as os comandos a
serem repetidos podem ser v!rios, e na maioria das vezes no so escritos na mesma linha que o for,
como temos feito, mas sim em linhas su"seqaentes.
' comando for algo que chamamos de ;estrutura de controle;, que serve para determinar a forma de
eecuo de um comando ou de uma seqa$ncia de comandos, Cs vezes chamada de um ;"loco;. 2m
outras linguagens, os "locos so delimitados por marcadores especiais. ?ava, &erl e +>> usam os
sinais W e X para este fim. &ascal e 3elphi usam as palavras 72gF* e 2*3. Alm desses marcadores
eigidos pelas linguagens, os programadores usam tam"m o recurso da recurso da endentao, ou
seja, o recuo em relao C margem esquerda, para tornar mais f!cil a visualizao da estrutura do
programa. Aeja este eemplo em &erl:
for ($i = 0; $i < 5; $i++) {
$v = $i * 3;
print "$v\n";
}
Aten!&o' isto ( Perl) e n&o Python*
Aqui, os comandos \v b \i V .R e print ;\vhn;R formam o "loco que est! so"re o controle do comando
for, ou seja, os dois comandos sero eecutados repetidamente. ' programa equivalente em &)thon
escrito assim:
>>> for i in range(5):
v = i * 3
print v
2m nossa opinio, o cdigo em &)thon "em mais leg%vel. &ara sinalizar quais comandos fazem parte
do "loco que est! so" o controle do for, apenas a endentao utilizada. 9e voc$ est! usando o F3:2,
esse recuo acontece automaticamente quando uma linha de comando termina com o sinal c:c, que em
&)thon sempre indica o in%cio de um "loco. *o interpretador &)thon invocado a partir da linha de
comando no 3'9 ou em T*FU, a indentao no autom!tica. Aoc$ precisa digitar ao menos um
espao em "ranco ou, melhor ainda, um O8A7P, para evitar uma mensagem de erro como essa:
>>> for i in range(5):
... print i
File "", line 2
print i
^
SyntaxError: invalid syntax
*ote que o interpretador est! reclamando de sintae inv!lida, e apontando IiK para a primeira palavra
do "loco que deveria estar recuado. Aeja a mesma coisa, com a segunda linha recuada com a tecla
O8A7P:
>>> for i in range(5):
... print i
...
0
1
2
3
4
>>>
?! deve ter ficado claro porque era preciso digitar dois O2*82SP depois do for nos eemplos
anteriores: que, no modo interativo, o interpretador &)thon espera uma linha em "ranco para
sinalizar o final de uma srie de comandos que formam um "loco dentro de uma estrutura de controle.
Agora que entendemos o conceito de "loco, podemos enfeitar ainda mais a nossa ta"ela colocando um
segundo comando print dentro do nosso for:
Aeja este eemplo:
>>> for p in range(9,13):
print 'US$ %5.2f = R$ %5.2f' % (p, p * d)
print '-' * 20


US$ 9.00 = R$ 15.17
--------------------
US$ 10.00 = R$ 16.85
--------------------
US$ 11.00 = R$ 18.54
--------------------
US$ 12.00 = R$ 20.22
--------------------
>>>
A outra face do +
Antes de encerrar este cap%tulo, vale a pena contar que, assim como o > e o V, o operador cec tam"m
tem dupla personalidade. _uando aplicado so"re dois nJmeros, que podem ser inteiros ou floats, o cec
retorna o resto da diviso inteira do primeiro pelo segundo. Aeja s:
>>> 6 % 3
0
>>> 7 % 3
1
>>> 8 % 3
2
>>> 9 % 3
0
>>>
2plicando: 1 4 . d! -, e o resto =R a diviso inteira de ] 4 . tam"m d! -, mas o resto ,. 2sta
operao chamada de ;modulo; em ingl$s. 9ua principal utilidade determinar se um nJmero
mJltiplo de outro. *os eemplos acima, o resultado de 1 e . e N e . zero, porque 1 e N so
mJltiplos de ..
*o primo cap%tulo vamos comear a ela"orar programas mais etensos. ' modo interativo, que
temos usado at agora, vai continuar sendo Jtil para testarmos novas idias e o"servar o
comportamento de funLes e mdulos do &)thon rapidamente. #as, a partir da prima sesso, vamos
comear a gravar nossos programas para uso posterior, em vez de digit!@los diretamente no
interpretador. 2 vamos tam"m desco"rir como solicitar informaLes do usu!rio, de forma que os
programas possam ser utilizados por pessoas que no sa"em programar e preferem ficar longe de um
interpretador interativo.
Aprenda a programar
Captulo ,
por Luciano Ramalho
3epois de dois cap%tulos "em "!sicos, hora de engatar uma segunda e comear a criar programas
mais dignos desse nome. *o vamos desprezar o que fizemos at aqui, digitando diretamente na deia
do interpretador &)thon. Ao contr!rio: tenha sempre em mente que voc$ pode us!@lo para esclarecer
aquela dJvida r!pida ou mesmo localizar um "ug escondido em um sistema compleo. A maioria das
outras linguagens no oferece um am"iente para eecuo imediata de comandos como o &)thon.
Tma eceo famosa a linguagem :ogo, onde o interpretador interativo serve justamente para
facilitar a aprendizagem da programao por tentativa e erro.
#as a partir de agora vamos atacar programas mais etensos, e no vamos querer digit!@los linha por
linha no modo interativo. 2m vez disso, vamos escrever os comandos em um editor de tetos, salvar o
arquivo, e mandar o interpretador &)thon ler o programa salvo.
-odando programas no ./0%
A verso 6indo(s do &)thon ,.0.- traz o F3:2, um interpretador interativo em modo gr!fico que j!
apresentamos no primeiro cap%tulo. 9e voc$ no usa essa verso do &)thon, v! direto para a prima
seo: 8estando no sistema. ' F3:2 inclui um editor de programas simplrio, mas Jtil para quem est!
aprendendo a linguagem. ' editor do F3:2 ei"e com cores diferentes as palavras da linguagem, de
acordo com sua funo sint!tica Ilem"ra da aula de portugu$s onde o ver"o era verde, o sujeito
vermelho etc^K. &ara a"rir o editor, rode o F3:2 e acione o comando Dile Q *e( (indo(. A janela
que se a"rir!, com o t%tulo ;untitled;, um editor. 2perimente digitar um programinha como esse:
for i in range(100):
print 'Luciano '
print 'e seus Camargos'
*ote que o editor pinta algumas palavras de laranja. 9o as chamadas palavras@chave, peas to
importantes em &)thon como os ver"os em portugu$s. A funo range e a vari!vel i, aparecem em
preto. Assim so ei"idos os identificadores que o prprio programador pode definir ou redefinir. 2 os
tetos entre aspas aparecem em verde: dessa forma, fica dif%cil esquecer de fechar aspas. 'utra coisa
que acontece magicamente a endentao. ' editor ;sa"e; que aps os ;:; do comando for, deve vir
um "loco endentado. &ara encerrar o "loco endentado, voc$ pode teclar O2*82SP duas vezes para
pular uma linha, como ocorre tam"m na deia do interpretador, ou ento teclar O7ac59paceP para
apagar de uma vez s os quatro espaos C esquerda da linha.
Tma vez digitado esse programinha voc$ pode eecut!@lo de duas maneiras: diretamente de dentro do
F3:2 ou na deia do sistema operacional. ' primeiro mtodo o mais f!cil, mas o segundo o
melhor por v!rios motivos. &ara usar o modo f!cil, s teclar OD0P. 9e voc$ ainda no salvou o teto
do seu programa, o F3:2 vai ei"ir uma mensagem pedindo para que voc$ o faa. 7asta usar o
comando Dile Q 9ave, ou melhor ainda, O+8S:P>O9P. 9e voc$ no sa"e onde salvar, sugiro que crie
uma pasta chamada +urso dentro da pasta onde est! o seu interpretador &)thon e salve ali
Iprovavelmente a pasta ficar! sendo +:hArquivos de &rogramash&)thonh+ursoK. Assim fica f!cil
encontr!@lo depois. Tse o nome egotrip.p).
A eecuo do programinha egotrip causa a ei"io repetida do nome do autor, seguinda do nome de
sua "anda. *o tempo do Apple FF e do 8f@[0, programinhas como esse eram invariavelmente os
primeiros eerc%cios de qualquer estudante de programao. *o F3:2, a ;sa%da; ou ;output; do
programa Iaquilo que ele produzK, ei"ida dentro de uma janela intitulada ;V'utputV;. Aoc$ pode
fechar essa janela quando o programa parar. "om mesmo que voc$ feche, porque ao rodar o
programa de novo, outra janela de output ser! criada, e elas se multiplicam rapidamente quando a
gente est! concentrado programando...
Aoc$ talvez tenha notado que o &)thon "astante lento. 2m meu note"oo5 &entium ,.. o programa
leva ,= segundos para escrever as ,=, linhas. muito. #as a culpa no do &)thon, e sim do F3:2,
como veremos a seguir.
1a2egando pela linha de comando
*o :inu a linha de comando est! em toda parte, mas no 6indo(s fica um pouco escondida. &ara
encontr!@la, clique na "arra de tarefas do 6indo(s em Fniciar Q &rogramas Q &rompt do #9@3'9.
&ara quem nunca navegou pelo sistema via prompt, eis aqui o m%nimo que voc$ precisa sa"er. Aeja o
que aparece na janela do &rompt:
j esquerda do cursor, voc$ tem a informao mais importante para se orientar: a letra do drive e o
nome da pasta onde voc$ se encontra. 9e o seu 6indo(s est! com a configurao de f!"rica, voc$
estar! em +:h6indo(s. ' sinal kQl apenas a deia do sistema, equivalente ao kQQQl usado pelo
&)thon para indicar que est! pronto para rece"er um comando. Antes de mais nada, vamos acionar um
programinha muito que nos poupar! muita digitao posteriormente. 3igite ;dos5e); ao lado do
prompt e tecle O2*82SP.
C:\Windows>doskey [ENTER]
Aoc$ ver! a mensagem k3'9fe) instaladol. A partir de agora, tudo o que voc$ digitar na linha de
comando ser! salvo pelo 3'9fe), e poder! ser recuperado para repetio posterior. :ogo veremos
como.
Agora, vamos ver o que eiste na pasta onde estamos Ia pasta 6indo(sK. 3igite:
C:\Windows>dir [ENTER]
Aoc$ ver! uma longa listagem de arquivos, com seus nomes a"reviados, etensLes, tamanhos, datas e
nomes longos. 2m meu note"oo5 aparecem -.1 arquivos na pasta 6indo(s. *o estamos
interessados neles agora, o o"jetivo era apenas mostrar que o comando dir produz uma listagem dos
arquivos da pasta, ou diretrio, atual. &ara ver o dos5e) em ao, tecle a OiP Iseta para cimaK. ' Jltimo
comando digitado aparece de novo, pronto para ser eecutado ao toque de um O2*82SP.
Agora vamos navegar at o diretrio onde foi gravado o programa egotrip.p). 3igite:
C:\Windows>cd \ [ENTER]
Agora voc$ est! no chamado diretrio raiz do seu disco. 3igite dir e veja como a maioria dos itens
dentro dessa pasta so outras pastas, como a prpria pasta 6indo(s e a pasta Arquivos de &rogramas.
Aamos ;entrar; nessa Jltima pasta. &ara isso, vamos usar seu nome a"reviado pelo 3'9, arquivm,:
C:\>cd arquiv~1 [ENTER]
Agora vamos entrar na pasta do &)thon:
C:\Arquivos de programas>cd python [ENTER]
2, em seguida, na pasta +urso, que voc$ deve ter criado quando salvou o arquivo egotrip.p).
C:\Arquivos de programas\Python>cd curso
C:\Arquivos de programas\Python\Curso>dir
Aoc$ dever! ver uma listagem como essa:
O volume da unidade C KAYAK_DOS
O nmero de srie do volume 3A64-0AE9
Pasta de C:\Arquivos de programas\Python\Curso
. <DIR> 25/10/99 20:57 .
.. <DIR> 25/10/99 20:57 ..
EGOTRIP PY 89 25/10/99 20:32 egotrip.py
1 arquivo(s) 89 bytes
2 pasta(s) 21.331.968 bytes disponveis
C:\Arquivos de programas\Python\Curso>
Agora voc$ est! no ponto certo para digitar o comando que causar! a eecuo do seu programa
egotrip.p).
estando no sistema
#eu am"iente favorito para rodar programas em &)thon a prpria linha de comando do sistema
operacional. *o costumo usar o editor do F3:2, mas sim o 8et&ad, um ecelente editor de tetos
so"re o qual voc$ pode ler mais no site da #Ag*28. 9eja qual for o editor que voc$ usa, o
importante salvar o arquivo como teto A9+FF puro. ' *otepad do 6indo(s pode melhor que
6ord para esse fim. *o :inu, vi, joe, pico e emacs so alguns editores A9+FF "astante comuns.
2ntre esses, prefiro o emacs. Tma vez digitado e salvo o arquivo, voc$ precisa eecut!@lo a partir da
linha de comando do seu sistema.
_uem usa :inu ou j! est! ha"ituado ao 3'9, pode seguir at a prima seo, A9+FF art.
A3C.. art
*o 6indo(s, para eecutar o programa, digite esse encantamento Isupondo que voc$ fez tudo
conforme descrito na seo acima, ou fez tudo diferente mas sa"ia o que estava fazendoK:
C:\Arquivos de programas\Python\Curso>..\python egotrip.py
's sinais ..h na frente do comando p)thon servem para dizer ao 3'9 para eecutar um programa que
est! no diretrio anterior no caminho atual. Assim, acionamos o programa p)thon.ee que est! na
pasta +:hArquivos de programash&)thon.
*o :inu, voc$ precisar! chegar at o diretrio que contm o eemplo, e digitar:
>python egotrip.py
'u, se isso no funcionar, tente algo como segue Io comando eato vai depender da sua instalaoK:
>/usr/local/bin/python egotrip.py
7om, deu tra"alho mas chegamos. 2 como voc$ deve ter notado, a eecuo do programinha foi "em
mais veloz que no F3:2 Iem meu computador, menos de , segundo, em vez de ,=K.
Agora vamos fazer uma pequena mudana no programa egotrip que ter! um grande efeito. &ara fazer
essa alterao, no 6indo(s o modo mais r!pido segurar a tecla OA:8P e pressionar O8A7P at que o
%cone do editor do F3:2 identificado pelo nome do arquivo egotrip.p) esteja selecionado. 2nto solte
a tecla OA:8P, que o editor aparecer! so"repondo@se Cs demais janelas. Agora vamos modificar o
programa egotrip. Ao final da segunda linha, digite uma v%rgula. ' seu programa dever! ficar assim:
--
for i in range(100):
print 'Luciano ',
print 'e seus Camargos'
--
9alve com O+8S:P>O9P e rode o programa novamente. 8ecle OD0P para rodar no F3:2, ou siga esses
passos para testar no 3'9:
OA:8PO8A7P at voltar ao prompt do 3'9
OiP Iseta para cimaK para fazer o dos5e) repetir o comando ..hp)thon egotrip.p)
O2*82SP para eecutar o comando acima.
,= entre ,= programadores que usam a plataforma 6indo(s t$m muita pr!tica com a sequ$ncia
OA:8P>O8A7P, OiP, O2*82SP. :ogo, logo, em sua primeira sesso de caa a um "ug, voc$ ter!
oportunidade de praticar "astante.
*esse caso, interessante testar o programa tanto no F3:2 quanto na linha de comando. Aoc$ ver!
que os resultados so "em diferentes. 2perimente e tente eplicar porqu$.
+omo eerc%cio final, su"situa o argumento ,== da funo range pelo nJmero ,===, e rode o
programa novamente Ino recomendo usar o OD0P do F3:2 dessa vezR ser! "em demoradoK. 8ente
acrescentar ou retirar letras do seu nome. ' efeito ser! diferente. 7em vindo ao mundo da epresso
art%stica com caracteres de computador.
3eu primeiro programa interati2o
At agora, todos os programas que mostramos no so interativos, ou seja, uma vez rodando eles no
aceitam a entrada de dados de um usu!rio ou do sistema. &rogramas no interativos so usados em
muitas situaLes comuns. ' programa que emite os cheques da folha de pagamentos de uma grande
empresa provavelmente no interativo, mas rece"e todos os dados necess!rios em um Jnico lote,
antes de sua eecuo. #as os programas mais interessantes, como um processador de tetos, um
game ou o piloto autom!tico de um avio so todos interativos. 2sse o tipo de programa que
passaremos a desenvolver agora.
*osso passeio pela A9+FF art no teve apenas o"jetivos estticos. _uizemos mostrar como rodar um
programa em &)thon a partir da linha de comando porque, a partir de agora, vamos usar um comando
da linguagem &)thon que no funciona na atual verso do F3:2. ' comando chama@se ;ra(dinput;, e
sua funo rece"er uma entrada de dados do usu!rio Iinput quer dizer entrada de dadosR cuidado
porque voc$ deve ter sido condicionado a acreditar que ;antes de & e 7 sempre vem a letra #;, mas
input ingl$s, e se escreve com * mesmoR eu perdi uma hora com isso quando aprendia 7A9F+K.
Aejamos um primeiro eemplo. '"serve que no estamos acentuando o teto no programa porque o
3'9 no reproduz corretamente os acentos do 6indo(s, e precisamos do 3'9 para testar esse
programa. 3eve haver uma forma de convencer o 3'9 a ei"ir os acentos corretos do 6indo(s, mas
ainda no desco"rimos como.
3e qualquer forma, isso no quer dizer que no d! para fazer programas com acentuao correta em
&)thonR quando aprendermos a criar soft(ares gr!ficos esse pro"lema desaparecer!.
3igite o programinha a"aio, salve como despdom,.p) e eecute na linha de comando.
# despdom1.py - Calculadora de despesas domesticas
print 'Balanco de despesas domesticas'
ana = raw_input('Quanto gastou Ana? ')
bia = raw_input('Quanto gastou Bia? ')
total = float(ana) + float(bia)
print 'Total de gastos = R$ %s.' % total
media = total/2
print 'Gastos por pessoa = R$ %s.' % media
's nJmeros que aparecem C esquerda na listagem acima no fazem parte do programa e no devem
ser digitados. 2les esto a% para facilitar a eplicao que vem logo a seguir.
Antes de esmiuar o programa, vale a pena eecut!@lo para ver o que acontece. Aoc$ ser! solicitado a
digitar um valor para Ana e outro para 7ia. *ote que os valores devero ser apenas nJmeros. 9e
quiser usar centavos, use o ponto decimal em vez de v%rgula, como j! v%nhamos fazendo antes. 2 nada
de \ ou S\. Aejamos um eemplo de eecuo:
C:\Arquivos de programas\Python\Curso>..\python despdom1.py
Balanco de despesas domesticas
Quanto gastou Ana? 10
Quanto gastou Bia? 20
Total de gastos = 30.0
Gastos por pessoa = 15.0
C:\Arquivos de programas\Python\Curso>
/issecando o c"digo
Agora vamos acompanhar, linha por linha, como o interpretador eecutou o programa. 2ssa a
atividade mais importante para desenvolver voc$ como programador ou programadora. Aoc$ precisa
aprender a ler um programa e simular mentalmente que acontece dentro do computador. ;_uando
voc$ aprender a se colocar no lugar do computador ao ler um programa, estar! pronto, gafanhoto;.
:inha ,: ' sinal M indica coment!rio. 8udo o que aparece em uma linha a partir desse sinal ignorado
pelo interpretador &)thon. *este caso, o coment!rio eplica para ns, humanos, o propsito do
programa. *ote que o coment!rio no aparece para o usu!rio final quando o programa eecutado.
+oment!rios servem apenas para ser lidos por outros programadores.
:inha .: ' velho comando print usado para escrever o t%tulo ;7alanco de despesas domesticas; na
tela do usu!rio.
:inha /: ' comando ra(dinput ei"e a pergunta ;_uanto gastou Ana^;, aguarda uma resposta e
armazena na var%avel ana.
:inha 0: ' mesmo comando usado para guardar os gastos de 7ia na vari!vel "ia.
:inha 1: Aqui calculado o total. *ote o uso da funo float. Acontece que a funo ra(dinput no
retorna nJmeros, e sim strings. +omo vimos no cap%tulo anterior, o operador ;>; tem efeitos diferentes
quando aplicado a stringsR em vez de somar, ele concatena ou junta os tetos. *esse caso, se ana
k,=l e "ia k-=l, ana > "ia seria k,=-=l. &ara realizar a soma, precisamos antes transformar as strings
em nJmeros, o que feito pela funLes float ou int. *esse caso, usamos float porque no vamos nos
limitar a aceitar nJmeros inteiros.
:inha ]: ' total ei"ido, com o au%lio do operador e que insere o valor na posio assinalada pelos
caracteres es dentro da mensagem. ' cdigo es faz com que &)thon transforme o nJmero em string.
:inha [: +!lculo da mdia. +omo am"os os valores so float, o resultado ser! preciso Ise fossem
inteiros, o resultado tam"m seria forado a ser inteiro, o que nesse caso levaria a erros do tipoK.
:inha N: #ostramos a mdia, usando a mesma tcnica da linha ].
2perimente rodar o programa algumas vezes. *ote que no um programa muito ro"usto: se voc$
no digitar coisa alguma e teclar O2*82SP aps uma das perguntas, ou responder com letras em vez
de nJmeros, o programa ;que"ra;. *o primo cap%tulo aprenderemos a lidar entradas inesperadas.
Um programa mais esperto
' programa acima quase Jtil. 2le calcula a despesa total e a mdia, mas no responde C pergunta
fundamental: quanto Ana tem que pagar a 7ia, ou vice@versa^ A aritmtica envolvida simples: se
Ana gastou menos, ela precisa pagar a 7ia um valor igual C diferena entre o que gastou e a mdia.
gostar%amos que nosso programa funcionasse assim:
Balanco de despesas domesticas
Quanto gastou Ana? 10
Quanto gastou Bia? 20
Total de gastos: R$ 30.0
Gastos por pessoa: R$ 15.0
Ana deve pagar: R$ 5.0
Ttilize o comando Dile Q 9ave As... para salvar o programa despdom,.p) como despdom-.p). Agora
vamos modific!@lo para fazer o que queremos. A"aio, o programa final, e a seguir, a eplicao de
cada mudana que foi feita.
# despdom2.py - Calculadora de despesas domesticas - versao 2
print 'Balanco de despesas domesticas'
ana = float(raw_input('Quanto gastou Ana? '))
bia = float(raw_input('Quanto gastou Bia? '))
print
total = ana + bia
print 'Total de gastos: R$ %s' % total
media = total/2
print 'Gastos por pessoa: R$ %s' % media
if ana < media:
diferenca = media - ana
print 'Ana deve pagar: R$ %s' % diferenca
else:
diferenca = media - bia
print 'Bia deve pagar: R$ %s' % diferenca
:inha ,: Acrescentamos ;versao -; ao coment!rio
:inhas / e 0: Aqui fazemos a converso dos resultados de ra(dinput para float imediatamente, de
modo que os valores armazenados na vari!veis ana e "ia so nJmeros, e no strings como antes.
:inha 1: Tma mudana cosmtica apenas: acrescentamos uma linha com apenas um print, para deiar
na tela uma linha em "ranco entre as perguntas e os resultados.
:inhas ]: Agora podemos simplesmente somar os valores de ana e "ia, que j! foram convertidos para
float nas linhas / e 0.
:inhas [ a ,=: 2i"imos o total e processamos a mdia, como antes.
:inha ,,: Apresentamos um novo comando de "loco, o comando if, que pode ser traduzido
eatamente como ;se;. 2ssa linha diz, literalmente: ;se ana n media:;. 'u seja, se o valor de Ana for
menor que o valor da mdia, eecute o "loco endentado a seguir Ilinhas ,- e ,.K. +aso contr!rio, no
eecute essas linhas, e passe direto para a linha ,/.
:inhas ,- e ,.: +alculamos e ei"imos quanto Ana deve pagar.
:inha ,/: Aqui vemos outro comando de "loco, o else, que pode ser traduzido como ;seno;. ' else
s pode eistir aps um "loco iniciado por if. ' "loco que segue o else s eecutado quando a
condio prevista no if no ocorre. Fsso significa que, quando temos um "loco if e um "loco else,
garantido que apenas um dos dois ser! eecutado. *esse caso, as linhas ,0 e ,1 s sero eecutadas
se o valor de Ana no for menor que a mdia.
:inhas ,0 e ,1: +alculamos e ei"imos quanto 7ia deve pagar.
2perimente um pouco com o programa despdom-.p). ' que acontece quando os gastos de Ana e 7ia
so iguais^ 8ente responder essa pergunta sem rodar o programa. A chave est! na linha ,,. _ual a
mdia quando os gastos so iguais^ 8ente simular mentalmente o comportamento do computador na
eecuo passo a passo do programa. 3edique alguns minutos a esse desafio, e s ento rode o
programa com valores iguais para ver se acontece o que voc$ imaginou.
udo sobre o if
' comando if, que aca"amos de conhecer atravs de um eemplo, uma pea fundamental da
linguagem &)thon, e de quase todas as linguagens de programao eistente. 9ua funo descrita
como ;comando de eecuo condicional de "loco;, ou seja, um comando que determina a eecuo
ou no de um "loco de comandos, de acordo com uma condio lgica. *o eemplo, a condio
lgica ;ana n media;. ' operador n serve para comparar dois nJmeros e determinar se o primeiro
menor que o segundo Iele tam"m funciona com strings, mas a% a comparao segue uma regra
parecida com a ordem usada dos dicion!riosK. 's operadores de comparao de &)thon so os mesmos
usados em ?ava e +>>:
'perador descrio eemplo
bb igual a bb "
`b diferente a `b "
n menor que a n "
Q maior que a Q "
Qb maior ou igual a a Qb "
nb menor ou igual a a nb "
&ara sentir o funcionamento desses operadores, a"ra o interpretador interativo do &)thon e digite esses
testes Ino vamos mostrar os resultados aquiR faa voc$ mesmoK.
>>> a = 1
>>> b = 2
>>> a == 1
>>> a == 2
>>> a == b
>>> 2 == b
>>> a != b
>>> a != 1
>>> a < b
>>> a >= b
As linhas , e - no produzem nenhum resultado, como j! vimos antes. 2las apenas atri"uem valor Cs
vari!veis a e ". A linha . parece um pouco com a linha ,, mas significa algo completamente diferente.
Aqui no acontece nenhuma atri"uio, apenas uma comparao, que vai gerar um resultado. Tm erro
"astante comum cometido por quem est! aprendendo &)thon, + ou ?ava usar b no lugar de bb ao
fazer uma comparao Iem 7asic, por eemplo, o b usado nos dois casosK. Aps cada as linhas a
partir da linha ., o interpretador mostrar! um nJmero , ou =, para indicar que a comparao
verdadeira I,K ou falsa I=K.
Aoltando ao comando if, no eiste nenhuma lei que force a presena de um operador de comparao
na condio do if. A Jnica coisa que interessa que a epresso que estiver no lugar da condio ser!
considerada falsa se for igual a = IzeroK, uma string vazia, uma lista vazia ou o valor especial *one,
so"re o qual voltaremos a falar depois. _ualquer valor que no seja um desses ser! considerado
;verdadeiro;, e provocar! a eecuo do "loco su"ordinado ao if. por isso que os operadores de
comparao retornam = ou , para representar falso ou verdadeiro.
*o o"rigatria a presena de um "loco else aps um if. #as um else s pode eistir aps um if. 2
um if pode conter, no m!imo, um else. 2iste um terceiro comando de "loco relacionado a esses,
chamado elif. 2le corresponde C com"inao else@if eistente em outras linguagens. Assim como o if,
cada elif deve ser acompanhado de uma condio que determinar! a eecuo do "loco su"ordinado.
+omo todo comando de "loco, a primeira linha do elif deve ser terminada por um sinal de :.
Tm if pode ser seguido de qualquer quantidade de "locos elif, e se houver um "loco else ele dever!
vir depois de todos os elif. Aeja esse fragmento de cdigo, parte de um jogo simples que criaremos no
primo cap%tulo:
if vf == 0:
print 'Alunissagem perfeita!'
elif vf <= 2:
print 'Alunissagem dentro do padrao.'
elif vf <= 10:
print 'Alunissagem com avarias leves.'
elif vf <= 20:
print 'Alunissagem com avarias severas.'
else:
print 'Modulo lunar destruido no impacto.'
*uma sequencia de if4elif4elif4...4else garantido que um, e apenas um dos "locos ser! eecutado.
Dica como desafio para o leitor desco"rir como usar o comando elif para corrigir o "ug dos gastos
iguais, que aparece no programa despdom-.p). A resposta voc$ encontrar! no site da #agnet.
Aprenda a programar
Captulo 4
or!amentos) pousos lunares e tratamento de erros
por Luciano Ramalho
' cap%tulo anterior terminou com uma questo no ar. Aps estudarmos todas as formas de se usar o
comando if, restou o desafio de usar um "loco elif para consertar um pequeno defeito no programa
despdom-.p). ' "ug se manifesta quando os gastos de Ana e 7ia so iguais. *esse caso, o programa
escreve na tela:
Bia deve pagar: R$ 0.0
2m vez de fazer a 7ia escrever um cheque de zero reais, o melhor seria tratar esse caso especial. Aeja
como faz$@lo, usando uma construo if4elif4else Ilistagem ,K. 9e voc$ guardou o arquivo
despdom-.p) da lio anterior, ter! muito pouco o que digitar. A"ra@o e salve com o nome de
despdom..p). ' cdigo id$ntico C verso anterior at a linha ,/. Ali, voc$ faz a primeira alterao:
o else su"stitu%do por um elif que verifica se 7ia gastou menos que a mdia. As linhas ,0 e ,1
continuam como antes, mas agora elas s sero eecutadas se "ia n media for verdadeiro. As linhas ,]
e ,[ so novas, e servem para tratar o caso em que nem ana n media nem "ia n media, ou seja,
quando no h! diferena a ser paga. Agora voc$ pode testar o programa digitando valores diferentes e
depois valores iguais para as despesas de Ana e 7ia.
0istagem 5
1 # despdom3.py - Calculadora de despesas domesticas - versao 3
2
3 print 'Balanco de despesas domesticas'
4 ana = float(raw_input('Quanto gastou Ana? '))
5 bia = float(raw_input('Quanto gastou Bia? '))
6 print
7 total = ana + bia
8 print 'Total de gastos: R$ %s' % total
9 media = total/2
10 print 'Gastos por pessoa: R$ %s' % media
11 if ana < media:
12 diferenca = media ana
13 print 'Ana deve pagar: R$ %s' % diferenca
14 elif bia < media:
15 diferenca = media bia
16 print 'Bia deve pagar: R$ %s' % diferenca
17 else:
18 print 'Ana e Bia gastaram a mesma Quantia.'
3omadora infinita
:ogo adiante iremos reescrever o programinha acima para torn!@lo mais fle%vel, permitindo digitar os
nomes e os gastos de qualquer nJmero de pessoas. Assim ele ser! Jtil para repartir as contas de uma
viagem de frias ou daquela festa entre amigos. &ara comear, vamos construir um programa um
pouco mais simples, capaz de somar uma srie de nJmeros Ilistagem -K.
0istagem #
1 # somadora1.py - somadora infinita - versao 1
2
3 print 'Digite os valores a somar Seguidos de .'
4 print 'Para encerrar digite zero: 0'
5 n = float(raw_input(':'))
6 total = n
7 while n != 0:
8 n = float(raw_input(':'))
9 total = total + n
10 print 'TOTAL: %s' % total
Aamos ver o que faz esse programa, linha por linha.
:inhas . e /: 2i"imos as instruLes de uso.
:inha 0: Tsamos o comando ra(dinputIK para ei"ir o sinal ;:; e ler o primeiro valor digitado pelo
usu!rio, e a funo float para transformar a string resultante em um nJmero de ponto flutuante. '
resultado armazenado na vari!vel n.
:inha 1: A vari!vel total servir! para guardar a soma acumulada. &ara comear, colocamos nela o
primeiro valor digitado.
:inha ]: Aqui usamos um novo comando de "loco, o (hile. 2ssa linha pode ser traduzida assim:
;enquanto n diferente de zero...;. Assim como o comando for, o (hile causa a eecuo repetida do
"loco su"ordinado Ilinhas [ e NK. 2m um comando (hile, a repetio condicionada a uma epresso
lgica do mesmo tipo que usamos com o comando if. *esse eemplo, a condio n `b = causar! a
repetio do "loco enquanto for verdadeiro que n diferente de =. *o momento que n contiver o valor
=, a condio ser! falsa e a repetio deiar! de ocorrer. ' programa ento seguir! para a linha ,=.
:inha ,=: #ostramos o total acumulado. Dim do programa.
Mais sobre o 6hile
's comandos (hile e for so semelhantes por causarem a repetio de um "loco. Am"os so
chamados, pelos computlogos, de comandos de iterao Iiterao sin<nimo de repetioR no
confunda com ;interao;, que uma ao rec%proca entre dois ou mais agentesK.
A diferena que no comando for a iterao serve para percorrer uma lista de itens, como fizemos
anteriormente quando tra"alhamos com ta"elas de converso. *o caso do for, o nJmero de repetiLes
sempre conhecido de antemo: o "loco ser! eecutado uma vez para cada item da lista. ' comando
(hile serve para todos os outros casos de iterao, quando o nJmero de repetiLes indefinido. *ossa
somadora infinita um eemplo t%pico: a iterao que solicita valores e os totaliza poder! ser repetida
qualquer nJmero de vezes, dependendo apenas da sua vontade.
Agora vamos analisar de perto duas circunstBncias especiais. Sode o programa e digite = IzeroK como
primeiro valor. *as linhas 0 e 1 o programa armazenar! o zero nas vari!veis n e total. A seguir, na
linha ], o comando (hile verificar! a condio n `b =. *esse caso, a condio ser! falsa. 2nto o
"loco su"ordinado ao (hile no ser! eecutado nenhuma vez, e o programa passar! direto para a linha
,=, mostrando o total.
'utro momento interessante ocorre quando o primeiro valor digitado no zero, e a iterao
eecutada. 3igamos que o usu!rio digitou O,PO2nterP, O-PO2nterP e O=PO2nterP. ' zero digitado pelo
usu!rio ser! lido e armazenado em n na linha [, como j! vimos. *a linha N o valor de n somado ao
total. *essa iterao o valor de n zero, portanto estamos somando zero ao total, uma operao
inofensiva. 9 aps efetuar essa soma inJtil, o programa retornar! ao in%cio do "loco e verificar! que a
condio do (hile no mais verdadeira, pois agora nosso n igual a zero. importante perce"er
que, apesar de o valor de n passar a ser zero na linha [, a eecuo continua at o fim do "loco,
passando pela linha N, para s ento ocorrer o retorno ao in%cio do "loco e a verificao da condio de
continuidade da repetio.
_uando estudamos as condiLes lgicas no final do cap%tulo anterior, aprendemos que &)thon
considera o valor = IzeroK como sin<nimo de ;falso;, e valores no@zero como ;verdadeiros;.
&rogramadores eperientes em &)thon costumam tirar proveito desse fato para a"reviar as condiLes
que colocam em seus ifs e (hiles. 2m nosso programa somadora,.p), a linha ]:
while n != 0:
&ode ser escrita de forma mais a"reviada assim:
while n:
Daa essa alterao no programa e eperimente. Aoc$ ver! que nada mudou no seu funcionamento.
Fsso porque, quando n diferente de zero, a condio ;n; epressa em (hile n: considerada
verdadeira, e a iterao eecutada. _uando n passa a ser zero, a condio falsa, encerrando a
iterao.
0oops 7quase8 infinitos
'utra forma de escrever a somadora, mais elegante em minha opinio, a mostrada na listagem ..
0istagem ,
1 # somadora2.py - somadora infinita - versao 2
2
3 print 'Digite os valores a somar seguidos de .'
4 print 'Para encerrar digite zero: 0'
5 total = 0
6 while 1:
7 n = float(raw_input(':'))
8 if n == 0: break
9 total = total + n
10 print 'TOTAL: %s' % total
Aqui a lgica um pouco diferente: na linha 1 o loop (hile tem como condio o nJmero ,. +omo o
nJmero , constante, e considerado ;verdadeiro; pelo interpretador &)thon, o loop das linhas 1 a N
seria repetido infinitas vezes, em tese. *a pr!tica, a linha [ verifica se o valor de n zero. 2m caso
afirmativo, o comando ;"rea5; acionado. Fsso faz com que o loop (hile seja interrompido
imediatamente, e a eecuo do programa passa diretamente para a prima linha aps o "loco Ilinha
,= em nosso eemploK.
2ssa forma de codificar, usando loops infinitos com "rea5s, no est! de acordo com a &rogramao
2struturada, a filosofia dominante entre os programadores nos anos ]=. ' pro"lema que no fica
imediatamente aparente qual a condio de terminao do loop e alguns professores de computao
podem descontar pontos por isso. #as em se tratando de um "loco de apenas tr$s linhas, no acho que
isso seja um grande pro"lema. A vantagem que agora a funo de leitura de dados ocorre em apenas
um lugar no programa Ina linha ]K e no em dois, como na verso anterior Ilinhas 0 e [ de
somadora,.p)K. Fsso simplificar! nossa prima alterao. Alm disso, no acontece mais a totalizao
inJtil da linha N, somando zero ao total na sa%da, porque o comando "rea5 da linha [ faz o programa
passar direto para a linha ,=.
Tma forma mais natural de codificar esse loop seria usar comandos com o do4(hile ou repeat4until
eistentes em linguagens como +4+>>4?ava e &ascal43elphiR nessas estruturas de controle, o teste
feito no fim do loop, garantindo a eecuo do "loco ao menos uma vez. o que precisamos fazer
aqui, mas &)thon no possui um comando de loop especial para essa situao. Aejamos outro
eemplo.
9uponha que voc$ queira, por algum motivo estranho, somar os nJmeros naturais I,, -, . etc.K at
o"ter um total maior ou igual a ,==. '"serve na listagem / como ficaria o loop central para fazer isso
em &ascal, ?ava e &)thon.
0istagem 4
3elphi
REPEAT
n := n + 1;
total := total + n;
UNTIL (total >= 100);
?ava
do {
n = n + 1;
total = total + n;
} while (total < 100);
&)thon
while 1:
n = n + 1
total = total + n
if total >= 100: break
*ote que os tr$s programas acima esto incompletosR reproduzimos apenas o loop principal.
generalizando, qualquer loop com teste no final pode ser codificado em &)thon usando@se uma
com"inao de (hile , e if4"rea5, assim:
while 1:
comando1
comando2
# etc.
if condicao_final: break
Um programa mais tolerante
Tm defeito das nossas somadoras, e de todos os programas que fizemos at agora, que eles no
toleram falhas na digitao. 9e voc$ rodar o programa somadora-.p) e digitar apenas O2nterP para
encerrar, ver! a seguinte mensagem na tela:
Traceback (innermost last):
File 'somadora1.py', line 7, in ?
n = float(raw_input())
ValueError: empty string for float()
A segunda linha dessa mensagem identifica o local do erro: linha ] do arquivo IfileK somadora,.p).
*a terceira linha est! reproduzida a linha do programa onde ocorreu o pro"lema, e a mensagem final
informa qual foi o erro. &odemos traduz%@la assim: ;2rro de valor: string vazia para a funo floatIK;.
' pro"lema que, ao digitarmos O2nterP sem fornecer um nJmero, a funo ra(dinputIK retorna uma
string vazia Inada mais justo, pois nada foi digitadoK. 2m seguinda, a funo floatIK tenta transformar a
string vazia em um ponto flutuante, mas no sa"e como. ela que dispara a mensagem de erro,
fazendo com que o programa seja interrompido antes de mostrar o valor total da soma.
2feito semelhante pode ser o"tido se voc$ digitar um teto qualquer em vez de um nJmero.
2perimente.
*esse caso, a mensagem de erro final : ;Aalue2rror: invalid literal for floatIK: "lah;. *esse caso, a
reclamao de ;invalid literal;, significando que o teto fornecido para a funo floatIK no se parece
com um nJmero.
A melhor maneira de resolver esse pro"lema envolve o uso de mais uma comando de "loco de
&)thon: o conjunto tr)4ecept Itentar4ecetoK. 2sse par de palavras@chave formam o mecanismo de
;tratamento de eceLes; de &)thon, algo que s se encontra em linguagens "astante modernas como
?ava e as versLes mais recentes de +>>. A idia "!sica simples: no caso da nossa somadora, vamos
tentar Itr)K converter a string digitada em floatR se isso no der certo, temos uma eceo, que deve ter
tratamento especial. *o nosso caso, vamos simplesmente acionar o comando "rea5 para interromper o
loop e ei"ir a totalizao.
Aeja na listagem 0 como fica a somadora..p), agora com tratamento de eceLes.
0istagem 9
1 # somadora3.py - somadora infinita - versao 3
2
3 print 'Digite os valores a somar seguidos de .'
4 print 'Para encerrar apenas .'
5 total = 0
6 while 1:
7 try:
8 n = float(raw_input(':'))
9 total = total + n
10 except:
11 break
12 print 'TOTAL: %s' % total
Aamos comentar apenas as diferenas em relao C verso anterior:
:inha /: mudamos a mensagem para o usu!rio, j! que agora "asta um O2nterP para encerrar.
:inha ]: in%cio do "loco tr): tentaremos eecutar as linhas [ e N. _ualquer erro que ocorrer aqui ser!
tratado no "loco ecept.
:inha [: aqui o local mais prov!vel do erro, quando floatIK tenta converter o resultado de ra(dinput
IK.
:inha N: se ocorrer um erro na linha [, a linha N no ser! eecutada porque, dentro do "loco tr)
qualquer erro causa a transfer$ncia imediata da eecuo para o "loco ecept correspondente.
:inha ,=: in%cio do "loco ecept associado ao "loco tr) da linha ]
:inha ,,: tratamento do erro: em caso de eceo, vamos simplesmente interromper o loop com um
comando "rea5.
:inha ,-: como esta linha vem logo aps um loop infinito I(hile ,K, a Jnica forma de chegarmos aqui
atravs de um "rea5. 'u seja, nesse caso o loop s termina em conseqa$ncia de uma eceo.
2perimente o programa agora: ele ficou muito mais conveniente de usar. &ara interromper a soma e
o"ter o total, "asta teclar O2nterP em uma linha em "ranco. Tma "oa melhoria na ;usa"ilidade; da
somadora`
Como tratar um erro de 2erdade
A terceira verso da nossa somadora ainda no chegou l!: tratamos da mesma forma a situao em
que usu!rio no digitou nada e aquela onde ele digitou algo que no um nJmero v!lido em &)thon.
&ode ser que o usu!rio seja um datilgrafo C moda antiga, que digita : minJsculo no lugar do d%gito
,. 'u ainda algum que quer usar, com toda razo, a ;,; como separador decimal I&)thon s aceita
nJmeros com ponto decimalK. &ara diferenciar um tipo de erro do outro, e sa"er quando o usu!rio
apenas quer encerrar o programa, precisamos guardar a linha que ele digitou antes de tentar
transform!@la em um nJmero. Aeja como na listagem 1.
0istagem :
1 # somadora4.py - somadora infinita - versao 4
2
3 print 'Digite os valores a somar seguidos de .'
4 print 'Para encerrar apenas .'
5 total = 0
6 while 1:
7 try:
8 linha = raw_input(':')
9 n = float(linha)
10 total = total + n
11 except:
12 if len(linha) == 0:
13 break
14 elif ',' in linha:
15 print 'Use o . (ponto) como separador decimal.'
16 else:
17 print 'Isso nao parece um numero valido.'
18 print 'TOTAL: %s' % total
Aamos analisar as novidades dessa verso:
:inha [: a nova variavel linha armazena a linha digitada pelo usu!rio, para verificao posterior.
:inha N: a linha convertida em nJmero.
:inha ,,: in%cio do "loco que tratar! os erros, provavelmente ocorridos na linha N.
:inha ,-: a funo lenIK retorna o nJmero de itens de uma seqa$nciaR nesse caso, o nJmero de
caracteres da string linha. 9e o nJmero igual a zero, ento a string est! vazia.
:inha ,.: no caso da string vazia, eecutamos um "rea5 porque o usu!rio no quer mais digitar.
:inha ,/: o operador in IemK retorna verdadeiro se o item C esquerda for encontrado na seqa$ncia C
direitaR nesse caso verificamos se eiste uma v%rgula dentro da string linha.
:inha ,0: como encontramos uma v%rgula, vamos supor que o usu!rio tentou digitar um nJmero
fracion!rio. 2nto vamos sugerir que ele use o ponto decimal. *esse caso, no eecutamos o "rea5.
*enhum outro comando no "loco if4elif4else ser! eecutado, e o loop recomear! de novo a partir da
linha 1.
:inhas ,1 e ,]: aqui vamos tratar todos os demais casos, dizendo que o que foi digitado no se parece
com um nJmero. *ovamente, sem o "rea5, o loop reiniciar!, e logo o sinal c:c aparecer! na tela
aguardando nova digitao.
Associa!&o de nomes a 2alores
Aoltemos ao pro"lema do c!lculo de despesas. *ossa meta fazer um programa que seja capaz de
calcular a partilha de gastos de qualquer grupo de pessoas, e no apenas de Ana e 7ia. &ara isso,
vamos precisar associar o nome das pessoas aos seus respectivos gastos. A linguagem &)thon possui
uma estrutura de dados ideal para essa aplicao. o dicion!rio, conhecido pelos programadores &erl
como hash ou associao. +omo ocorre em &erl, em &)thon o dicion!rio serve para associar chaves a
valores. ' mais comum que as chaves sejam strings, como no nosso caso, onde as chaves sero
nomes de pessoas. #as as chaves podem ser qualquer tipo de o"jeto.
2m &)thon o dicion!rio "em mais poderoso que em &erl, pois seus valores podem conter qualquer
tipo de o"jeto como listas e at mesmo outros dicion!rios. &ara entender rapidamente o funcionamento
de um dicion!rio, nada melhor que eperimentar com o interpretador interativo F3:2. Daa os
seguintes testes, que eplicaremos a seguir, com a listagem ].
0istagem ;
1 Python 1.5.2 (#0, Apr 13 1999, 10:51:12) [MSC 32 bit (Intel)] on win32
2 Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam
3 dic = {}
4 >>> dic['ze'] = 300
5 >>> dic['mauricio'] = 100
6 >>> dic['heloisa'] = 150
7 >>> dic['ze']
8 300
9 >>> dic
10 {'mauricio': 100, 'ze': 300, 'heloisa': 150}
11 >>> dic['ze'] = 200
12 >>> dic
13 {'mauricio': 100, 'ze': 200, 'heloisa': 150}
14 >>> dic.keys()
15 ['mauricio', 'ze', 'heloisa']
16 >>> dic['paulo']
17 Traceback (innermost last):
18 File '', line 1, in ?
19 dic['paulo']
20 KeyError: paulo
21 >>> dic.has_key('heloisa')
22 1
23 >>> dic.has_key('paulo')
24 0
25 >>>
:inha .: antes de usar um dicion!rio, preciso cri!@lo. *esse caso, criamos um dicion!rio vazio. As
chaves WX so usadas para representar dicion!rios, como veremos novamente nas linhas ,= e ,..
:inhas /, 0 e 1: criamos tr$s itens no dicion!rio, usando as chaves czec, cmauricioc e cheloisac e os
valores .==, ,== e ,0=, respectivamente.
:inhas ] e [: aqui acessamos o valor associado C chave czec e o"temos o nJmero .==.
:inhas N e ,=: agora acessamos o dicion!rio como um todo, e o"temos uma listagem entre chaves,
com os itens separados por v%rgula. +ada par de chave e valor aparece separado pelo sinal c:c. *ote que
a ordem dos itens no tem lgica aparente. &)thon no garante a ordem dos itens de um dicion!rio.
:inha ,,: associamos um novo valor a uma chave eistente. *um dicion!rio, todas as chaves so
Jnicas. *o pode haver dois itens com a mesma chave czec. Assim, essa operao muda o valor
associado C esta chave.
:inhas ,- e ,.: ei"imos de novo o dicion!rio inteiro. *ote que o valor associado C chave czec mudou.
:inha ,/: o mtodo 5e)sIK retorna a lista de chaves do dicion!rio. Tm mtodo nada mais que uma
funo associada a um o"jeto, que deve ser invocada usando a sintae o"jeto.metodoIK. 2m nosso
eemplo temos dic.5e)sIK.
:inha ,0: aqui aparece a lista de chaves. *ote que a lista, como sempre, vem delimitada por
colchetes. ' resultado do mtodo 5e)sIK uma lista de chaves, e no um dicion!rio.
:inhas ,1 a -=: tentamos acessar o valor de uma chave ineistente. &)thon reclama com a mensagem
cfe)2rror: pauloc, indicando que o dicion!rio no possui uma chave igual a cpauloc.
:inhas -, a -/: para verificar se uma determinada chave eiste, usamos o mtodo hasd5e)IK
ItemdchaveK. 's eemplos mostram que hasd5e)IK retorna , quando a chave eiste, e zero quando ela
no eiste.
-esol2endo o <r!amento da -ep=blica
Agora que conhecemos o funcionamento "!sico dos dicion!rios, podemos implementar o nosso
aplicativo de acerto de contas, que pode ser muito Jtil por eemplo na administrao de uma repJ"lica
de universit!rios. Antes de mais nada, vejamos como vai funcionar o programa Ilistagem [K:
0istagem >
1 D:\magnet\aprendaprog\cap04>python desprep1.py
2 Balanco de despesas da Republica Recanto Suico
3
4 (deixe um nome em branco para encerrar)
5
6 Digite o nome da pessoa: Marcos
7 Quanto gastou Marcos? 10
8 Digite o nome da pessoa: Alexandre
9 Quanto gastou Alexandre? 500
10 Digite o nome da pessoa: Tyrone
11 Quanto gastou Tyrone? 250
12 Digite o nome da pessoa: Harley
13 Quanto gastou Harley? 124,67
14 Numero invalido.
15 Quanto gastou Harley? 124.67
16 Digite o nome da pessoa:
17
18 Numero de pessoas: 4
19 Total de gastos: R$ 884.67
20 Gastos por pessoa: R$ 221.17
21
22 Saldo de Marcos: -211.17
23 Saldo de Alexandre: 278.83
24 Saldo de Tyrone: 28.83
25 Saldo de Harley: -96.50
26
27 D:\magnet\aprendaprog\cap04>
:inha ,: invocao do programa a partir da linha de comando.
:inhas - e /: apresentao e instruLes de uso.
:inha 1: o programa pergunta o nome de uma pessoa.
:inha ]: a seguir, solicita o valor dos gastos daquela pessoa.
:inhas [ a ,-: o processo repetido quantas vezes for necess!rio.
:inha ,.: o usu!rio digita um nJmero com v%rgula no lugar do ponto decimal.
:inha ,/: o programa informa que o numero ;inv!lido;.
:inha ,0: novamente o programa pede o valor gasto por Garle).
:inha ,1: o usu!rio no fornece outro nome, encerrando a digitao.
:inhas ,[ a -=: o nJmero de pessoas, o total gasto e o gasto mdio por pessoa so calculados.
:inhas -- a -0: para cada pessoa, o programa ei"e seu saldo. Aqueles que t$m saldo negativo t$m
valores a pagarR os que de saldo positivo t$m valores a rece"er.
Agora, vamos C listagem do programa desprep,.p) Ilistagem NK:
0istagem ?
1 #desprep1.py - calculo de despesas da republica
2
3 print 'Balanco de despesas da Republica Recanto Suico'
4 print
5 print '(deixe um nome em branco para encerrar)'
6 print
7 total = 0
8 contas = {}
9 while 1:
10 pessoa = raw_input('Digite o nome da pessoa: ')
11 if not pessoa: break
12 while 1:
13 resp = raw_input('Quanto gastou %s? ' % pessoa)
14 try:
15 gasto = float(resp)
16 break
17 except:
18 print 'Numero invalido.'
19 contas[pessoa] = gasto
20 total = total + gasto
21
22 num_pessoas = len(contas)
23 print
24 print 'Numero de pessoas: %d' % num_pessoas
25 print 'Total de gastos: R$ %.2f' % total
26 media = total/num_pessoas
27 print 'Gastos por pessoa: R$ %.2f' % media
28 print
29 for nome in contas.keys():
30 saldo = contas[nome] - media
31 print 'Saldo de %s: %.2f' % (nome, saldo)
:inhas . a 0: ei"ir identificao e instruLes.
:inha ]: a vari!vel total inicializada com o valor zero. Fsso necess!rio em funo da linha -,.
:inha [: o dicion!rio de contas criado, sem conteJdo. 2le armazenar! as contas de cada pessoa.
:inha N: in%cio do loop principal.
:inha ,=: solicitamos um nome e armazenamos na vari!vel pessoa.
:inha ,,: se a vari!vel pessoa estiver vazia, nenhum nome foi digitado. 2nto eecutamos um "rea5
para deiar o loop principal, j! que o usu!rio no quer mais fornecer nomes.
:inha ,-: in%cio do loop secund!rio, para digitao do valor numrico.
:inha ,.: solicitamos o valor gasto pela pessoa em questo.
:inha ,/: in%cio do "loco tr), onde tentaremos converter a string digitada em nJmero.
:inha ,0: a converso fat%dica. 2m caso de erro aqui, o programa saltar! para o "loco ecept, na linha
,].
:inha ,1: esse "rea5 s ser! eecutado se no ocorrer erro na linha ,0. 9ua funo interromper o
loop secund!rio quando o"tivermos um valor numrico.
:inhas ,] e ,[: o "loco ecept simplesmente ei"e na tela a mensagem ;*umero invalido;. Aqui se
encerra o loop secund!rio, que repetir! novamente a partir da linha ,-, solicitando outro valor.
:inha ,N: o gasto o"tido armazenado no dicion!rio, usando o nome da pessoa como chave.
:inha -=: o total de gastos atualizado. Aqui o final do loop principal. 3aqui o programa voltar!
para a linha N, e pedir! os dados da prima pessoa.
:inha --: a funo lenIK usada para contar o nJmero de itens no dicion!rio.
:inhas -. a -0: so ei"idos o nJmero de pessoas e total gasto. A notao e.-f faz com que os gastos
apaream com duas casas decimais, pois trata@se de um valor em dinheiro.
:inhas -1 a -]: o gasto por ca"ea calculado e mostrado, tam"m com duas casas decimais.
:inha -N: aqui comeamos um loop for que ser! repetido para cada nome que constar na lista de
chaves do dicion!rio. A lista de chaves o"tida atravs do mtodo 5e)sIK. A vari!vel nome apontar!,
sucessivamente, para cada nome encontrado nesta lista.
:inha .=: os valor gasto por uma pessoa o"tido acessando o dicion!rio com a epresso contas
OnomeP. 9u"tra%mos o gasto mdio para o"ter o saldo daquela pessoa.
:inha .,: ei"imos o nome e o saldo da pessoa. 2sta a Jltima linha do loop for, que percorrer! todas
as chaves do dicion!rio.
1ossa primeira simula!&o
Agora j! sa"emos tudo o que precis!vamos para implementar um jogo simples, como hav%amos
prometido no cap%tulo anterior. 8rata@se de uma simulao de pouso lunar, em modo teto. 2sse
programinha "aseado em um jogo cl!ssico escrito para calculadoras G&@-0. *ossa verso "em
mais f!cil de entender que o original para calculadora Icuja listagem apareceu na seo A 6e" como
2la da #agnet nJmero .K. 2m vez de eplicar linha por linha o funcionamento do programa,
colocamos coment!rios a"undantes na prpria listagem, delimitados pelo sinal M. :em"re@se de que
no preciso digitar os coment!rios Ie o programa inteiro pode ser simplesmente copiado do site da
#agnetK. 2sse simulador de alunissagem um game de recursos m%nimos, mas ainda assim deve valer
alguns minutos de diverso, especialmente se voc$ curte a f%sica ne(toniana ensinada no colegial.
< @ogo da alunissagem
O jogo da alunissagem
# lunar.py
# importar funcao sqrt do modulo math
from math import sqrt
x = 500. # altitude em pes
v = -50. # velocidade em pes/s
g = -5. # aceleracao gravitacional lunar em pes/s/s
t = 1. # tempo entre jogadas em segundos
comb = 120. # quantidade de combustvel
print 'Simulacao de alunissagem'
print
print '(digite a quantidade de combustivel a queimar)'
fmt = 'Alt: %6.2f Vel: %6.2f Comb: %3d'
while x > 0: # enquanto nao tocamos o solo
msg = fmt % (x, v, comb) # montar mensagem
if comb > 0: # ainda temos combustivel?
# obter quantidade de combustivel a queimar
resp = raw_input(msg + ' Queima = ')
try: # converter resposta em numero
queima = float(resp)
except: # a resposta nao era um numero
queima = 0
if queima > comb: # queimou mais do que tinha?
queima = comb # entao queima o que tem
comb = comb - queima # subtrai queimado
a = g + queima # acel = grav + queima
else: # sem combustivel
print msg # mensagem sem perguntar
a = g # aceleracao = gravidade
x0 = x # armazenar posicao inicial
v0 = v # armazenar velocidade inicial
x = x0 + v0*t + a*t*t/2 # calc. nova posicao
v = v0 + a*t # calc. nova vel.
# se o loop acabou, tocamos no solo (x <= 0)
vf = sqrt(v0*v0 + 2*-a*x0) # calcular vel. final
print '>>>CONTATO! Velocidade final: %6.2f' % (-vf)
# avaliar pouso de acordo com a velocidade final
if vf == 0:
msg = 'Alunissagem perfeita!'
elif vf <= 2:
msg = 'Alunissagem dentro do padrao.'
elif vf <= 10:
msg = 'Alunissagem com avarias leves.'
elif vf <= 20:
msg = 'Alunissagem com avarias severas.'
else:
msg = 'Modulo lunar destruido no impacto.'
print '>>>' + msg
Como @ogar
9eu o"jetivo desacelerar a nave, queimando com"ust%vel na dosagem certa ao longo da queda, para
tocar o solo lunar com uma velocidade "em prima de zero. 9e voc$ quiser, pode usar um diagrama
como o mostrado a"aio Icolocamos em nosso site um desses em "ranco, para voc$ imprimir e usarK.
As unidades esto no sistema ingl$s, como no original. ' mais importante voc$ sa"er que cada 0
unidades de com"ust%vel queimadas anulam a acelerao da gravidade. 9e queimar mais do que 0
unidades, voc$ desaceleraR menos do que 0, voc$ ganha velocidade. &rimeiro, pratique seus pousos
preocupando@se apenas com a velocidade final. 3epois voc$ pode aumentar a dificuldade,
esta"elecendo um limite de tempo: por eemplo, o pouso tem que ocorrer em eatos ,. segundos.
Tma Jltima dica: cuidado para no queimar com"ust%vel cedo demais. 9e voc$ su"ir, vai aca"ar
caindo de uma altura ainda maior` 7oas alunissagens`
Aprenda a programar
Captulo 9
< segredo dos ob@etosAfun!&o' saiba como criar seus pr"prios comandos
por Luciano Ramalho
' simulador de alunissagem lunar.p), apresentado no Jltimo cap%tulo, tem 0= linhas de cdigo. um
jogo "em simples, mas foi nosso eemplo mais etenso at o momento. 2m termos de programao
profissional, trata@se de um programa "em pequeno. *o mundo real, soft(ares modestos t$m milhares
de linhas de cdigo, e essa contagem chega aos milhLes quando se fala de grandes alicativos como o
#icrosoft 6ord ou o sistema operacional :inu. Ao se tra"alhar com programas maiores,
fundamental poder dividir o tra"alho em mdulos, em vez de criar uma soluo ;monol%tica; com a do
nosso lunar.p), onde o programa inteiro est! epresso em uma Jnica sequ$ncia de comandos. A partir
de agora, vamos ver porque e como modularizar nossos programas, utilizando os conceitos de funo,
o"jeto, classe, mdulo e pacote.
/i2idir para conquistar
Tm programa modularizado facilita o planejamento, a distri"uio de tarefas entre v!rios
programadores, o controle de qualidade e a reutilizao de soluLes. &or eemplo, no cap%tulo anterior
utilizamos v!rias vezes sequ$ncias de comandos para ler dados do usu!rio, parecidas com o fragmento
do programa desprep,.p) Imostrado na listagem ,K.
' ideal seria reunir sequ$ncias como esta em um mdulo que ns pudssemos reutilizar facilmente
em qualquer um de nossos programas, em vez de redigitar ou cortar e colar esse cdigo sempre que
precisarmos reutiliz!@lo. Ao evitar a redigitao, no s economizamos tempo, mas ainda limitamos a
propagao de ;"ugs;, ou falhas de programao. Fmagine se, aps meses de programao, usando
centenas de vezes o fragmento, desco"rimos que ele contm um erro em sua lgica. 9e o cdigo foi
copiado manualmente para cada programa onde foi utilizado, seremos o"rigados a localiz!@lo e
corrigi@lo em centenas de arquivos diferentes. &or outro lado, se o fragmento foi devidamente
empacotado em um mdulo, a correo somente precisa ser feita em um arquivo.
0istagem 5
while 1:
resp = raw_input('Quanto gastou %s? ' % pessoa)
try:
gasto = float(resp)
break
except:
print 'Numero invalido.'
Programa!&o estruturada
A primeira grande onda a favor da modularizao no desenvolvimento de soft(are foi a chamada
;programao estruturada;. *o in%cio dos anos ]=, essa epresso estava to na moda quanto a
;programao orientada a o"jetos; de hoje. *a realidade, a programao orientada a o"jetos, ou ''&,
pode ser entendida como uma radicalizao da programao estruturada. A pea@chave da
programao estruturada o conceito de su"programa, um fragmento com comeo, meio e fim, que
desempenha um papel "em definido dentro de um programa maior. *a linguagem &)thon, um
su"programa definido atravs do comando de "loco def. 2istem dois tipos de su"programas:
procedimentos e funLes. 2m &)thon, a Jnica diferena entre eles que as funLes produzem valores,
e os procedimentos no. 9eguindo a tradio da linguagem +, os criadores do &)thon preferem falar
apenas de funLes, considerando os procedimentos apenas um tipo especial de funo.
Aamos usar o F3:2 para ver como se define uma funo. 3igite as duas linhas a"aio e tecle O2nterP
duas vezes para concluir:
>>> def dobro(x):
... return x * 2
Aparentemente, nada acontece. #as voc$ aca"ou de definir uma funo, chamada do"ro, que est!
armazenada na memria do interpretador &)thon. &ara ver sua funo funcionar, "asta invoc!@la
assim:
>>> dobro(3)
6
Agora vamos aos detalhes da nossa definio de funo. A primeira linha, def do"roIK:, traz duas
informaLes importantes: o nome da funo, do"ro, e a presena de um argumento, . ' argumento
uma vari!vel especial que associada ao valor fornecido pelo usu!rio na invocao da funo. Ao
rece"er a instruo do"roI.K, &)thon associa ao valor .. A segunda linha da funo, return V -
pode ser lida da direita para a esquerda. &rimeiro &)thon calcula a epresso V -. 2m nosso
eemplo, o est! associado ao valor ., portanto o resultado 1. ' comando return sinaliza o fim da
funo, e faz com que o resultado seja passado para quem a invocou. *o eemplo a"aio, a funo
invocada no meio de uma epresso aritmtica:
>>> y = dobro(7) + 1
>>> y
15
>>>
hora de que"rar algumas regras para ver o que acontece. &rimeiro, eperimente digitar isso:
>>> dobro()
' resultado ser! um ;trace"ac5; com a mensagem de erro ;not enough argumentsR epected ,, got =;,
ou ;argumentos insuficientesR , esperado, = rece"ido;. Fsso aconteceu porque nossa definio, def
do"roIK, o"riga o usu!rio da funo a fornecer um argumento. poss%vel criar uma funo que no
pede argumentos, como veremos depois.
'utro eperimento interessante digitar apenas o nome da funo:
>>> dobro
<function dobro at 82fa30>
Aale a pena parar e pensar no que aca"ou de acontecer.
9e voc$ digita o nome da funo sem par$nteses, o interpretador no a eecuta, mas apenas informa a
que se refere aquele nome. ' que ocorre quando usamos o comando def a criao, na memria, de
um o"jeto do tipo ;function;, ou funo. ' nome fornecido aps o comando def associado ao o"jeto@
funo. #as o o"jeto funo eiste independente do nome.
Bun!Ces como ob@etos
Aca"amos de fazer uma afirmao importante, que vale a pena repetir: &)thon permite criar funLes
que so tratadas da mesma forma que outros o"jetos da linguagem, como nJmeros e listas. &ara
entender as implicaLes disso, "om reforar o nosso entendimento de como &)thon lida com os
o"jetos que criamos. &ara tanto, vamos deiar as funLes um pouco de lado e voltar a "rincar com
listas:
>>> l = [10,20,30,40]
Aca"amos de criar uma lista ;l; com quatro elementos. 2ssa a forma sucinta de dizer o que ocorreu.
Tma descrio "em melhor a seguinte: criamos uma lista com quatro elementos e associamos a
vari!vel ;l; a esta lista. A letra ;l; apenas uma etiqueta que identifica a listaR importante notar que
a lista eiste mesmo antes de rece"er uma etiqueta.
+omprove:
>>> m = l
>>> m
[10, 20, 30, 40]
>>>
Agora associamos m a l, ou melhor, C lista associada a l. *osso o"jeto@lista agora tem duas etiquetas.
&odemos usar qualquer uma delas para se referir a ele, tanto que, ao digitarmos m, o interpretador
mostra a mesma lista. &odemos tam"m acessar e modificar um item espec%fico da lista:
>>> m[2]
30
>>> m[2] = 55
>>> m
[10, 20, 55, 40]
>>>
Agora digite l e veja o resultado:
>>> l
[10, 20, 55, 40]
>>>
' que aconteceu com o l^ A"solutamente nada` 2le continua sendo uma mera etiqueta colada em
nosso o"jeto@lista. #udamos a lista atravs da etiqueta m, mas tanto m quanto l referem@se C mesma
lista, como voc$ aca"ou de comprovar.
' mesmo ocorre com funLes. Ao interpretar o cdigo def do"roIK: return V -, &)thon cria um
o"jeto@funo e o associa C etiqueta do"ro. *ada impede que voc$ associe outras etiquetas ao mesmo
o"jeto, assim:
>>> f = dobro
>>> f
<function dobro at 82fa30>
*ote que o nome f agora est! associado ao mesmo o"jeto@funo que antes chamamos de do"ro.
' novo nome tam"m pode ser usado para invocar a funo:
>>> f(19)
38
>>> y = f(17) + 2
>>> y
36
>>>
Ao tratar funLes como o"jetos, &)thon deia para tr!s linguagens mais tradicionais como +>> e ?ava,
e se junta a uma classe de linguagens utilizadas em tra"alhos avanados de +i$ncia da +omputao:
linguagens de programao funcional. A mais famosa delas, :isp, tem sido ferramenta fundamental na
pesquisa de Fntelig$ncia Artificial h! v!rias dcadas. Tm dialeto simplificado de :isp, chamado
9cheme, usado nos cursos introdutrios de computao do #F8 I#assachussetts Fnstitute of
8echnolog)K, um dos mais importantes centros de pesquisa em inform!tica do planeta. +omo voc$ v$,
estudando &)thon estamos em tima companhia.
Aejamos na pr!tica uma vantagem de tratarmos funLes como o"jetos. &)thon possui uma funo
poderosa chamada map. Aamos us!@la agora:
>>> map(dobro, m)
[20, 40, 110, 80]
>>>
Fnvocamos a funo map com dois argumentos. ' primeiro a nossa funo do"ro, e o segundo a
lista m, O,=, -=, 00, /=P. A funo map aplica o o"jeto@funo a cada item do segundo argumento. '
resultado a criao de um novo o"jeto@lista, sem modificar o original.
Aeja este outro eemplo:
>>> map(str, m)
['10', '20', '55', '40']
>>>
*este caso, usamos a funo em"utida Iou pr@definidaK str para converter cada um dos itens
numricos em uma string.
Argumentos default
+omo j! dissemos, uma funo no precisa retornar um valor. Aeja este eemplo:
>>> def bom_dia():
... print 'Bom dia, humanide!'
Fsso o que chamamos de procedimento: uma funo que faz alguma coisa Ineste caso, imprime uma
mensagemK, mas no retorna um valor. Aoc$ pode invoc!@lo assim:
>>> bom_dia()
Bom dia, humanide!
>>>
inJtil usar esse procedimento em uma epresso:
>>> x = bom_dia()
Bom dia, humanide!
>>> x
>>> x == None
1
>>>
*ossa funo "omddia dispensa argumentos, j! que em sua definio no colocamos nada entre os
par$nteses. &ara sermos mais simp!ticos com nossos usu!rios, poder%amos modific!@la para aceitar um
nome, desta maneira:
>>> def bom_dia(nome = 'humanide'):
... print 'Bom dia, %s!' % nome
*ote que, neste caso, associamos um valor ao argumento nome. o chamado valor ;default;, que ser!
usado caso o argumento no seja fornecido.
Aeja como:
>>> bom_dia('Martinha')
Bom dia, Martinha!
>>> bom_dia()
Bom dia, humanide!
>>>
A idia de argumento default outro ponto forte da linguagem &)thon, oferecendo grande
flei"ilidade na definio de funLes.
Usando m"dulos
Tma vez entendido o "!sico de funLes, podemos passar para os mdulos, que so coleLes de
funLes. Antes de criarmos nossos prprios mdulos, "om aprender a usar mdulos prontos, para
no ficarmos ;reinventado a roda;. Assim como qualquer "oa linguagem moderna, &)thon possui uma
coleo de mdulos com milhares de funLes testadas e prontas para uso em diferentes tipos de
aplicaLes. A verso ,.0.- do &)thon inclui mais de ,/= mdulos, sem contar com a etenso gr!fica
85. 2 muitos outros podem ser encontrados a partir do site &)thon.org, quase todos livres e gratuitos.
_ue tipo de coisa pode ser encontrada nessa vasta "i"lioteca^ 2is alguns eemplos de mdulos,
apenas para dar uma idia:
cgi' programao de p!ginas dinBmicas para a 6e"
ftplib' montagem de scripts para interao com servidores D8&
gDip' leitura e escrita de arquivos comprimidos
math' funLes matem!ticas Itrigonometria, logaritmos etc.K
re' "uscas de teto avanadas com epressLes regulares Icomo na linguagem &erlK
string' operaLes com strings, incluindo conversLes de listas
time' hora atual e converso de formatos de data
Emllib' interpretao de arquivos em formato U#:
+omo primeiro eemplo de como se usa um mdulo, vamos recorrer ao mdulo calendar, um
conjunto de funLes de alto n%vel Iou seja, f!ceis de usarK para gerar calend!rios. Aoltando ao seu
interpretador &)thon, digite o seguinte:
>>> import calendar
' comando import geralmente no produz um resultado vis%vel. 2le localiza o mdulo mencionado,
carrega para a memria suas funLes e eecuta os comandos de inicializao do mdulo, se eistirem.
2m nosso caso, as funLes do arquivo calendar.p) aca"aram de ser lidas para a memria. &ara us!@las,
voc$ digita o nome do mdulo e o nome da funo separados por um ;.;:
>>> calendar.prmonth(2000,3)
March 2000
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 29 30 31
>>>
Dornecendo o ano e o m$s, voc$ rece"e o calend!rio do m$s prontinho. 2iste tam"m uma funo
para gerar um calend!rio anual. 2perimente:
>>> calendar.prcal(2000)
3evido a limitaLes das "i"liotecas@padro da linguagem + que so a "ase do &)thon, o mdulo
calendar no chega a ser um ;calend!rio perptuo;. 2le s tra"alha com datas de janeiro de ,N]= a
janeiro de -=.[. &ara os curiosos, a eplicao que, internamente, as funLes de + armazenam datas
contando o nJmero de segundos transcorridos desde ,4,4,N]=. 2atamente sete segundos aps ,:,/ da
madrugada do dia ,N4=,4-=.[, esse nJmero eceder! o limite de um nJmero inteiro de .- "its. mais
um "ug do novo mil$nio...
Agora, vamos supor que voc$ deseja ei"ir o calend!rio mensal de uma outra maneira, por eemplo,
separando os dias por ta"s, para facilitar a eportao para um programa de editorao eletr<nica. 'u
ainda, podemos querer gerar um calend!rio em G8#:. *esses dois casos, o resultado da funo
prmonthIK no muito Jtil. A funo monthcalendarIK nos d! mais li"erdade. Aeja como ela funciona:
>>> calendar.monthcalendar(2000,3)
[[0, 0, 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, 29, 30, 31, 0, 0]]
>>>
' resultado uma lista de listas. +ada uma das cinco listas de dentro representa uma semana com
seus respectivos dias. Heros aparecem nos dias que ficam fora do m$s.
Agora vamos comear a destrinchar o resultado da funo monthcalendar. Antes de mais nada, j! que
vamos usar muitas vezes essa funo, podemos economizar alguma digitao se usarmos uma outra
forma do comando import:
>>> from calendar import monthcalendar
Agora no precisaremos mais usar o prefio calendar, podendo chamar a funo monthcalendarIK
diretamente por seu nomeR assim:
>>> for semana in monthcalendar(2000,3):
... print semana
...
[0, 0, 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, 29, 30, 31, 0, 0]
>>>
Atravs do comando for, listamos separadamente cada semana. &ara tra"alhar com cada dia
individualmente, podemos criar outro comando for para percorrer cada uma das semanas. ' resultado
voc$ pode ver na listagem -.
A cada ciclo do primeiro for, a vari!vel semana representa uma lista de sete dias. *o segundo for,
cada ciclo escreve na tela um dia. &ara que todos os dias da semana apaream na mesma linha,
usamos um truque do comando print: a v%rgula no final de print ceshtc e dia, faz com que o &)thon
no inicie uma nova linha. *ote pela indentao que o Jltimo comando print est! dentro do primeiro
for, e no dentro do segundo. Fsso significa que esse print ser! eecutado uma apenas vez para cada
semana.
2m programao, sempre h! uma outra forma de o"ter algum resultado. *este caso, no resistimos C
tentao de mostrar um outro jeito de gerar a mesma listagem. ' mdulo string contm uma funo,
join, que serve para transformar listas em strings, concatenando IjuntandoK os elementos da lista com
algum elemento separador. &ara usar esta funo, precisamos primeiro import!@la:
>>> from string import join
&ara test!@la, eperimente digitar algo assim:
>>> join(['1','2','3'])
'1 2 3'
>>> join(['1','2','3'], ' + ')
'1 + 2 + 3'
>>>
*ote que o segundo argumento define a string que ser! usada como separador. *o primeiro eemplo,
omitimos o separador e &)thon usou o argumento default, um espao. Agora vamos pegar uma
semana do m$s para fazer mais algumas eperi$ncias:
>>> s = monthcalendar(2000,3)[0]
>>> s
[0, 0, 1, 2, 3, 4, 5]
>>>
Aqui usamos o mecanismo de indeao de &)thon para o"ter apenas uma semana do m$s.
+hamamos a funo monthcalendarI-===,.K com um %ndice, O=P. :em"re@se que monthcalendar
retorna uma lista de listas. ' %ndice O=P refere@se ao primeiro elemento da lista, ou seja a lista dos dias
da primeira semana de maro de -===. &ara ei"ir os dias dessa semana separados por ta"s, usamos a
funo join com o caractere de ta"ulao, representado por chtc, assim:
>>> join(s, '\t')
Traceback (innermost last):
File "<interactive input>", line 1, in ?
TypeError: first argument must be sequence of strings
>>>
'ops, &)thon reclamou: ;2rro de tipo: o primeiro argumento tem que ser uma sequ$ncia de strings;.
&recisamos transformar a lista s, que cont$m nJmeros, em uma lista de strings. Delizmente, aca"amos
de desco"rir como fazer isso usando a funo map, no in%cio deste cap%tulo:
>>> map(str, s)
['0', '0', '1', '2', '3', '4', '5']
Agora podemos eecutar o join:
>>> join(map(str,s), '\t')
'0\0110\0111\0112\0113\0114\0115'
' resultado ficou pouco apresent!vel, porque &)thon ei"e o caractere ;ta"; atravs de seu cdigo em
numerao octal, h=,,. #as isso no ocorre se usamos o comando print:
>>> print join(map(str,s), '\t')
0 0 1 2 3 4 5
>>>
Agora podemos fazer em duas linhas o que fizemos em quatro linhas na listagem -. Aeja a listagem ..
Agora que aprendemos o "!sico so"re funLes e sa"emos como importar mdulos, estamos prontos
para criar nossas prprias ;"i"liotecas de cdigo;. Goje vimos como definir e importar funLes. 2m
seguida, aprenderemos como organiz!@las em mdulos e us!@las no conteto de programas maiores,
aplicando primeiro conceitos da programao estruturada, e depois, da orientao a o"jetos. #as isso
ter! que ficar para o m$s que vem.
0istagem #
>>> for semana in monthcalendar(2000,3):
... for dia in semana:
... print '%s\t' % dia,
... print
...
0 0 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 29 30 31 0 0
>>>
0istagem ,
>>> for semana in monthcalendar(2000,3):
... print join( map(str,semana), '\t')
...
0 0 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 29 30 31 0 0
>>>
8eto: :uciano Samalho
Pginas dinFmicas em Python
Perca o medo do ser2idor Apache e do protocolo CG.
por Luciano Ramalho
hora de colocar em pr!tica os nossos conhecimentos de funLes e mdulos para criar nosso primeiro
programa para a Fnternet: o +alend!rio 3inBmico. Tma vez instalado em um servidor (e", ele ei"ir!
o calend!rio do m$s atual com o dia de hoje assinalado. Ao final desse cap%tulo voc$ ter! constru%do
seus primeiros programas +gF em linguagem &)thon. #as para chegar l!, preciso entender o
funcionamento de um +gF, e conhecer como se d! a operao "!sica de um servidor G88&.
$uem ( quem do HP
A 6e" constru%da a partir de duas tecnologias fundamentais: a linguagem G8#: e o protocolo
G88&. G8#:, ou G)pertet #ar5up :anguage a codificao usada para criar as p!ginas da 6e".
2ste no o assunto deste curso, mas vamos usar um pouco de G8#: nos eemplos desse cap%tulo.
9e voc$ quiser sa"er mais, h! um timo curso "!sico escrito por um cola"orador da #agnet, +aique
9evero. &rocure o lin5 na p!gina (((.magnet.com."r4aprendaprog4.
' segundo pilar da 6e" o G88&, ou G)pertet 8ransport &rotocol @ protocolo de transporte de
hiperteto. 2sse o conjunto de comandos e regras que define como deve ser a comunicao entre um
"ro(ser Icomo o Fnternet 2plorer ou o *etscape *avigatorK e um servidor G88& Icomo o Apache ou
o Fnterner Fnformation 9erverK. A epresso ;servidor G88&; pode significar duas coisas: o soft(are
que serve p!ginas via G88&, ou o computador onde esse soft(are est! instalado. *o mundo Tni,
softares servidores so chamados de ;daemons;, e a sigla G88&d descreve um ;G88& daemon;
genrico. 2ssa a sigla que vamos usar para diferenciar o soft(are do hard(are.
A relao entre um "ro(ser e um G88&d descrita pelos computlogos como ;cliente@servidor;. Fsso
significa que a interao entre esses dois soft(ares sempre parte do "ro(ser, que o cliente. '
servidor no tem nenhuma iniciativa, limitando@se a responder aos comandos enviados pelo cliente.
_uando voc$ digita uma TS: como http:44(((.tom@".com4nomono4inde.html, o seu "ro(ser
localiza e conecta@se ao servidor (((.tom@".com e envia@lhe o comando g28 4nomono4inde.html. '
servidor ento l$ o arquivo inde.html da pasta nomono, transmite seu conteJdo para o cliente e
encerra a coneo. 2sses so os passos "!sicos de qualquer interao de um "ro(ser com um G88&d:
coneo, solicitao, resposta e desconeo.
Pginas dinFmicas
*o eemplo que aca"amos de ver, inde.html o que chamamos de uma p!gina est!tica. A resposta
do servidor consiste apenas em enviar uma cpia do documento para o cliente. 9ites que incluem
transaLes Icomo lojas virtuaisK, interatividade Icomo chatsK, ou atualizaLes muito freqaentes Icomo
a #Ag*28K utilizam p!ginas dinBmicas. *este caso, ao rece"er a TS: http:44(((.magnet.com."r4
indedhtml, nosso servidor G88&d Apache passa a solicitao para o aplicativo Hope, instalado no
servidor Ileia mais so"re Hope na #agnet M.K. ' Hope monta imediatamente a p!gina indedhtml
listando as not%cias mais recentes de nosso "anco de dados, a hora atual e outros elementos. A p!gina
recm montada ento passada para o Apache, que finalmente a transmite para o seu navegador.
' Hope apenas uma das tecnologias de p!ginas dinBmicas que eistem hoje. ' A9& da #icrosoft, o
+oldDusion da Allaire e o soft(are livre &G& so outros sistemas dinBmicos de montagem de p!ginas.
#as o mecanismo mais antigo, e tam"m o mais simples de entender e de configurar, o velho e "om
+gF @ ou +ommon gate(a) Fnterface, um protocolo "!sico para interao entre um G88&d e um
programa gerador de p!ginas dinBmicas. com ele que nos vamos tra"alhar a partir de agora.
Configurando o seu HPd
&ara desenvolver aplicativos +gF importante ter um "om am"iente de testes. ' ideal ter acesso a
um G88&d s para voc$ na fase de desenvolvimento, para maior agilidade na depurao, e no correr
o risco de comprometer o funcionamento de um servidor pJ"lico com "ugs nos seus +gFs em
construo.
&ode ser que o seu micro j! possua um servidor G88&. A #icrosoft inclui o &ersonal 6e" 9erver ou
o FF9 em diferentes versLes do 6indo(s. Aoc$ pode tentar usar um desses G88&d para fazer os
eemplos, mas sugerimos fortemente que voc$ v! at o (((.apache.org "aie o Apache, que no
custa nada I open sourceK, roda em qualquer plataforma 6in.- ou Tni, f!cil de instalar e to
ro"usto e vers!til que o G88&d mais usado em todo mundo, alem de ser o favorito disparado entre
os melhores e maiores sites da 6e". Aale a pena conhec$@lo, e o do(nload tem apenas . #7.
*o 6indo(s, o Apache vem com um instalador "em amig!vel. *ossa Jnica recomendao instalar
diretamente em um diretrio como c:hapache e no no famoso c:hArquivos de &rogramas. Fsso porque
os espaos em nomes de diretrios Cs vezes causam pro"lemas na eecuo de programas origin!rios
do Tni como &)thon e o prprio Apache.
Tma vez terminada a instalao, voc$ deve rodar o servidor, acionando o programa ;9tart Apache;
que foi instalado em Fniciar o &rogramas o Apache 6e" 9erver. Fsso faz a"rir uma janela 3'9 com
uma mensagem como ;Apache4,...N I6in.-K running...;. *o feche esta janela, pois isso encerrar! a
eecuo do servidor. Agora voc$ pode ver se est! tudo certo digitando essa TS: m!gica em seu
"ro(ser: http:44,-].=.=.,4. 9e a instalao foi "em sucedida, voc$ ver! uma p!gina com o teto: ;Ft
6or5ed` 8he Apache 6e" 9erver is Fnstalled on this 6e" 9ite`; IDuncionou` ' servidor Apache est!
instalado neste 6e" 9ite`K. IDigura ,K.
Aale a pena sa"er que o endereo ,-].=.=., tem um significado especial. 's criadores da Fnternet
reservaram esse nJmero F& para o ;loop"ac5;, ou seja, testes de coneo de uma m!quina com ela
mesma. 2m outras palavras, o endereo ,-].=.=., sempre se refere C maquina onde voc$ est!, que
conhecida tam"m pelo nome ;localhost;. 9e o seu micro estiver "em configurado, a TS:
http:44localhost4 deve ter o mesmo efeito. +aso contr!rio, utilize o nJmero F& e vamos em frente.
3eu primeiro CG.
+hegamos ao grande momento. 9eguindo a tradio milenar, vamos comear fazendo um +gF em
&)thon que produz uma p!gina com as palavras ;'l!, #undo`;. ' programa completo voc$ v$ na
listagem ,.
Antes de digitar este eemplo, "om destacar dois aspectos essenciais. &rimeiramente, o coment!rio
da linha , importante. ' +gF no vai funcionar sem ele. Ao eecutar um script +gF, o Apache
procura na primeira linha um coment!rio especial marcado pelos caracteres cM`c. 's sinais cM`c devem
estar encostados na margem esquerda da p!gina, e o restante dessa linha deve conter o caminho at o
programa eecut!vel do interpretador que rodar! o script. *ote que o caminho pode ser especificado
usando a "arra c4c do Tni, em vez da contra@"arra chc preferida pelo 6indo(s.
2m meu computador, o &)thon est! instalado em uma pasta chamada ;p)thon; localizada no mesmo
drive onde est! o Apache I3:, no meu casoK. 9e o seu &)thon est! instalado em outro lugar, voc$
precisar! alterar a linha ,. 2m caso de dificuldades, nossa sugesto que voc$ desinstale o
interpretador e o reinstale em uma pasta ;p)thon; diretamente na raiz do mesmo disco onde voc$
aca"ou de instalar o Apache.
'utro detalhe importante so os print das linhas . e /. 9ua funo no meramente decorativa. '
comando print c+ontent@t)pe: tet4htmlc produz a parte o"rigatria do ca"ealho da p!gina, eigida
pelo protocolo +gF. 2ste ca"ealho define o tipo do documento a ser transmitido de acordo com um
esquema de classificao chamado ;#F#2;. ' ;tet4html; o ;#F#2 t)pe; padro de documentos
G8#:. Tm teto A9+FF puro teria o #F#2 t)pe ;tet4plain; e um arquivo de foto ?&2g seria
;image4jpeg;. ' print da linha / gera uma linha em "ranco, que marca o fim do ca"ealho. 9e uma
dessas duas linhas no for digitada corretamente, o +gF no funcionar!.
' restante da listagem apenas produz o cdigo G8#: de uma p!gina muito simples. 's comandos
marcados pelos sinais n e Q so os chamados tags, ou marcaLes, da linguagem G8#:. A marcao
nG,Q#ancheten4G,Q, por eemplo, define que uma manchete de n%vel ,, que ser! ei"ida pelo
navegador como um teto em letras grandes.
Listagem 1
1 #!/python/python
2
3 print 'Content-type:
text/html'
4 print
5 print '<HTML><BODY>'
6 print '<H1>Ol, Mundo!</H1>'
7 print '</BODY></HTML>'
.nstalar e testar o CG.
' programinha da listagem , dever! ser salvo com o nome ola.p) no diretrio cgi@"in dentro da pasta
do Apache. 2ste diretrio criado automaticamente pelo instalador do Apache no 6indo(s, mas deve
estar vazio inicialmente. +oloque o ola.p) ali dentro e faa o grande teste: digite http:44 ,-].=.=.,4cgi@
"in4ola.p) em seu "ro(ser. 3as duas, uma: ou voc$ viu a p!gina ;'l!, #undo`; e est! feliz com seu
primeiro +gF, ou ficou deprimido por encontrar uma mensagem de ;Fnternal 9erver 2rror;. *este
caso, sai"a que voc$ est! em "oa companhia: todo programador de +gF j! se deparou com esta
mensagem. 's que dizem que nunca a viram esto mentindo. #esmo que seu script tenha funcionado,
proveitoso entender as causas de um ;Fnternal 9erver 2rror; para sa"er como depur!@lo.
' ;Fnternal 9erver 2rror; ocorre quando o script +gF no gera um ca"ealho m%nimo, formado por
uma linha de +ontent@t)pe e uma linha em "ranco. o que o nosso ola.p) deveria fazer nas linhas . e
/. Aejamos passo a passo como diagnosticar a causa do pro"lema.
,K Aerifique se o script pode ser eecutado a partir do prompt do 3'9.
A"ra uma janela do 3'9 e digite:
> c: (ou d:)
' passo acima no necess!rio se voc$ j! est! no disco certo.
> cd \apache\cgi-bin
> python ola.py
*este momento, tr$s coisas podem acontecer:
aK o script funciona perfeitamente, ei"indo o ca"ealho, uma linha em "ranco, e o G8#: da p!gina @
pule para o passo -.
"K o 3'9 responde ;+omando ou nome de arquivo inv!lido; @ leia o passo .R
cK o interpretador &)thon ei"e um trace"ac5 e uma mensagem de erro qualquer @ v! at o passo /R
-K 9e o script funciona a partir do prompt mas no atravs do Apache, eistem quatro causas
poss%veis:
aK ' coment!rio da linha , est! incorreto. :em"re@se que ele que informa ao Apache qual
interpretador invocar para rodar o script. 9e o seu interpretador &)thon Ip)thon.eeK foi instalado na
pasta d:hp)thon, ento a linha , do seu script deve ser assim: M`d:hp)thonhp)thon.ee I*a verdade, a
etenso .ee dispens!vel, e se o Apache e o &)thon esto no mesmo disco, voc$ pode usar a
notao mais elegante do Tni e escrever apenas M`4p)thon4p)thonK
"K ' script no foi colocado na pasta cgi@"in. 9e o seu Apache foi instalado em c:hapache, o programa
ola.p) tem que estar eatamente neste local: c:hapachehcgi@"inhola.p). 9e este foi o pro"lema, corrija e
volte ao passo ,.
cK Apache pode no estar configurado para eecutar programas na pasta cgi@"in. Fsso no deve
acontecer em uma instalao nova do Apache, mas se voc$ est! usando um G88&d que foi instalado
por outra pessoa, ela pode ter mudado esta configurao. *este caso, pea ajuda ao respons!vel pela
instalao.
dK *o :inu, ou em qualquer Tni, o Apache dever! ter permisso de eecutar o script ola.p). &ara
tanto, voc$ pode precisar usar o comando chmod para setar o "it de eecuo de ola.p). 2m :inu, o
comando a"aio deve dar conta do recado:
$ chmod a+x ola.py
9e voc$ usa outro Tni, eperimente:
$ chmod 755 ola.py
Tma vez marcado como eecut!vel o script poder! ser invocado diretamente pelo nome, sem
necessidade de mencionar o interpretador, assim:
$ ola.py
9e este teste funcionou, tente acionar o script novamente pelo "ro(ser, porque um shell do Tni
tam"m utiliza o coment!rio M` da linha , para localizar o interpretador. 9e isto no deu certo, volte ao
item -a acima. 9e o teste funcionou mas o programa ei"e um trace"ac5, v! at o passo /.
.K Aerifique se o interpretador &)thon Iarquivo p)thon.ee no 3'9K est! instalado corretamente e em
local acess%vel. 9e ele foi instalado em uma pasta chamada c:hp)thon, o seguinte comando deve
acionar o seu +gF:
> c:\python\python ola.py
' que fazer ento:
aK se agora o script funcionou perfeitamente, ei"indo o ca"ealho, uma linha em "ranco, e o G8#:
da p!gina, pule para o passo -.
"K se voc$ continua vendo ;+omando ou nome de arquivo inv!lido; ou outra mensagem do sistema
operacional, verifique novamente o local eato da instalao do seu &)thon e se necess!rio, reinstale.
Deito isso, volte para o passo ,.
/K 9e ao rodar o script a partir do prompt voc$ est! vendo um trace"ac5 do interpretador &)thon, o
pro"lema est! mesmo dentro do seu programa. _uando ocorre um erro de sintae I9)nta2rrorK o
interpretador apenas leu, mas no chegou a eecutar nenhuma linha do seu script. Assim, o famoso
ca"ealho ;+ontent@t)pe: ...; e a linha em "ranco no so enviados para o servidor, e o trace"ac5 que
o ajudaria a detectar o pro"lema no chega ao seu "ro(ser, mas vai para um arquivo onde o Apache
registra mensagens de erro. 2ste arquivo chama@se error.log e fica em 4apache4logs4. Aoc$ pode
inspecion!@lo com qualquer editor de teto. 'utras vezes, o erro pode acontecer durante a eecuo e
aps o envio do ca"ealho. *este caso, o trace"ac5 perdido para sempre. por isso que
programadores de +gF eperientes procuram testar eaustivamente seus scripts a partir da linha de
comando antes de tentar acion!@lo pelo "ro(ser. G! tam"em aguns truques que podem ser usados
durante a depurao de um +gF para que as mensagens de erro sejam transmitidas para o "ro(ser. 2m
seguida veremos como.
Afinal) um CG. dinFmico
*osso primeiro eemplo de +gF foi "olado para ser simples, mas tam"m um tanto tolo. *o gera
nenhuma informao vari!velR o mesmo efeito poderia ser o"tido com uma p!gina est!tica. A p!gina
dinBmica mais simples que conseguimos imaginar uma que mostre a hora certa Ide acordo com o
relgio do servidorK. &ara fazer um +gF assim, "om conhecermos duas funLes do mdulo time.
Aamos ver o que elas fazem acionando o interpretador &)thon. &rimeiro, temos que importar as duas
funLes de dentro do mdulo:
>>> from time import time,
localtime
&odemos invocar diretamente a funo timeIK:
>>> time()
953500536.8
_ue nJmero esse^ +omo eplicamos no final do cap%tulo passado, o &)thon, assim como muitos
programas origin!rios da plataforma Tni, marca o tempo contando o nJmero de segundos desde , de
janeiro de ,N]=. Fsto quer dizer que haviam se passado N0. milhLes, 0== mil e 0.1 segundos e [
dcimos desde ,4,4,N]= quando eu digitei timeIK no F3:2 do meu computador. Fsto muito
interessante, mas como transformar segundos transcorridos na hora atual^ para isso que serve a
funo localtimeIK:
>>> t = time()
>>> localtime(t)
(2000, 3, 19, 18, 33, 19, 6, 79,
0)
>>>
Agora ns associamos os segundos transcorridos C vari!vel t, e em seguida usamos a funo localtime
para transformar os segundos em uma seqa$ncia de N nJmeros que fornecem os seguintes dados:
localtimeItKO=:.P @Q -===, ., ,N Iano, m$s e diaK
localtimeItKO.:1P @Q ,[, .., ,N Ihora, minutos e segundosK
localtimeItKO1P @Q 1 Idia da semanaR = b segunda@feiraR 1 b domingoK
localtimeItKO]P @Q ]N InJmero do dia no anoR de , a .11 em anos "issetosK
localtimeItKO[P @Q = Iindicador de hor!rio de veroR = b noR , b simK
2sta funo se chama localtime porque alm de converter de segundos transcorridos para data e hora,
ela o faz levando em conta o fuso hor!rio configurado no sistema operacional, fornecendo portanto a
hora local. &ara sa"er a hora no meridiano de green(ich, ou T8+ no jargo moderno, usar%amos a
funo gmtimeIK:
>>> from time import gmtime
>>> gmtime(t)
(2000, 3, 19, 21, 33, 19, 6, 79,
0)
>>>
Agora vamos com"inar as novas funLes para montar um +gF, hora.p), que mostre a hora local do
servidor I:F98Ag2# -K.
Listagem 2
1 #!/python/python
2 # hora.py - CGI que exibe a hora local do servidor
3
4 from time import time, localtime
5
6 print 'Content-type: text/html'
7 print
8
9 h, m, s = localtime(time())[3:6]
10 print '<HTML><BODY>'
11 print '<H1>Hora: %02d:%02d:%02d</H1>' % (h, m, s)
12 print '<P>* de acordo com o relgio interno deste
servidor</P>'
13 print '</BODY></HTML>'
Tma vez salvo no diretrio cgi@"in, este script poder! ser acessado pela TS: http:44 ,-].=.=.,4cgi@
"in4hora.p). A p!gina gerada conter! a hora, minutos e segundos do instante em que ela foi invocada.
_ual o defeito do nosso relgio em +gF^ 2perimente e voc$ ver!.
Um rel"gio que se atualiDa
um pouco frustrante acessar uma p!gina que mostra a hora certa, com preciso de segundos, mas
fica parada no tempo IDigura -K. &ara atualizar os segundos, voc$ tem que acionar o comando de
;reload; do seu "ro(ser I2i"ir o Atualizar ou OD0P no Fnternet 2plorerR Aie( o Seload ou O+ontrolP
OSP no *avigatorK. *ossa p!gina parece um relgio que"rado, que s mostra a hora certa quanto
chacoalhado.
' ideal seria que o servidor atualizasse a p!gina que est! no seu "ro(ser a cada segundo.
Fnfelizmente, isso imposs%vel. +omo j! dissemos, o protocolo G88& do tipo cliente@servidor, e isto
quer dizer que a iniciativa de toda interao fica do lado do cliente. *o h! como o servidor por conta
prpria enviar uma nova p!gina sem que ela seja antes solicitada pelo navegador. 2sta uma
limitao importante do protocolo G88& que voc$ precisa ter em mente ao "olar seus programas +gF.
's "ro(sers modernos suportam uma uma soluo parcial para este pro"lema. 2les reconhecem um
ca"ealho especial chamado Sefresh, cuja presena em um documento serve para instruir o "ro(ser a
solicitar novamente a p!gina aps algum tempo. ' argumento do Sefresh um nJmero de segundos
que o navegador deve esperar para pedir a atualizao. :ogo veremos como isso funciona na pr!tica.
&ara usar o Sefresh "asta acrescentar uma linha ao ca"ealho da resposta gerado pelo nosso +gF
hora.p). A nova verso, hora-.p) ficar! assim:
Listagem 3
1 #!/python/python
2 # hora2.py - CGI que exibe continuamente hora local do
servidor
3
4 from time import time, localtime
5
6 print 'Content-type: text/html'
7 print 'Refresh: 0.6'
8 print
9
10 h, m, s = localtime(time())[3:6]
11 print '<HTML><BODY>'
12 print '<H1>Hora: %02d:%02d:%02d</H1>' % (h, m, s)
13 print '<P>* de acordo com o relgio interno deste
servidor</P>'
14 print '</BODY></HTML>'
A Jnica novidade a linha ], onde acrescentamos ;Sefresh: =.1; ao ca"ealho. 2m vez de mandar o
"ro(ser atualizar a p!gina a cada , segundo, aps alguns testes decidimos faz$@lo a cada 1 dcimos de
segundo. Dizemos assim porque quanto eperimentamos com ;Sefresh: ,; a contagem
freqaentemente pulava um segundo, por eemplo de ,=:.=:-= direto para ,=:.=:--. Fsso no quer
dizer que o relgio adiantava, porque a cada nova solicitao a hora certa estava sendo consultada pelo
nosso +gFR mas como o tempo de espera somado ao tempo de solicitao e resposta era maior que ,
segundo, a ei"io da hora sofria alguns so"ressaltos.
Dazendo o refresh a cada 1 dcimos, muitas vezes estamos atualizando a p!gina duas vezes no mesmo
segundo, o que um desperd%cio de processamento. #as pelo menos nos livramos da enervante
pertur"ao na contagem. claro que se o servidor estiver so"recarregado, ele pode levar mais de um
segundo para responder. *esse caso, de nada adiantar! se "ro(ser fizer novas solicitaLes a cada =.1
segundo.
Calendrio /inFmico
Agora vamos juntar o que j! sa"emos so"re +gF com o mdulo calendar que vimos no cap%tulo
anterior para fazer um prottipo r!pido do nosso +alend!rio 3inBmico I:istagem /K.
As passagens mais interessantes da listagem / so comentados a seguir.
Listagem 4
1 #!/python/python
2 # calendin.py - calendrio dinmico - prottipo 1
3
4 print 'Content-type: text/html\n'
5
6 try:
7 from time import time, localtime
8 from calendar import monthcalendar
9 from string import join
10
11 ano, mes = localtime(time())[:2]
12
13 print '<HTML><TITLE>Calendrio Dinmico</TITLE>'
14 print '<BODY>'
15
16 print '<H1>Calendrio do ms %02d/%04d</H1>' % (mes,
ano)
17 print '<PRE>'
18 for semana in monthcalendar(ano, mes):
19 print join( map(str, semana),'\t' )
20 print '</PRE>'
21
22 except:
23 import sys
24 sys.stderr = sys.stdout
25 from traceback import print_exc
26 print '<HR><H3>Erro no CGI:</H3><PRE>'
27 print_exc()
28 print '</PRE>'
29
30 print '</BODY></HTML>'
:inha /: logo de sa%da produzimos o ca"ealho m%nimo necess!rio. A linha em "ranco, em vez de ser
gerada por um segundo comando print, est! inclu%da no final prpria string do ca"ealho Io chnc
representa uma que"ra de linha, e o prprio print produz outra que"raR assim o"temos a linha em
"ranco para encerrar o ca"ealhoK.
:inha 1: para facilitar a depurao, colocamos praticamente o +gF inteiro dentro de um "loco
tr)4ecept. _ualquer falha na eecuo deste "loco ser! tratada a partir da linha -.. +om isso, esse
script s dever! gerar um ;Fnternal 9erver 2rror; se houver um erro de sintae, justamente o tipo de
falha mais f!cil de localizar rodando o script a partir de uma linha de comando. 3esta forma a
depurao fica "em mais simples.
:inhas ] a N: importamos v!rias funLes, todas velhas conhecidas.
:inha ,,: etra%mos o ano e o m$s do resultado de localtimeItimeIKK.
:inha ,.: iniciamos a produo do G8#:, agora colocando um t%tulo na p!gina Ique aparecer! na
"arra de t%tulo da janela do "ro(serK.
:inhas ,] a -=: para simplificar a formatao do calend!rio, colocamos seu conteJdo entre um par de
tags n&S2Qn4&S2Q. ' tag n&S2Q faz com que o "ro(ser respeite as que"ras de linha at o tag
n4&S2Q. *ormalmente, o navegador ignora ta"ulaLes e que"ras de linha, tratando tudo como simples
espaos, mas isso estragaria nosso calend!rio, pois queremos mostrar uma semana por linha. ' cdigo
das linhas ,[ e ,N foi rou"ado sem alteraLes da listagem . do cap%tulo anterior.
:inha --: a"rimos um "loco ecept para tratar qualquer erro que tenha ocorrido at aqui. A"rir um
"loco ecept sem qualificar o tipo de eceo que ser! tratado normalmente uma m! idia, porque
pode mascarar muitos "ugs. *esse caso, o ecept ;pega@tudo; est! justificado porque em seguida
ei"iremos o trace"ac5 completo, revelando qualquer "ug que tentar se esconder.
:inhas -. e -/: importamos o mdulo s)s, para podermos manipular os o"jetos stdout e stderr. 2sses
so os chamados ;dispositivos lgicos; para onde toda a sa%da de dados do &)thon direcionada.
#ensagens geradas pelo comando print so enviadas para stdout, que normalmente est! associado C
tela do computador ou terminal. 3urante a eecuo de um +gF, o stdout redirecionado para o
G88&d, que vai enviar para o cliente tudo o que passar por este dispositivo. #ensagens de erro e
trace"ac5s do &)thon, no entanto, vo para stderr. 9e o script invocado pela linha de comando, o
stderr tam"m est! associado C tela, e assim podemos ver os trace"ac5s. #as ao eecutar um +gF, o
G88&d simplesmente ignora o dispositivo stderr aps o envio do ca"ealho, ocasionando a perda dos
trace"ac5s. *a linha -/ associamos s)s.stderr ao o"jeto s)s.stdout. 3esta maneira as mensagens de
erro passam a ser enviadas para o "ro(ser atravs do G88&d, como ocorre com os tetos gerados por
print.
:inha -0: importamos uma funo do mdulo trace"ac5 para uso na linha -].
:inha -1: geramos tags para uma linha horizontal InGSQK e o t%tulo c2rro no +gF:cR a"rimos um tag
n&S2Q para manter a formatao original das linhas do trace"ac5.
:inha -]: usamos a funo printdecIK do mdulo trace"ac5 para gerar o teto de uma descrio de
erro.
:inha .=: encerramos o programa gerando os tags que marcam o fim de uma p!gina G8#:.
Prot"tipo melhorado
Agora que colocamos o calend!rio "!sico para funcionar, est! na hora de melhorar sua apresentao.
Aamos deiar de lado o recurso preguioso do tag n&S2Q e colocar os dias do m$s dentro de uma
ta"ela constru%da em G8#: IDigura .K. Aproveitando outros recursos daquela linguagem, vamos
tam"m colorir os finais de semana e assinalar o dia de hoje. Aoc$ encontra o programa calendin-.p)
na listagem /.
Listagem 5
1 #!/python/python
2 # calendin2.py - calendrio dinmico - prottipo 2
3
4 print 'Content-type: text/html\n'
5
6 try:
7 from time import time, localtime
8 from calendar import monthcalendar
9 from string import join
10
11 ano, mes, hoje = localtime(time())[:3]
12
13 print '<HTML><TITLE>Calendrio Dinmico</TITLE>'
14 print '<BODY>'
15 print '<CENTER>'
16 print '<H1>Calendrio de %02d/%04d</H1>' % (mes, ano)
17 print '<TABLE>'
18 print '<TR>'
19 for dia_sem in
['seg','ter','qua','qui','sex','sab','dom']:
20 if dia_sem in ['sab','dom']: bgcolor = 'green'
21 else: bgcolor = 'blue'
22 print '<TH WIDTH="45" BGCOLOR="%s">' % bgcolor
23 print '<H3>%s</H3></TH>' % dia_sem
24 print '</TR>'
25 for semana in monthcalendar(ano, mes):
26 print '<TR>'
27 num_dia_sem = 0
28 for dia in semana:
29 if dia == hoje:
30 bgcolor = 'pink'
31 elif num_dia_sem >= 5:
32 bgcolor = 'lightgreen'
33 else:
34 bgcolor = 'lightblue'
35 print '<TD ALIGN="RIGHT" BGCOLOR="%s">' % bgcolor
36 if dia != 0:
37 print '<H2>%2d</H2>' % dia
38 print '</TD>'
39 num_dia_sem = num_dia_sem + 1
40 print '</TR>'
41 print '</TABLE></CENTER>'
42
43 except:
44 import sys
45 from traceback import print_exc
46 sys.stderr = sys.stdout
47 print '<HR><H3>Erro no CGI:</H3><PRE>'
48 print_exc()
49 print '</PRE>'
50
51 print '</BODY></HTML>'
&rincipais novidades em relao C verso anterior:
:inha ,,: alm do ano e do m$s, guardamos o dia de hoje, para poder assinal!@lo no calend!rio.
:inha ,0: vamos centralizar tudo na p!gina.
:inha ,]: a"rimos o tag n8A7:2Q que conter! o calend!rio propriamente dito. 2sta ta"ela s ser!
fechada pelo tag n48A7:2Q na linha /, do programa.
:inha ,[: iniciamos a primeira linha da ta"ela In8SQ b 8a"le So( ou linha da ta"elaK.
:inha ,N: vamos percorrer os nomes dos dias da semana para construir o ca"ealho da ta"ela.
:inhas -= e -,: s!"ados e domingos tero fundos verdes IgreenKR demais dias tero fundos azuis
I"lueK.
:inha --: ta"elas em G8#: so divididas em ;clulas;. G! dois tags para definir clulas, o n8GQ
Ita"le head b ca"eaK e o n83Q Ita"le data b dadosK. 's dias da semana ficaro dentro de clulas 8G
com largura de /0 piels e a cor de fundo definida acima. A largura dessas clulas determinar! a
largura das colunas.
:inha -.: o nome de cada dia da semana colocado entre tags nG.Qn4G.Q, para $nfase, e o tag
n48GQ aplicado para fechar cada clula.
:inha -/: fechamos a primeira linha da ta"ela.
:inha -0: iniciamos um loop para percorrer cada semana do m$s.
:inha -1: a"rimos a linha da ta"ela correspondente a uma das semanas.
:inha -]: zeramos o contador que permitir! identificar s!"ados e domingos Ia funo monthcalendar
retorna semanas com in%cio Cs segundas@feirasR em nossa contagem, segunda@feira ser! o dia zeroK.
:inha -[: iniciamos outro loop, agora para percorrer cada dia da semana.
:inhas -N a ./: a cor do fundo da prima clula definida assim: a clula de hoje rosa Ipin5KR
s!"ados e domingos Idias 0 e 1 na semanaK sero verde@claro Ilight greenK e os demais dias sero azul@
claro Ilight "lueK
:inha .0: a"rimos a clula do dia, com a cor escolhida. 2la ser! fechada na linha .[.
:inhas .1 e .]: se o nJmero do dia diferente de zero, colocamos o conteJdo da clula. :em"re@se
que a funo monthcalendar completa com zeros as semanas do primeiro e Jltimo dia do m$s.
:inha .N: incrementamos o contador de dia da semana. Aqui se encerra o "loco que percorre os dias.
:inha /=: fechamos a linha da ta"ela. Dim do loop que corresponde Cs semanas.
Pr"Eimas paradas
Aqui termina nosso primeiro contato com programao aplicada C 6e". *este cap%tulo voc$ instalou
seu prprio servidor Apache, e implementou seus primeiros programas +gF. 's princ%pios que voc$
est! aprendendo aqui se aplicam a qualquer tecnologia de gerao de p!ginas dinBmicas. &ara
construir os eemplos, lanamos mo de cdigo G8#:. *o nosso o"jetivo aqui a"ordar esta outra
linguagem, mas no podemos fazer coisas interessantes na 6e" sem conhecer um pouco dela. Aamos
manter o uso de G8#: em um n%vel "em elementar, e continuaremos eplicando os tags mais
importantes de cada eemplo, mas seu aproveitamento poder! ser melhor se voc$ estudar por conta
prpria. ' tutorial do +aique, que voc$ encontra no site da #agnet, mais que suficiente para
acompanhar o restante deste curso.
*o primo nJmero, aperfeioaremos nosso calend!rio para torn!@lo interativo: em vez de mostrar
sempre o m$s atual, vamos permitir que o usu!rio escolha um m$s e um ano qualquer, e tam"m
navegue para frente e para tr!s de m$s em m$s. Fsso nos levar! a eplorar o uso de TS:s com
argumentos e formul!rios em G8#:. At l!`
%Eemplos
por Luciano Ramalho 2stes so alguns eemplos para serem treinados e estudados em casa. &ara
rod!@los, siga os passos a"aio:
=,. +lique so"re o lin5 desejado
=-. 2spere carregar o eemplo na nova janela que se a"riu
=.. +lique em Arquivo IDileK QQ 9alvar como I9ave asK
=/. 9alve o arquivo como .p) Ie: ta"uada.p)K
=0. A"ra o prompt do #9@3'9 Ique est! em &rogramas, do menu FniciarK
=1. 2ntre na pasta onde o arquivo foi salvo Ie: cd eemplosK
=]. 2ecute o arquivo com o comando p)thon nomedoarquivo.p) Ie: p)thon ta"uada.p)K
lista@cars.p)
lista@cars-.p)
md0.p)
porcentagens.p)
sistema@solar.p)
sistema@solar-.p)
sistema@solar-a.p)
sistema@solar..p)
somador,.p)
somador-.p)
somador..p)
somador/.p)
ta"uada.p)
ta"uada-.p)
ta"uada-certo.p)
ta"uada..p)
ta"uada/.p)
ta"uada/".p)

Você também pode gostar