Sunteți pe pagina 1din 12

Este um curso intensivo mnimo para a linguagem de programao Python.

Para aprender mais, veja a


documentao no site www.python.org; especialmente o tutorial. Se voc est se perguntando porque
deveria se interessar, veja esta comparao entre o Python e outras linguagens.
Esta introduo tem recebido elogios de leitores satisfeitos, e est sendo traduzida para vrios idiomas,
entre os quais russo, noruegus, portugus (esta pgina!) e espanhol. A verso original, em ingls,
est aqui.

O bsico
Para comear, pense em Python como sendo pseudo-cdigo. Isto quase uma verdade. Variveis no
tm tipos, assim voc no precisa declar-las. Elas so criadas quando voc lhes atribui um valor, e so
destrudas quando no forem mais usadas. A atribuio feita pelo operador =. A igualdade testada
com o operador ==. Voc pode atribuir mais de uma varivel ao mesmo tempo:
Esconder nmero das linhas

1 x , y , z = 1, 2, 3

primeiro, segundo, terceiro = primeiro, segundo, terceiro

ou um, dois, tres = 1, 2, 3


Esconder nmero das linhas

1 a = b = 123
Os blocos so indicados somente pela indentao (nada de BEGIN/END ou chaves). Algumas estruturas
de controle so:
Esconder nmero das linhas

1
2
3
4
5
6
7
8
9
10

i f x < 5 or ( x > 10 and x < 20) :


pr i nt " O v al or es t c or r et o. "
i f x < 5 or 10 < x < 20:
pr i nt " O v al or es t c or r et o. "
f or i i n [ 1, 2, 3, 4, 5] :
pr i nt " Es t a a i t er a o nmer o" , i
x = 10
whi l e x >= 0:
pr i nt " x ai nda no negat i v o. "
x = x - 1

Os primeiros dois exemplos so equivalentes.


A varivel de ndice no lao for varia de acordo com os elementos de uma lista (escrita como no
exemplo). Para fazer um lao for comum (isto , um lao de contagem), use a funo embutida range().
Esconder nmero das linhas

1 # Mos t r a os v al or es de 0 a 99 i nc l us i v e.
2 f or v al or i n r ange( 100) :
3
pr i nt v al or

(A linha comeando por "#" um comentrio, sendo ignorada pelo interpretador.)


Vejamos: agora voc j sabe o suficiente (em teoria) para implementar qualquer algoritmo em Python.
Vamos incluir alguma interao bsica com o usurio. Para obter dados do usurio (a partir de
um prompt texto), use a funo embutida input().
Esconder nmero das linhas

1 x = i nput ( " Por f av or di gi t e um nmer o: " )


2 pr i nt " O quadr ado des s e nmer o " , x * x
A funo input() mostra o texto dado (o qual pode ser vazio) e deixa o usurio entrar qualquer valor
vlido em Python. Neste caso ns estamos esperando um nmero - se alguma outra coisa (como uma
string) for fornecida, o programa poder falhar. Para evitar isto ns devemos implementar alguma
checagem de erro. Eu no vou entrar em detalhes aqui; suficiente dizer que se voc deseja receber o
dado do usurio, literalmente como uma string (assim qualquer coisa pode ser fornecida), use a
funo raw_input(). Se voc deseja converter uma string s para um inteiro, voc poderia
usar int(s).
Nota: Se o usurio deseja fornecer uma string com input(), ele dever escrever as aspas
explicitamente. Em Python, as stringspodem ser delimitadas com aspas simples ou duplas.
Assim, j que temos estruturas de controle, entrada e sada - agora ns precisamos de algumas
estruturas de dados. As mais importantes so as listas e os dicionrios. As listas so escritas com
colchetes, e podem ser (naturalmente) aninhadas:
Esconder nmero das linhas

1 nome = [ " Cl ees e" , " J ohn" ]


2 x = [ [ 1, 2, 3] , [ y , z ] , [ [ [ ] ] ] ]
Uma das coisas mais interessantes sobre as listas que os seus elementos podem ser acessados
separadamente ou em grupos, atravs de indexao e corte em fatias. A indexao feita (como em
muitas outras linguagens) pela colocao do ndice entre os colchetes (Note que o primeiro elemento tem
ndice 0).
Esconder nmero das linhas

1 pr i nt nome[ 1] , nome[ 0] # Mos t r a " J ohn Cl ees e"


2 nome[ 0] = " Smi t h"
O corte em fatias parecido com a indexao, indicando-se os ndices inicial e final separados por dois
pontos (":")
Esconder nmero das linhas

1 x = [ " s pam" , " s pam" , " s pam" , " s pam" , " s pam" , " eggs " , " and" , " s pam" ]
2 pr i nt x [ 5: 7] # Mos t r a a l i s t a [ " eggs " , " and" ]
Observe que o ndice final no se inclui no resultado. Se um dos ndices omitido, assume-se que voc
deseja todos os elementos na direo correspondente. Por exemplo, lista[:3] significa "cada
elemento desde o incio da lista at o elemento 3, este no includo." (Poderia-se dizer na verdade que vai
at o elemento 4, desde que a contagem inicia do 0... Oh, tudo bem) list[3:] significaria, por outro
lado, "cada elemento da lista, comeando do elemento 3 (inclusive) at o ltimo inclusive." Para outros

resultados bem interessantes, voc pode usar nmeros negativos tambm: list[-3] o terceiro
elemento desde o final da lista...
J que estamos falando de indexao, interessante saber que a funo embutida len() fornece o
tamanho de uma lista (em nmero de elementos).
E agora, o que h sobre os dicionrios? Para ser breve, eles so como listas, mas o seu contedo no
est ordenado. Como voc os indexa ento? Bem, cada elemento tem uma chave, ou um "nome" que
usado para buscar o elemento tal qual um dicionrio de verdade. Eis dois dicionrios como exemplo:
Esconder nmero das linhas

1 { " Al i c e" :
2
" Cl ar i c e"
3 pes s oa = { '
4
'

23452532, " Bor i s " : 252336,


: 2352525, " Dor i s " : 23624643}
nome' : " Robi n" , ' s obr enome' : " Hood" ,
oc upa o' : " Ladr o" }

Agora, para obter a ocupao da pessoa, ns usamos a expressopessoa["ocupao"]. Se ns


desejarmos alterar o seu sobrenome, nos poderamos escrever:
Esconder nmero das linhas

1 pes s oa[ ' s obr enome' ] = " de Loc k s l ey "


Simples, no? Como as listas, os dicionrios podem armazenar outros dicionrios. Ou listas, que j
conhecemos. E naturalmente listas podem armazenar dicionrios tambm. Desta forma, voc pode
conseguir estruturas de dados bastante avanadas.

Funes
Prximo passo: Abstrao. Queremos dar um nome a um pedao de cdigo, e cham-lo com um
parmetro. Em outras palavras - ns queremos definir uma funo (ou "procedimento"). Isto fcil. Use a
palavra-chave def assim:
Esconder nmero das linhas

1 def quadr ado( x ) :


2
r et ur n x * x
3 pr i nt quadr ado( 2) # Mos t r a 4
Para os que podem entender: Quando voc passa um parmetro uma funo, voc vincula o parmetro
ao valor (passado), criando, portanto, uma nova referncia. Se voc mudar o "contedo" deste parmetro
no afetar o original. Funciona como em Java, por exemplo. Vamos dar uma olhada em um exemplo:
Esconder nmero das linhas

1
2
3
4
5

def mudar ( l i s t a_qual quer ) :


l i s t a_qual quer [ 1] = 4
x = [ 1, 2, 3]
mudar ( x )
pr i nt x # Mos t r a [ 1, 4, 3]

Como voc pode ver, a lista original que foi passada, e se a funo mud-la, essas mudanas sero
refletidas para o local de onde a funo foi chamada. Note, entretanto, o comportamento no seguinte
exemplo:
Esconder nmero das linhas

1
2
3
4
5

def naoMudar ( x ) :
x = 0
y = 1
naoMudar ( y )
pr i nt y # Mos t r a 1

Por que no h mudana agora? Porque ns no mudamos o valor! O valor passado o nmero 1 -- ns
no podemos mudar um nmero do mesmo modo que mudamos uma lista. O nmero 1 (e sempre ser)
o nmero 1. O que ns realmente fizemos foi mudar o contedo da varivel local (parmetro x), e isto no
afetar o ambiente (fora da funo).
Para os que no entenderam: No se preocupem com isso
Python tem muitas coisas "legais" como argumentos com nome e argumentos com valor padro, podendo
manipular um nmero varivel de argumentos para uma funo. Para mais informaes sobre isto, veja
a seo 4.7 do tutorial de Python.
Se voc sabe como usar funes em geral, isto basicamente o que voc precisa saber sobre elas em
Python. (Ah, sim... A palavra-chave return termina a execuo da funo e retorna o valor dado.)
Uma coisa que til saber, entretanto, que as funo so valores em Python. Assim se voc tem uma
funo como quadrado, voc pode fazer alguma coisa assim:
Esconder nmero das linhas

1 f i gur a = quadr ado


2 f i gur a( 2) # Mos t r a 4
Para chamar uma funo sem argumentos voc deve lembrar de escrever func() e no func. A
segunda forma, como mostrado, somente retorna a prpria funo, como um valor. (Isto ocorre com os
mtodos dos objetos tambm... Veja abaixo.)

Objetos e coisas...
Eu suponho que voc saiba como funciona a programao orientada a objetos. (De outra forma, esta
seo no faria muito sentido. Sem problemas... Comece a brincar sem os objetos :).) Em Python voc
define classes com a palavra-chave (surpresa!) class, assim:
Esconder nmero das linhas

1 c l as s Ces t a:
2
# Lembr e- s e s empr e do ar gument o * s el f *
3
def __i ni t __( s el f , c ont eudo=None) :
4
s el f . c ont eudo = c ont eudo or [ ]
5
def adi c i one( s el f , el ement o) :
6
s el f . c ont eudo. append( el ement o)
7
def mos t r e_me( s el f ) :

8
9
10
11

r es ul t = " "
f or el ement o i n s el f . c ont eudo:
r es ul t ado = r es ul t ado + " " + ` el ement o`
pr i nt " Cont m: " +r es ul t ado

Coisas novas aqui:


1.

Todos os mtodos (funes dentro de um objeto) recebem um argumento adicional no incio da


lista de argumentos, contendo o prprio objeto. (Chamado self neste exemplo, por conveno.)

2. Mtodos so chamados assim:objeto.mtodo(arg1, arg2).


3. Alguns nomes de mtodos, como __init__ so pr-definidos, e tm significado
especial. __init__ o nome do construtor da classe, isto , esta a funo que
chamada quando voc cria uma instncia.
4.

Alguns argumentos podem ser opcionais e ter um valor padro (como mencionado acima, na
seo sobre funes). Isto feito escrevendo-se a definio desta forma:

Esconder nmero das linhas

1 def s pam( i dade=32) : # . . .

Aqui, spam pode ser chamado com um ou zero parmetros. Se nenhum for usado, ento o
parmetro idade ter o valor 32.

"Lgica de curto-circuito." Este um ponto... Veja abaixo.

Aspas simples invertidas convertem um objeto para sua representao como string. (Assim se
elemento contm o nmero 1, ento elemento o mesmo que "1" sendo 'elemento' uma
string literal.)

O sinal de adio + usado tambm para concatenao de listas, e strings so na verdade listas
de caracteres (o que significa que voc pode usar indexao e corte em fatias e a funo len
com strings. Legal, no acha?)

Nenhum mtodo ou varivel membro protegido (nem privado, nem nada parecido) em Python.
Encapsulao na maioria das vezes um estilo de programao. (Se voc realmente precisar, existem
convenes para nomes de variveis, que permitem alguma privacidade :)).
E agora, sobre a lgica de curto-circuito...
Todos os valores em Python podem ser usados como valores lgicos. Alguns dos mais "vazios", tais
como [], 0, "" e None representam o valor lgico "falso", enquanto o resto dos valores (como [0], 1 ou "Ol
Mundo" representam o valor lgico "verdadeiro".
Assim, expresses lgicas como a and b so avaliadas deste modo: Primeiro, verifique se a
verdadeiro. Se no, ento simplesmente retorne-o. Se sim, ento simplesmente retorne b (o que ir
representar o valor lgico da expresso.). A lgica correspondente para a or b : se a verdadeiro,
ento retorne-o, Se no , ento retorne b.
Este mecanismo faz com que and e or se comportem como os operadores booleanos que
implementam, mas eles tambm permitem escrever expresses condicionais muito curiosas. Por
exemplo, o cdigo
Esconder nmero das linhas

1 i f a:
2
pr i nt a
3 el s e:
4
pr i nt b
Poderia ser substitudo por:
Esconder nmero das linhas

1 pr i nt a or b
Na verdade, isto j alguma coisa do idioma Python, assim melhor voc ir se acostumando. Isto o
que foi feito no mtodoCesta.__init__. O argumento conteudo tem um valor padro None(o que ,
entre outras coisas, falso). Portanto, para verificar se ele tem um valor, ns poderamos escrever:
Esconder nmero das linhas

1 i f c ont eudo:
2
s el f . c ont eudo = c ont eudo
3 el s e:
4
s el f . c ont eudo = [ ]
claro, agora voc sabe como fazer de uma forma melhor. E por que ns no demos o valor padro [] no
comeo? Porque da maneira como o Python funciona, isto daria a todas as Cestas a mesma lista vazia
como valor padro. To logo uma das listas comeasse a ser preenchida, todas as outras teriam os
mesmo elementos, e o padro no seria mais vazio... Para aprender mais sobre isto voc deveria ler a
documentao e procurar a diferena entre identidade e igualdade.
Outra forma de fazer o anterior :
Esconder nmero das linhas

1 def __i ni t __( s el f , c ont eudo=[ ] ) :


2
s el f . c ont eudo = c ont eudo[ : ]
Voc pode adivinhar como isto funciona? Ao invs de usar a mesma lista vazia para todos, ns usamos a
expresso conteudo[:] para fazer uma cpia (Usamos uma fatia que contm a lista toda.)
Assim, para fazer uma Cesta e us-la (isto . para chamar alguns dos seus mtodos) ns devemos fazer
algo assim:
Esconder nmero das linhas

1 b = Ces t a( [ ' ma ' , ' l ar anj a' ] )


2 b. adi c i one( " l i mo" )
3 b. mos t r e_me( )
H outros mtodos mgicos alm do __init__. Um desses mtodos __str__ que define como o
objeto ser conhecido quando for tratado como uma string. Ns poderamos usar este mtodo ao invs
de mostre_me():
Esconder nmero das linhas

1 def __s t r __( s el f ) :


2
r es ul t = " "
3
f or el ement o i n s el f . c ont eudo:

4
5

r es ul t ado = r es ul t ado + " " + s t r ( el ement o)


r et ur n " Cont m: " +r es ul t ado

Agora, se ns desejamos mostrar a cesta b, ns usaramos simplesmente:


Esconder nmero das linhas

1 pr i nt b
Legal, no acha?
Subclasses so feitas assim:
Esconder nmero das linhas

1 c l as s Ces t aSpam( Ces t a) :


2
# ...
Python permite herana mltipla, assim voc pode ter vrias superclasses entre parnteses, separadas
por vrgulas. Classes so instanciadas assim: x = Cesta(). Construtores so implementados, como
disse, com a definio de uma funo membro especial__init__. Digamos que CestaSpam tem um
construtor__init__(self,tipo).
assim: y = CestaSpam("maas").

Ento

voc

poderia

fazer

uma

cesta

spam

Se voc, no construtor de CestaSpam precisar chamar o construtor de uma ou mais superclasses, voc
poderia cham-los desta forma:Cesta.__init__(self). Note que alm dos parmetros comuns,
voc deve fornecer explicitamente o self, j que a superclasse__init__ no sabe qual instncia est
tratando.
Para saber mais sobre as maravilhas da programao orientada a objeto em Python, veja seo 9 do
tutorial de Python.

Um truque mental de Jedi


(Esta seo est aqui porque eu acho que ela muito interessante. Definitivamente esta seo no
necessria para comear a aprender Python.)
Voc gosta de exerccios mentais? Ento, se voc realmente ousado, voc gostar de ver o ensaio
do GuidoVanRossum sobre metaclasses. Se, entretanto, voc prefere no explodir sua mente, ir
igualmente satisfazer-se com este pequeno truque.
Python usa espaos de nomes dinmicos (no lxicos). Isto quer dizer que se h uma funo como esta:
Esconder nmero das linhas

1 def s uc o_l ar anj a( ) :


2
r et ur n x * 2
... onde uma varivel (neste caso x) no est ligada a um argumento e no dado um valor dentro da
funo, Python usar o valor que ela tiver onde e quando a funo for chamada. Neste caso:
Esconder nmero das linhas

1 x = 3

2
3
4
5
6

y =
# y
x =1
y =
# y

s uc o_l ar anj a( )
agor a 6
s uc o_l ar anj a( )
agor a 2

Normalmente este o tipo de comportamento esperado (apesar do exemplo ser um pouco rebuscado raramente acessamos variveis desta forma.) Entretanto, algumas vezes pode ser til ter um espao de
nomes esttico, ou seja, armazenar alguns valores do ambiente em que a funo criada. A maneira de
fazer isto em Python por meio dos argumentos padro.
Esconder nmero das linhas

1 x = 4
2 def s uc o_mac a( x =x ) :
3
r et ur n x * 2
Aqui, ao argumento x atribudo o valor padro que o mesmo valor da varivel x quando a funo
definida. Assim, se nenhum valor fornecido como argumento para a funo, ela ir funcionar assim:
Esconder nmero das linhas

1
2
3
4
5
6

x
y
#
x
y
#

=
=
y
=
=
y

3
s uc o_mac a( ) :
agor a 8
1
s uc o_mac a( ) :
agor a 8

Assim - o valor de x no alterado. Se isto era tudo que ns queramos, poderamos simplesmente ter
escrito
Esconder nmero das linhas

1 def s uc o_t omat e( ) :


2
x = 4
3
r et ur n x * 2
ou mesmo
Esconder nmero das linhas

1 def s uc o_c enour a( ) :


2
r et ur n 8
Entretanto, o ponto que o valor de x obtido do ambiente quando a funo definida. O quanto isto
til? Vejamos um exemplo: uma funo composta.
Ns queremos uma funo que funcione assim:
Esconder nmero das linhas

1 f r om mat h i mpor t s i n, c os
2 s i nc os = c omponha( s i n, c os )
3 x = s i nc os ( 3)

Onde componha a funo que queremos fazer, e x tem o valor -0.836021861538, que o mesmo que
sin(cos(3)). Agora, como faremos isto?
(Note que ns estamos usando funes como argumentos... Este o prprio truque.)
Claramente, componha toma duas funes como parmetros, e retorna uma funo que por sua vez
recebe um parmetro. Assim, um esqueleto da soluo seria:
Esconder nmero das linhas

1 def c omponha( f un1, f un2) :


2
def i nt er i or ( x ) :
3
pas s # . . .
4
r et ur n i nt er i or
Ns poderamos tentar return fun1(fun2(x)) dentro da da funo interior e deix-lo tal qual. No, no, no.
Isto teria um comportamento muito estranho. Imagine o seguinte cenrio:
Esconder nmero das linhas

1
2
3
4
5
6
7

f r om mat h i mpor t s i n, c os
def f un1( x ) :
r et ur n x + " mundo! "
def f un2( x ) :
r et ur n " Ol , "
s i nc os = c omponha( s i n, c os )
x = s i nc os ( 3)

# Us ando a v er s o i nc or r et a

Agora, qual valor x ter? Resposta: "Ol, mundo!". Por que isto? Porque quando chamada, ela toma o
valor de fun1 e fun2 do ambiente, no aqueles de quando foi criada. Para conseguir a soluo correta,
tudo que teremos que fazer usar a tcnica descrita anteriormente:
Esconder nmero das linhas

1 def c omponha( f un1, f un2) :


2
def i nt er i or ( x , f un1=f un1, f un2=f un2) :
3
r et ur n f un1( f un2( x ) )
4
r et ur n i nt er i or
Agora ns s temos que esperar que ningum fornea mais de um argumento funo resultante, pois
isto quebraria os esquemas :). E, a propsito, j que ns no precisamos do nome interior, e esta funo
contm somente uma expresso, ns podemos usar uma funo annima, usando a palavra-chave
lambda:
Esconder nmero das linhas

1 def c omponha( f 1, f 2) :
2
r et ur n l ambda x , f 1=f 1, f 2=f 2: f 1( f 2( x ) )
Sucinto, porm claro. Voc tem que gostar
(E se voc no entendeu nada, no se preocupe. Pelo menos eu espero t-lo convencido que Python
muito mais do que "uma linguagem para scripts"...

E agora...
S umas coisinhas para terminar. A maioria das funes e classes mais teis so colocadas em mdulos,
os quais so na verdade arquivos-texto contendo cdigo Python. Voc pode import-los e us-los em
seus programas. Por exemplo, para usar o mtodo split do mdulo padro string, voc pode ter estas
duas formas:
Esconder nmero das linhas

1 i mpor t s t r i ng
2 x = s t r i ng. s pl i t ( y )
Ou...
Esconder nmero das linhas

1 f r om s t r i ng i mpor t s pl i t
2 x = s pl i t ( y )
Para mais informaes sobre a biblioteca de mdulos padro, de uma olhada em www.python.org/doc/lib.
Contm muitos mdulos teis.
Todo o cdigo em um mdulo/script se executa quando importado. Se voc quer que o seu programa
seja tanto um mdulo importvel quanto um programa executvel, voc pode adicionar alguma coisa
parecida com isto no final do programa:
Esconder nmero das linhas

1 i f __name__ == " __mai n__" :


2
ex ec ut ar ( )
Esta uma forma mgica de dizer que se este mdulo esta sendo executado como um script executvel
(isto , que no est sendo importado por outro script), ento a funo executar deve ser chamada. E
claro, voc poderia fazer qualquer coisa aps os dois pontos...
E para aqueles que desejam fazer um script UN*X executvel, escreva isto como primeira linha do
arquivo:
Esconder nmero das linhas

1 #! / us r / bi n/ env py t hon
Finalmente, uma breve meno de um conceito importante: Excees. Algumas operaes (como diviso
por zero ou ler de um arquivo no-existente) produzem condies de erro ou excees. Voc pode at
criar suas prprias excees e lan-las em momentos adequados.
Se nada feito para tratar a exceo, seu programa termina e mostra uma mensagem de erro. Voc pode
evitar isto com uma construo try/except. Por exemplo:
Esconder nmero das linhas

1 def di v i s ao_s egur a( a, b) :


2
t r y:
3
r et ur n a/ b
4
ex c ept Zer oDi v i s i onEr r or :

r et ur n None

ZeroDivisionError uma exceo padro. Neste caso, voc poderia ter verificado se b era zero,
mas em muitos casos, esta estratgia no vivel. Alm disso, se no tivermos a clusula try em
divisao_segura, e dessa forma tornando arriscada a sua chamada, ns poderamos ainda fazer alguma
coisa assim:
Esconder nmero das linhas

1 t r y:
2
di v i s ao_i ns egur a( a, b)
3 ex c ept Zer oDi v i s i onEr r or :
4
pr i nt " Foi t ent ada uma di v i s o por z er o em di v i s ao_i ns egur a"
Nos casos onde normalmente no haveriam problemas especficos, mas eles poderiam ocorrer, o uso de
excees evita tediosos testes, etc.
Bem - era isto. Espero que voc tenha aprendido alguma coisa. Agora pode ir brincar. E lembre-se do
lema do aprendizado em Python: "Use os fontes, Lucas." (Traduo: leia todo cdigo fonte a que voc
tiver acesso

Para comear, aqui est um exemplo. o conhecido algoritmo QuickSort, de Hoare. Uma

verso com a sintaxe destacada em cores est aqui.


Vale a pena mencionar uma coisa sobre este exemplo. A varivel done controla se partition foi finalizada,
ou no, na busca entre os elementos. Assim quando um dos dois laos internos querem terminar a
sequncia de trocas, eles atribuem 1 varivel done e interrompem-se a si prprios com break. Por que
os laos internos usam done? Porque, quando o primeiro lao interno finaliza com um break, o lao
seguinte s ser executado se done no estiver com o valor 1:
Esconder nmero das linhas

1 whi l e not
2
whi l e
3
#
4
whi l e
5
#

done:
not done:
Repet e- s e at oc or r er um br eak
not done:
S ex ec ut ado s e o pr i mei r o no at r i bui r 1 par a " done"

Uma verso equivalente, possivelmente mais clara, mas em minha opinio menos elegante que a anterior
poderia ser:
Esconder nmero das linhas

1 whi l e not done:


2
whi l e 1:
3
# Repet e- s e at oc or r er um br eak
4
i f not done:
5
whi l e 1:
6
# S ex ec ut ado s e o pr i mei r o no at r i bui r
" done"

1 par a

A nica razo para eu usar a varivel done no primeiro lao foi porque eu preferi manter a simetria entre
os dois laos. Desta forma poderia ser invertida a ordem e mesmo assim o algoritmo funcionaria.
Mais alguns exemplos podem ser encontrados na pgina tidbitde Joe Strout

S-ar putea să vă placă și