Você está na página 1de 452

A meta deste livro ensinar a voc a pensar como um cientista da computao.

. Esta maneira de pensar combina algumas das melhores caractersticas da matemtica, engenharia e cincias naturais. Como matemticos, os cientistas da computao usam linguagens formais para representar idias (especificamente, computaes). Como engenheiros, eles projetam coisas, montando sistemas a partir de componentes e avaliando as vantagens e desvantagens de diferentes alternativas. Como cientistas naturais, eles observam o comportamento de sistemas complexos, formulam hipteses e testam previses. A mais importante habilidade para um cientista da computao a soluo de problemas. A soluco de problemas a habilidade de formular questes, pensar criativamente sobre solues possveis e expressar uma soluo de forma clara e precisa. Ocorre que aprender a programar uma excelente oportunidade de praticar as habilidades da soluo de problemas. por isso que este captulo se chama? O caminho do programa?. Em um nvel, voc estar aprendendo a programar, uma habilidade til por si mesma. Em outro nvel, voc estar usando a programao como meio para um fim. medida que avanamos, este fim se tornar mais claro.

1.1 A linguagem de programao Python

1.3.1 Erros de sintaxe

Python somente pode executar um programa se o programa est sintaticamente correto; de outro modo, o processo falha e retorna uma mensagem de erro. Sintaxe se refere estrutura de um programa e s regras sobre esta estrutura. Por exemplo, em portugus, uma sentena deve comear com uma letra maiscula e terminar com um ponto. esta sentena contm um erro de sintaxe assim como est. Para a maioria dos leitores, uns poucos erros de sintaxe no so um problema significativo, o que o motivo pelo qual podemos ler a poesia moderna de e. e. cummings sem cuspir mensagens de erro. Python no to indulgente. Se existir um nico erro de sintaxe em qualquer lugar em seu programa, o interpretador Python exibir uma mensagem de erro e terminar, e voc no poder rodar o seu programa. Durante as primeiras semanas da sua carreira como programador, voc provavelmente perder um bocado de tempo procurando erros de sintaxe. Conforme ganhar experincia, entretanto, cometer menos erros e os encontrar mais rapidamente. 1.3.2 Erros em tempo de execuo (runtime errors)

O segundo tipo de erro o erro de runtime, ou erro em tempo de execuo, assim chamado porque no aparece at o momento em que voc rode o programa. Estes erros so tambm conhecidos como excees porque eles normalmente indicam que alguma coisa excepcional (e ruim) aconteceu. Erros de runtime so raros nos programas simples que voc ver nos primeiros captulos, assim levar algum tempo at que voc encontre um.

Captulo 1: Variveis, expresses e comandos


1.1 Valores e tipos O valor (por exemplo, letras e nmeros) uma das coisas fundamentais que um programa manipula. Os valores que j vimos at agora foram o 2 (como resultado, quando adicionamos 1 + 1) e "Al, Mundo!". Esses valores pertencem a tipos diferentes: 2 um inteiro, e "Al, Mundo!" uma string, assim chamada porque "string", em ingls, quer dizer sequncia, srie, cadeia (de caracteres), ou neste caso, "srie de letras". Voc (e o interpretador) consegue identificar strings porque elas aparecem entre aspas. O comando print tambm funciona com inteiros:
>>> print 4 4

Se voc estiver em dvida sobre qual o tipo de um determinado valor, o interpretador pode revelar:
>>> type ("Al, Mundo!") <type 'string'> >>> type (17) <type 'int'>

Nenhuma surpresa: strings pertencem ao tipo string e inteiros pertencem ao tipo int. Menos obviamente, nmeros com um ponto decimal pertencem a um tipo chamado float, porque estes nmeros so representados em um formato chamado ponto flutuante [1]:
>>> type (3.2) <type 'float'>

[1]

N.T.: Observe o uso de ponto no lugar da vrgula para separar a parte inteira da parte fracionria.

O que dizer de valores como "17" e "3.2"? Eles parecem nmeros, mas esto entre aspas, como strings:
>>> type("17") <type 'string'>

>>> type("3.2") <type 'string'>

Eles so strings. Ao digitar um nmero grande, tentador usar pontos entre grupos de trs dgitos, assim: 1.000.000. Isso no funciona porque Python usa o ponto como separador decimal. Usar a vrgula, como se faz em ingls, resulta numa expresso vlida, mas no no nmero que queramos representar:
>>> print 1,000,000 100

No nada do que se esperava! Python interpreta 1,000,000 como uma tupla, algo que veremos no Captulo 9. Por hora, lembre-se apenas de no colocar vrgulas nos nmeros. 2.2 Variveis Uma das caractersticas mais poderosas de uma linguagem de programao a habilidade de manipular variveis. Uma varivel um nome que se refere a um valor. O comando de atribuio cria novas variveis e d a elas valores:
>>> mensagem = "E a, Doutor?" >>> n = 17 >>> PI = 3.14159

Este exemplo faz trs atribuies. A primeira atribui a string "E a, Doutor?" a uma nova varivel chamada mensagem. A segunda d o valor inteiro 17 a n, e a terceira atribui o nmero de ponto flutuante 3.14159 varivel chamada pi. Uma maneira comum de representar variveis no papel escrever o nome delas com uma seta apontando para o valor da varivel. Esse tipo de figura chamado de diagrama de estado porque mostra em que estado cada varivel est (pense nisso como o estado de esprito da varivel). O diagrama a seguir mostra o resultado das instrues de atribuio: XXXfigura pg.13 O comando print tambm funciona com variveis:
>>> print mensagem E a, Doutor? >>> print n 17 >>> print pi 3.14159

Em cada um dos casos, o resultado o valor da varivel. Variveis tambm

tm tipo; novamente, podemos perguntar ao interpretador quais so eles:


>>> type(mensagem) <type 'string'> >>> type(n) <type 'int'> >>> type(pi) <type 'float'>

O tipo de uma varivel o tipo do valor ao qual ela se refere. 2.3 Nomes de variveis e palavras reservadas Os programadores geralmente escolhem nomes significativos para suas variveis -- eles documentam para o qu a varivel usada. Nomes de variveis podem ser arbitrariamente longos. Eles podem conter tanto letras quanto nmeros, mas tm de comear com uma letra. Embora seja vlida a utilizao de letras maisculas, por conveno, no usamos. Se voc o fizer, lembre-se de que maisculas e minsculas so diferentes. Bruno e bruno so variveis diferentes. O caractere para sublinhado ( _ ) pode aparecer em um nome. Ele muito utilizado em nomes com mltiplas palavras, tal como em meu_nome ou preco_do_cha_na_china. Se voc der a uma varivel um nome invlido, causar um erro de sintaxe:
>>> 76trombones = "grande parada" SyntaxError: invalid syntax >>> muito$ = 1000000 SyntaxError: invalid syntax >>> class = "Ciencias da Computacao 101" SyntaxError: invalid syntax

76trombones invlida porque no comea com uma letra. muito$ invlida porque contm um caractere ilegal, o cifro. Mas o que est errado com class? Ocorre que class uma das palavras reservadas em Python. Palavras reservadas definem as regras e a estrutura da linguagem e no podem ser usadas como nomes de variveis. Python tem 29 palavras reservadas:
and def exec if not return assert del finally import or try break elif for in pass while class else from is print yield continue except global lambda raise

Pode ser til ter essa lista mo [2]. Se o interpretador acusar erro sobre um de seus nomes de varivel e voc no souber porqu, veja se o nome est na

lista. N.T.: esta lista pode ser obtida atravs do prprio interpretador Python, com apenas dois comandos: [2] System Message: WARNING/2 (<string>, line 1192) Literal block expected; none found. import keyword print keyword.kwlist 2.4 Comandos Um comando uma instruo que o interpretador Python pode executar. Vimos at agora dois tipos de comandos: de exibio (print) e de atribuio. Quando voc digita um comando na linha de comando, o Python o executa e mostra o resultado, se houver um. O resultado de um comando print a exibio de um valor. Comandos de atribuio no produzem um resultado visvel. Um script normalmente contm uma seqncia de comandos. Se houver mais de um comando, os resultados aparecero um de cada vez, conforme cada comando seja executado. Por exemplo, o "script":
print 1 x=2 print 2

produz a sada:
1 2

Novamente, o comando de atribuio no produz sada. 2.5 Avaliando expresses Uma expresso uma combinao de valores, variveis e operadores. Se voc digitar uma expresso na linha de comando, o interpretador avalia e exibe o resultado:
>>> 1 + 1 2

Embora expresses contenham valores, variveis e operadores, nem toda expresso contm todos estes elementos. Um valor por si s considerado

uma expresso, do mesmo modo que uma varivel:


>>> 17 17 >>> x 2

Avaliar uma expresso no exatamente a mesma coisa que imprimir um valor:


>>> mensagem = "E a, Doutor?" >>> mensagem 'E a, Doutor?' >>> print mensagem E a, Doutor?

Quando Python exibe o valor de uma expresso, usa o mesmo formato que voc usaria para entrar com o valor. No caso de strings, isso significa que as aspas so includas [3]. Mas o comando print imprime o valor da expresso, que, neste caso, o contedo da string. Num script, uma expresso sozinha um comando vlido, porm sem efeito. O script:
17 3.2 "Al, Mundo!" 1+1

no produz qualquer sada. Como voc mudaria o "script" para exibir os valores destas quatro expresses? 2.6 Operadores e operandos Operadores so smbolos especiais que representam computaes como adio e multiplicao. Os valores que o operador usa so chamados operandos. Todas as expresses seguintes so vlidas em Python e seus significados so mais ou menos claros:
20+32 hora-1 hora*60+minuto minuto/60 5**2 (5+9)*(15-7)

Em Python, os smbolos +, -, / e o uso de parnteses para agrupamento tm o mesmo significado que em matemtica. O asterisco (*) o smbolo para multiplicao e ** o smbolo para potenciao. Quando um nome de varivel aparece no lugar de um operando, ele substitudo pelo valor da varivel, antes da operao ser executada. Adio, subtrao, multiplicao e potenciao fazem o que se espera, mas voc pode ficar surpreso com a diviso. A operao seguinte tem um resultado

inesperado:
>>> minuto = 59 >>> minuto/60 0

O valor de minuto 59 e, em aritmtica convencional, 59 dividido por 60 0,98333, no 0. A razo para a discrepncia que Python est realizando uma diviso inteira. Quando ambos os operandos so inteiros, o resultado tem de ser tambm um inteiro e, por conveno, a diviso inteira sempre arredonda para baixo, mesmo em casos como este, em que o inteiro seguinte est muito prximo:
>>> minuto*100/60 98

De novo, o resultado arredondado para baixo, mas agora pelo menos a resposta aproximadamente correta. A alternativa usar a diviso em ponto flutuante, o que veremos no captulo 3. 2.7 Ordem dos operadores Quando mais de um operador aparece em uma expresso, a ordem de avaliao depende das regras de precedncia. Python segue as mesmas regras de precedncia para seus operadores matemticos que a matemtica. O acrnimo PEMDAS uma maneira prtica de lembrar a ordem das operaes: Parnteses tm a mais alta precedncia e podem ser usados para forar uma expresso a ser avaliada na ordem que voc quiser. J que expresses entre parnteses so avaliadas primeiro, 2 * (3-1) 4, e (1+1)**(5-2) 8. Voc tambm pode usar parnteses para tornar uma expresso mais fcil de ler, como em (minuto * 100) / 60, ainda que isso no altere o resultado. Exponenciao ou potenciao tem a prxima precedncia mais alta, assim 2**1+1 3 e no 4, e 3*1**3 3 e no 27. Multiplicao e Diviso tm a mesma precedncia, que mais alta do que a da Adio e da Subtrao, que tambm tm a mesma precedncia. Assim 2*3-1 d 5 em vez de 4, e 2/3-1 -1, no 1 (lembrese de que na diviso inteira, 2/3=0). Operadores com a mesma precedncia so avaliados da esquerda para a direita. Assim, na expresso minuto*100/60, a multiplicao acontece primeiro, resultando em 5900/60, o que se transforma produzindo 98. Se as operaes tivessem sido avaliadas da direita para a esquerda, o resultado poderia ter sido 59*1, que 59, que est errado. 2.8 Operaes com strings De maneira geral, voc no pode executar operaes matemticas em strings, ainda que as strings se paream com nmeros. O que segue invlido

(assumindo que mensagem do tipo string):


mensagem-1 "Al"/123 mensagem*"Al" "15"+2

Interessante o operador +, que funciona com strings, embora ele no faa exatamente o que voc poderia esperar. Para strings, o operador + representa concatenao, que significa juntar os dois operandos ligando-os pelos extremos. Por exemplo:
fruta = "banana" assada = " com canela" print fruta + assada

A sada deste programa banana com canela. O espao antes da palavra com parte da string e necessrio para produzir o espao entre as strings concatenadas. O operador * tambm funciona com strings; ele realiza repetio. Por exemplo, "Legal"*3 "LegalLegaLegal". Um dos operadores tem que ser uma string; o outro tem que ser um inteiro. Por um lado, esta interpretao de + e * faz sentido pela analogia entre adio e multiplicao. Assim como 4*3 equivale a 4+4+4, no de estranhar que "Legal"*3 seja o mesmo que "Legal"+"Legal"+"Legal". Por outro lado, uma diferena significativa separa concatenao e repetio de adio e multiplicao. Voc saberia mencionar uma propriedade da adio e da multiplicao que no ocorre na concatenao e na repetio? 2.9 Composio At agora, vimos os elementos de um programa -- variveis, expresses, e instrues ou comandos -- isoladamente, sem mencionar como combin-los. Uma das caractersticas mais prticas das linguagens de programao a possibilidade de pegar pequenos blocos e combin-los numa composio. Por exemplo, ns sabemos como somar nmeros e sabemos como exibi-los; acontece que podemos fazer as duas coisas ao mesmo tempo:
>>> print 17 + 3 20

Na realidade, a soma tem que acontecer antes da impresso, assim, as aes no esto na realidade acontecendo ao mesmo tempo. O ponto que qualquer expresso envolvendo nmeros, strings, e variveis pode ser usada dentro de um comando print. Voc j tinha visto um exemplo disto:
print "Nmero de minutos desde a meia-noite: ", hora*60+minuto

Esta possibilidade pode no parecer muito impressionante agora, mas voc ver outros exemplos em que a composio torna possvel expressar

computaes complexas de modo limpo e conciso. Ateno: Existem limites quanto ao lugar onde voc pode usar certos tipos de expresso. Por exemplo, o lado esquerdo de um comando de atribuio tem que ser um nome de varivel, e no uma expresso. Assim, o seguinte no vlido: minuto+1 = hora. 2.11 Glossrio valor (value) Um nmero ou string (ou outra coisa que ainda vamos conhecer) que pode ser atribuda a uma varivel ou computada em uma expresso. tipo (type) Um conjunto de valores. O tipo de um valor determina como ele pode ser usado em expresses. At agora, os tipos vistos so: inteiros (tipo int), nmeros em ponto-flutuante (tipo float) e strings (tipo string). ponto-flutuante (floating-point) Formato para representar nmeros que possuem partes fracionrias. varivel (variable) Nome que se refere a um valor. comando (statement) Trecho de cdigo que representa uma instruo ou ao. At agora, os comandos vistos foram de atribuio e exibio. atribuio (assignment) Comando que atribui um valor a uma varivel. diagrama de estado (state diagram) Representao grfica de um conjunto de variveis e os valores aos quais elas se referem. palavra-chave (keyword) Palavra reservada usada pelo compilador para analisar o programa; voc no pode usar palavras-chave como if, def, e while como nomes de variveis. operador (operator) Smbolo especial que representa uma computao simples, como adio, multiplicao ou concatenao de strings. operando (operand) Um dos valores sobre o qual o operador opera. expresso (expression) Combinao de variveis, operadores e valores, que representa um resultado nico. avaliar (evaluate) Simplificar uma expresso atravs da realizao de operaes, para produzir um valor nico. diviso inteira (integer division) Operao que divide um inteiro por outro e resulta em um inteiro. A diviso inteira resulta no nmero de vezes que o numerador divisvel pelo denominador e descarta qualquer resto. regras de precedncia (rules of precedence) O conjunto de regras que governa a ordem em que expresses envolvendo mltiplos operadores e operandos so avaliadas.

concatenar (concatenate) Juntar dois operandos lado a lado. composio (composition) Habilidade de combinar expresses e comandos simples em expresses e comandos compostos, de forma a representar computaes complexas de forma concisa. comentrio (comment) Informao em um programa dirigida a outros programadores (ou qualquer pessoa que esteja lendo o cdigo fonte) e que no tem efeito na execuo do programa.

Captulo 2: Variveis, expresses e comandos


System Message: INFO/1 (<string>, line 1395); backlink Duplicate implicit target name: "captulo 2: variveis, expresses e comandos". Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos o 3.4 Funes matemticas o 3.5 Composio o 3.6 Adicionando novas funes

3.7 Definies e uso 3.8 Fluxo de execuo 3.9 Parmetros e argumentos 3.10 Variveis e parmetros so locais 3.11 Diagramas da pilha 3.12 Funes com resultados 3.13 Glossrio Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio
o o o o o o o

5.4 Funes booleanas 5.5 Mais recursividade 5.6 Voto de confiana (Leap of faith) 5.7 Mais um exemplo 5.8 Checagem de tipos 5.9 Glossrio Captulo 6: Iterao Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores
o o o o o o

2.1 Valores e tipos System Message: INFO/1 (<string>, line 1401); backlink Duplicate implicit target name: "2.1 valores e tipos". O valor (por exemplo, letras e nmeros) uma das coisas fundamentais que um programa manipula. Os valores que j vimos at agora foram o 2 (como resultado, quando adicionamos 1 + 1) e "Al, Mundo!". Esses valores pertencem a tipos diferentes: 2 um inteiro, e "Al, Mundo!" uma string, assim chamada porque "string", em ingls, quer dizer seqncia, srie, cadeia (de caracteres), ou neste caso, "srie de letras". Voc (e o

interpretador) consegue identificar strings porque elas aparecem entre aspas. O comando print tambm funciona com inteiros:
>>> print 4 4

Se voc estiver em dvida sobre qual o tipo de um determinado valor, o interpretador pode revelar:
>>> type("Al, Mundo!") <type 'string'> >>> type(17) <type 'int'>

Nenhuma surpresa: strings pertencem ao tipo string e inteiros pertencem ao tipo int. Menos obviamente, nmeros com um ponto decimal pertencem a um tipo chamado float, porque estes nmeros so representados em um formato chamado ponto flutuante [4]:
>>> type(3.2) <type 'float'>

[3]

N.T.: Observe o uso de ponto no lugar da vrgula para separar a parte inteira da parte fracionria.

O que dizer de valores como "17" e "3.2"? Eles parecem nmeros, mas esto entre aspas, como strings:
>>> type("17") <type 'string'> >>> type("3.2") <type 'string'>

Eles so strings. Ao digitar um nmero grande, tentador usar pontos entre grupos de trs dgitos, assim: 1.000.000. Isso no funciona porque Python usa o ponto como separador decimal. Usar a vrgula, como se faz em ingls, resulta numa expresso vlida, mas no no nmero que queramos representar:
>>> print 1,000,000 100

No nada do que se esperava! Python interpreta 1,000,000 como uma tupla, algo que veremos no Captulo 9. Por hora, lembre-se apenas de no colocar vrgulas nos nmeros. 2.2 Variveis System Message: INFO/1 (<string>, line 1444); backlink Duplicate implicit target name: "2.2 variveis".

Uma das caractersticas mais poderosas de uma linguagem de programao a habilidade de manipular variveis. Uma varivel um nome que se refere a um valor. O comando de atribuio cria novas variveis e d a elas valores:
>>> mensagem = "E a, Doutor?" >>> n = 17 >>> pi = 3.14159

Este exemplo faz trs atribuies. A primeira atribui a string "E a, Doutor?" a uma nova varivel chamada mensagem. A segunda d o valor inteiro 17 a n, e a terceira atribui o nmero de ponto flutuante 3.14159 varivel chamada pi. Uma maneira comum de representar variveis no papel escrever o nome delas com uma seta apontando para o valor da varivel. Esse tipo de figura chamado de diagrama de estado porque mostra em que estado cada varivel est (pense nisso como o estado de esprito da varivel). O diagrama a seguir mostra o resultado das instrues de atribuio: XXXfigura pg.13 O comando print tambm funciona com variveis:
>>> print mensagem E a, Doutor? >>> print n 17 >>> print pi 3.14159

Em cada um dos casos, o resultado o valor da varivel. Variveis tambm tm tipo; novamente, podemos perguntar ao interpretador quais so eles:
>>> type(mensagem) <type 'string'> >>> type(n) <type 'int'> >>> type(pi) <type 'float'>

O tipo de uma varivel o tipo do valor ao qual ela se refere. 2.3 Nomes de variveis e palavras reservadas System Message: INFO/1 (<string>, line 1482); backlink Duplicate implicit target name: "2.3 nomes de variveis e palavras reservadas". Os programadores geralmente escolhem nomes significativos para suas

variveis -- eles documentam para o qu a varivel usada. Nomes de variveis podem ser arbitrariamente longos. Eles podem conter tanto letras quanto nmeros, mas tm de comear com uma letra. Embora seja vlida a utilizao de letras maisculas, por conveno, no usamos. Se voc o fizer, lembre-se de que maisculas e minsculas so diferentes. Bruno e bruno so variveis diferentes. O caractere para sublinhado ( _ ) pode aparecer em um nome. Ele muito utilizado em nomes com mltiplas palavras, tal como em meu_nome ou preco_do_cha_na_china. Se voc der a uma varivel um nome invlido, causar um erro de sintaxe:
>>> 76trombones = "grande parada" SyntaxError: invalid syntax >>> muito$ = 1000000 SyntaxError: invalid syntax >>> class = "Ciencias da Computacao 101" SyntaxError: invalid syntax

76trombones invlida porque no comea com uma letra. muito$ invlida porque contm um caractere ilegal, o cifro. Mas o que est errado com class? Ocorre que class uma das palavras reservadas em Python. Palavras reservadas definem as regras e a estrutura da linguagem e no podem ser usadas como nomes de variveis. Python tem 29 palavras reservadas:
and def exec if not return assert del finally import or try break elif for in pass while class else from is print yield continue except global lambda raise

Pode ser til ter essa lista mo [#]_. Se o interpretador acusar erro sobre um de seus nomes de varivel e voc no souber porqu, veja se o nome est na lista. N.T.: esta lista pode ser obtida atravs do prprio interpretador Python, com apenas dois comandos: [4] System Message: WARNING/2 (<string>, line 1516) Literal block expected; none found. import keyword print keyword.kwlist 2.4 Comandos

System Message: INFO/1 (<string>, line 1522); backlink Duplicate implicit target name: "2.4 comandos". Um comando uma instruo que o interpretador Python pode executar. Vimos at agora dois tipos de comandos: de exibio (print) e de atribuio. Quando voc digita um comando na linha de comando, o Python o executa e mostra o resultado, se houver um. O resultado de um comando print a exibio de um valor. Comandos de atribuio no produzem um resultado visvel. Um script normalmente contm uma seqncia de comandos. Se houver mais de um comando, os resultados aparecero um de cada vez, conforme cada comando seja executado. Por exemplo, o "script":
print 1 x=2 print 2

produz a sada:
1 2

Novamente, o comando de atribuio no produz sada. 2.5 Avaliando expresses System Message: INFO/1 (<string>, line 1545); backlink Duplicate implicit target name: "2.5 avaliando expresses". Uma expresso uma combinao de valores, variveis e operadores. Se voc digitar uma expresso na linha de comando, o interpretador avalia e exibe o resultado:
>>> 1 + 1 2

Embora expresses contenham valores, variveis e operadores, nem toda expresso contm todos estes elementos. Um valor por si s considerado uma expresso, do mesmo modo que uma varivel:
>>> 17 17 >>> x 2

Avaliar uma expresso no exatamente a mesma coisa que imprimir um

valor:
>>> mensagem = "E a, Doutor?" >>> mensagem 'E a, Doutor?' >>> print mensagem E a, Doutor?

Quando Python exibe o valor de uma expresso, usa o mesmo formato que voc usaria para entrar com o valor. No caso de strings, isso significa que as aspas so includas [#]_. Mas o comando print imprime o valor da expresso, que, neste caso, o contedo da string. Num script, uma expresso sozinha um comando vlido, porm sem efeito. O script:
17 3.2 "Al, Mundo!" 1+1

no produz qualquer sada. Como voc mudaria o "script" para exibir os valores destas quatro expresses? 2.6 Operadores e operandos System Message: INFO/1 (<string>, line 1582); backlink Duplicate implicit target name: "2.6 operadores e operandos". Operadores so smbolos especiais que representam computaes como adio e multiplicao. Os valores que o operador usa so chamados operandos. Todas as expresses seguintes so vlidas em Python e seus significados so mais ou menos claros:
20+32 hora-1 hora*60+minuto minuto/60 5**2 (5+9)*(15-7)

Em Python, os smbolos +, -, / e o uso de parnteses para agrupamento tm o mesmo significado que em matemtica. O asterisco (*) o smbolo para multiplicao e ** o smbolo para potenciao. Quando um nome de varivel aparece no lugar de um operando, ele substitudo pelo valor da varivel, antes da operao ser executada. Adio, subtrao, multiplicao e potenciao fazem o que se espera, mas voc pode ficar surpreso com a diviso. A operao seguinte tem um resultado inesperado:
>>> minuto = 59 >>> minuto/60

O valor de minuto 59 e, em aritmtica convencional, 59 dividido por 60 0,98333, no 0. A razo para a discrepncia que Python est realizando uma diviso inteira. Quando ambos os operandos so inteiros, o resultado tem de ser tambm um inteiro e, por conveno, a diviso inteira sempre arredonda para baixo, mesmo em casos como este, em que o inteiro seguinte est muito prximo:
>>> minuto*100/60 98

De novo, o resultado arredondado para baixo, mas agora pelo menos a resposta aproximadamente correta. A alternativa usar a diviso em ponto flutuante, o que veremos no captulo 3. 2.7 Ordem dos operadores System Message: INFO/1 (<string>, line 1611); backlink Duplicate implicit target name: "2.7 ordem dos operadores". Quando mais de um operador aparece em uma expresso, a ordem de avaliao depende das regras de precedncia. Python segue as mesmas regras de precedncia para seus operadores matemticos que a matemtica. O acrnimo PEMDAS uma maneira prtica de lembrar a ordem das operaes: Parnteses tm a mais alta precedncia e podem ser usados para forar uma expresso a ser avaliada na ordem que voc quiser. J que expresses entre parnteses so avaliadas primeiro, 2 * (3-1) 4, e (1+1)**(5-2) 8. Voc tambm pode usar parnteses para tornar uma expresso mais fcil de ler, como em (minuto * 100) / 60, ainda que isso no altere o resultado. Exponenciao ou potenciao tem a prxima precedncia mais alta, assim 2**1+1 3 e no 4, e 3*1**3 3 e no 27. Multiplicao e Diviso tm a mesma precedncia, que mais alta do que a da Adio e da Subtrao, que tambm tm a mesma precedncia. Assim 2*3-1 d 5 em vez de 4, e 2/3-1 -1, no 1 (lembrese de que na diviso inteira, 2/3=0). Operadores com a mesma precedncia so avaliados da esquerda para a direita. Assim, na expresso minuto*100/60, a multiplicao acontece primeiro, resultando em 5900/60, o que se transforma produzindo 98. Se as operaes tivessem sido avaliadas da direita para a esquerda, o resultado poderia ter sido 59*1, que 59, que est errado. 2.8 Operaes com strings

System Message: INFO/1 (<string>, line 1625); backlink Duplicate implicit target name: "2.8 operaes com strings". De maneira geral, voc no pode executar operaes matemticas em strings, ainda que as strings se paream com nmeros. O que segue invlido (assumindo que mensagem do tipo string):
mensagem-1 "Al"/123 mensagem*"Al" "15"+2

Interessante o operador +, que funciona com strings, embora ele no faa exatamente o que voc poderia esperar. Para strings, o operador + representa concatenao, que significa juntar os dois operandos ligando-os pelos extremos. Por exemplo:
fruta = "banana" assada = " com canela" print fruta + assada

A sada deste programa banana com canela. O espao antes da palavra com parte da string e necessrio para produzir o espao entre as strings concatenadas. O operador * tambm funciona com strings; ele realiza repetio. Por exemplo, "Legal"*3 "LegalLegaLegal". Um dos operadores tem que ser uma string; o outro tem que ser um inteiro. Por um lado, esta interpretao de + e * faz sentido pela analogia entre adio e multiplicao. Assim como 4*3 equivale a 4+4+4, no de estranhar que "Legal"*3 seja o mesmo que "Legal"+"Legal"+"Legal". Por outro lado, uma diferena significativa separa concatenao e repetio de adio e multiplicao. Voc saberia mencionar uma propriedade da adio e da multiplicao que no ocorre na concatenao e na repetio? 2.9 Composio System Message: INFO/1 (<string>, line 1645); backlink Duplicate implicit target name: "2.9 composio". At agora, vimos os elementos de um programa -- variveis, expresses, e instrues ou comandos -- isoladamente, sem mencionar como combin-los. Uma das caractersticas mais prticas das linguagens de programao a possibilidade de pegar pequenos blocos e combin-los numa composio. Por exemplo, ns sabemos como somar nmeros e sabemos como exibi-los; acontece que podemos fazer as duas coisas ao mesmo tempo:
>>> print 17 + 3 20

Na realidade, a soma tem que acontecer antes da impresso, assim, as aes no esto na realidade acontecendo ao mesmo tempo. O ponto que qualquer expresso envolvendo nmeros, strings, e variveis pode ser usada dentro de um comando print. Voc j tinha visto um exemplo disto:
print "Nmero de minutos desde a meia-noite: ", hora*60+minuto

Esta possibilidade pode no parecer muito impressionante agora, mas voc ver outros exemplos em que a composio torna possvel expressar computaes complexas de modo limpo e conciso. Ateno: Existem limites quanto ao lugar onde voc pode usar certos tipos de expresso. Por exemplo, o lado esquerdo de um comando de atribuio tem que ser um nome de varivel, e no uma expresso. Assim, o seguinte no vlido: minuto+1 = hora. 2.11 Glossrio System Message: INFO/1 (<string>, line 1664); backlink Duplicate implicit target name: "2.11 glossrio". valor (value) Um nmero ou string (ou outra coisa que ainda vamos conhecer) que pode ser atribuda a uma varivel ou computada em uma expresso. tipo (type) Um conjunto de valores. O tipo de um valor determina como ele pode ser usado em expresses. At agora, os tipos vistos so: inteiros (tipo int), nmeros em ponto-flutuante (tipo float) e strings (tipo string). ponto-flutuante (floating-point) Formato para representar nmeros que possuem partes fracionrias. varivel (variable) Nome que se refere a um valor. comando (statement) Trecho de cdigo que representa uma instruo ou ao. At agora, os comandos vistos foram de atribuio e exibio. atribuio (assignment) Comando que atribui um valor a uma varivel. diagrama de estado (state diagram) Representao grfica de um conjunto de variveis e os valores aos quais elas se referem. palavra-chave (keyword) Palavra reservada usada pelo compilador para analisar o programa; voc no pode usar palavras-chave como if, def, e while como nomes de variveis. operador (operator) Smbolo especial que representa uma computao simples, como adio, multiplicao ou concatenao de strings. operando (operand) Um dos valores sobre o qual o operador opera.

expresso (expression) Combinao de variveis, operadores e valores, que representa um resultado nico. avaliar (evaluate) Simplificar uma expresso atravs da realizao de operaes, para produzir um valor nico. diviso inteira (integer division) Operao que divide um inteiro por outro e resulta em um inteiro. A diviso inteira resulta no nmero de vezes que o numerador divisvel pelo denominador e descarta qualquer resto. regras de precedncia (rules of precedence) O conjunto de regras que governa a ordem em que expresses envolvendo mltiplos operadores e operandos so avaliadas. concatenar (concatenate) Juntar dois operandos lado a lado. composio (composition) Habilidade de combinar expresses e comandos simples em expresses e comandos compostos, de forma a representar computaes complexas de forma concisa. comentrio (comment) Informao em um programa dirigida a outros programadores (ou qualquer pessoa que esteja lendo o cdigo fonte) e que no tem efeito na execuo do programa. System Message: WARNING/2 (<string>, line 1716) Definition list ends without a blank line; unexpected unindent.

Captulo 3: Funes
Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos

2.5 Avaliando expresses 2.6 Operadores e operandos 2.7 Ordem dos operadores 2.8 Operaes com strings 2.9 Composio 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos o 3.4 Funes matemticas o 3.5 Composio o 3.6 Adicionando novas funes o 3.7 Definies e uso o 3.8 Fluxo de execuo o 3.9 Parmetros e argumentos o 3.10 Variveis e parmetros so locais o 3.11 Diagramas da pilha o 3.12 Funes com resultados o 3.13 Glossrio Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 5: Funes frutferas
o o o o o o

5.1 Valores de retorno 5.2 Desenvolvimento de programas 5.3 Composio 5.4 Funes booleanas 5.5 Mais recursividade 5.6 Voto de confiana (Leap of faith) 5.7 Mais um exemplo 5.8 Checagem de tipos 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores
o o o o o o o o o

3.1 Chamadas de funes Voc j viu um exemplo de uma chamada de funo:


>>> type('32') <type 'str'>

O nome da funo type e ela exibe o tipo de um valor ou varivel. O valor ou varivel, que chamado de argumento da funo, tem que vir entre parnteses. comum se dizer que uma funo 'recebe' um valor e 'retorna' um resultado. O resultado chamado de valor de retorno. Em vez de imprimir um valor de retorno, podemos atribui-lo a uma varivel:
>>> bia = type('32') >>> print bia <type 'str'>

Como outro exemplo, a funo id recebe um valor ou uma varivel e retorna um inteiro, que atua como um identificador nico para aquele valor:
>>> id(3) 134882108 >>> bia = 3 >>> bia(beth) 134882108

Todo valor tem um id, que um nmero nico relacionado ao local onde ele est guardado na memria do computador. O id de uma varivel o id do valor a qual ela se refere. 3.2 Converso entre tipos Python prov uma coleo de funes nativas que convertem valores de um tipo em outro. A funo int recebe um valor e o converte para inteiro, se possvel, ou, se no, reclama:
>>> int('32') 32 >>> int('Al') ValueError: invalid literal for int() : Al

int tambm pode converter valores em ponto flutuante para inteiro, mas lembre que isso trunca a parte fracionria:
>>> int(3.99999) 3 >>> int(-2.3) -2

A funo float converte inteiros e strings em nmeros em ponto flutuante:


>>> float(32)

32.0 >>> float('3.14159') 3.14159

Finalmente, a funo str converte para o tipo string:


>>> str(32) '32' >>> str(3.14149) '3.14149'

Pode parecer curioso que Python faa distino entre o valor inteiro 1 e o valor em ponto flutuante 1.0. Eles podem representar o mesmo nmero, mas pertencem a tipos diferentes. A razo que eles so representados de modo diferente dentro do computador. 3.3 Coero entre tipos Agora que podemos converter entre tipos, temos outra maneira de lidar com a diviso inteira. Voltando ao exemplo do captulo anterior, suponha que queiramos calcular a frao de hora que j passou. A expresso mais bvia, minuto / 60, faz aritmtica inteira, assim, o resultado sempre 0, mesmo aos 59 minutos passados da hora. Uma soluo converter minuto para ponto flutuante e fazer a diviso em ponto flutuante:
>>> minuto = 59 >>> float(minuto) / 60 0.983333333333

Opcionalmente, podemos tirar vantagem das regras de converso automtica entre tipos, chamada de coero de tipos. Para os operadores matemticos, se qualquer operando for um float, o outro automaticamente convertido para float:
>>> minuto = 59 >>> minuto / 60.0 0.983333333333

Fazendo o denominador um float, foramos o Python a fazer a diviso em ponto flutuante. 3.4 Funes matemticas Em matemtica, voc provavelmente j viu funes como seno (sin) e log, e aprendeu a resolver expresses como sin(pi/2) e log(1/x). Primeiro voc resolve e expresso entre parnteses (o argumento). Por exemplo, pi/2 aproximadamente 1,571, e 1/x 0.1 (se x for 10,0). A voc avalia a funo propriamente dita, seja procurando numa tabela ou realizando vrios clculos. O sin de 1,571 1 e o log de 0,1 -1 (assumindo

que log indica o logaritmo na base 10). Este processo pode ser aplicado repetidamente para avaliar expresses mais complicadas, como log(1/sin(pi/2)). Primeiro voc avalia o argumento na funo mais interna, depois avalia a funo e assim por diante. Python tem um mdulo matemtico que prov a maioria das funes matemticas mais familiares. Um mdulo um arquivo que contm uma coleo de funes relacionadas agrupadas juntas. Antes de podermos usar as funes contidas em um mdulo, temos de import-lo:
>>> import math

Para chamar uma das funes, temos que especificar o nome do mdulo e o nome da funo, separados por um ponto. Esse formato chamado de notao de ponto:
>>> decibel = math.log10(17.0) >>> angulo = 1.5 >>> altura = math.sin(angulo)

A primeira instruo atribui a decibel o logaritmo de 17 na base 10. Existe tambm uma funo chamada log, que pega o logaritmo na base e. A terceira instruo encontra o seno do valor da varivel angulo. sin e as outras funes trigonomtricas (cs, tan, etc.) recebem argumentos em radianos. Para converter de graus em radianos, divida por 360 e multiplique por 2*pi. Por exemplo, para encontrar o seno de 45 graus, primeiro calcule o ngulo em radianos e depois ache o seno:
>>> graus = 45 >>> angulo = graus * 2 * math.pi / 360.0 >>> math.sin(angulo) 0.707106781187

A constante pi tambm parte do mdulo math. Se voc sabe geometria, pode checar o resultado anterior comparando-o com a raiz quadrada de dois dividido por dois:
>>> math.sqrt(2) / 2.0 0.707106781187

3.5 Composio Do mesmo modo como nas funes matemticas, as funes do Python podem ser compostas, o que significa que voc pode usar uma expresso como parte de outra. Por exemplo, voc pode usar qualquer expresso como um argumento para uma funo:
>>> x = math.cos(angulo + pi/2)

Esta instruo toma o valor de pi, divide-o por 2, e soma o resultado ao valor de angulo. A soma ento passada como um argumento para a funo cos. Voc tambm pode pegar o resultado de uma funo e pass-lo como um argumento para outra:
>>> x = math.exp(math.log(10.0))

Esta instruo encontra o logaritmo base e de 10 e ento eleva e quela potncia. O resultado atribudo a x. 3.6 Adicionando novas funes At aqui, temos utilizado somente as funes que vm com Python, mas tambm possvel adicionar novas funes. Criar novas funes para resolver seus prprios problemas uma das coisas mais teis de uma linguagem de programao de propsito geral. No contexto de programao, funo uma seqncia nomeada de instrues ou comandos, que realizam uma operao desejada. Esta operao especificada numa definio de funo. At agora, as funes que usamos neste livro so pr-definidas e suas definies no foram apresentadas. Isso demonstra que podemos usar funes sem ter que nos preocupar com os detalhes de suas definies. A sintaxe para uma definio de funo :
def NOME( LISTA DE PARAMETROS ) : COMANDOS

Voc pode usar o nome que quiser para as funes que criar, exceto as palavras reservadas do Python. A lista de parmetros especifica que informao, se houver alguma, voc tem que fornecer para poder usar a nova funo. Uma funo pode ter quantos comandos forem necessrios, mas eles precisam ser endentados a partir da margem esquerda. Nos exemplos deste livro, usaremos uma endentao de dois espaos. As primeiras funes que vamos mostrar no tero parmetros, ento, a sintaxe ter esta aparncia:
def novaLinha(): print

Esta funo chamada de novaLinha. Os parnteses vazios indicam que ela no tem parmetros. Contm apenas um nico comando, que gera como sada um caractere de nova linha (isso o que acontece quando voc usa um comando print sem qualquer argumento).

A sintaxe para a chamada desta nova funo a mesma sintaxe para as funes nativas:
print 'Primeira Linha.' novaLinha() print 'Segunda Linha.'

A sada deste programa :


Primeira Linha. Segunda Linha.

Observe o espao extra entre as duas linhas. E se quisssemos mais espao entre as linhas? Poderamos chamar a mesma funo repetidamente:
print 'Primeira Linha.' novaLinha() novaLinha() novaLinha() print 'Segunda Linha.'

Ou poderamos escrever uma nova funo chamada tresLinhas, que produzisse trs novas linhas:
def tresLinhas() : novaLinha() novaLinha() novaLinha() print 'Primeira Linha.' tresLinhas() print 'Segunda Linha.'

Esta funo contm trs comandos, todos com recuo de dois espaos a partir da margem esquerda. J que o prximo comando no est endentado, Python reconhece que ele no faz parte da funo. Algumas coisas que devem ser observadas sobre este programa: 1. Voc pode chamar o mesmo procedimento repetidamente. Isso muito comum, alm de til. 2. Voc pode ter uma funo chamando outra funo; neste caso tresLinhas chama novaLinha. Pode no estar claro, at agora, de que vale o esforo de criar novas funes existem vrias razes, mas este exemplo demonstra duas delas: Criar uma nova funo permite que voc coloque nome em um grupo de comandos. As funes podem simplificar um programa ao ocultar uma computao complexa por trs de um simples comando cujo nome pode ser uma palavra em portugus, em vez de algum cdigo misterioso.

Criar uma nova funo pode tornar o programa menor, por eliminar cdigo repetido. Por exemplo, um atalho para 'imprimir' nove novas linhas consecutivas chamar tresLinhas trs vezes. Como exerccio, escreva uma funo chamada noveLinhas que use tresLinhas para imprimir nove linhas em branco. Como voc poderia imprimir vinte e sete novas linhas? 3.7 Definies e uso Reunindo os fragmentos de cdigo da Seo 3.6, o programa completo fica assim:
def novaLinha() : print def tresLinhas() : novaLinha() novaLinha() novaLinha() print 'Primeira Linha.' tresLinhas() print 'Segunda Linha.'

Esse programa contm duas definies de funes: novaLinha e tresLinhas. Definies de funes so executadas como quaisquer outros comandos, mas o efeito criar a nova funo. Os comandos dentro da definio da funo no so executados at que a funo seja chamada, logo, a definio da funo no gera nenhuma sada. Como voc j deve ter imaginado, preciso criar uma funo antes de poder execut-la. Em outras palavras, a definio da funo tem que ser executada antes que ela seja chamada pela primeira vez. Como exerccio, mova as ltimas trs linhas deste programa para o topo, de modo que a chamada da funo aparea antes das definies. Rode o programa e veja que mensagem de erro voc ter. Tambm a ttulo de exerccio, comece com a verso que funciona do programa e mova a definio de novaLinha para depois da definio de tresLinhas. O que acontece quando voc roda este programa? 3.8 Fluxo de execuo Para assegurar que uma funo esteja definida antes do seu primeiro uso, preciso saber em que ordem os comandos so executados, o que chamado de fluxo de execuo. A execuo sempre comea com o primeiro comando do programa. Os comandos so executados um de cada vez, pela ordem, de cima para baixo.

As definies de funo no alteram o fluxo de execuo do programa, mas lembre-se que comandos dentro da funo no so executados at a funo ser chamada. Embora no seja comum, voc pode definir uma funo dentro de outra. Neste caso, a definio mais interna no executada at que a funo mais externa seja chamada. Chamadas de funo so como um desvio no fluxo de execuo. Em vez de ir para o prximo comando, o fluxo salta para a primeira linha da funo chamada, executa todos os comandos l e ento volta atrs para retomar de onde havia deixado. Parece muito simples, at a hora em que voc lembra que uma funo pode chamar outra. Enquanto estiver no meio de uma funo, o programa poderia ter de executar os comandos em uma outra funo. Mas enquanto estivesse executando esta nova funo, o programa poderia ter de executar ainda outra funo! Felizmente, Python adepto de monitorar a posio onde est, assim, cada vez que uma funo se completa, o programa retoma de onde tinha parado na funo que a chamou. Quando chega ao fim do programa, ele termina. Qual a moral dessa histria srdida? Quando voc ler um programa, no o leia de cima para baixo. Em vez disso, siga o fluxo de execuo. 3.9 Parmetros e argumentos Algumas das funes nativas que voc j usou requerem argumentos, aqueles valores que controlam como a funo faz seu trabalho. Por exemplo, se voc quer achar o seno de um nmero, voc tem que indicar qual nmero . Deste modo, sin recebe um valor numrico como um argumento. Algumas funes recebem mais de um argumento. Por exemplo, pow recebe dois argumentos, a base e o expoente. Dentro da funo, os valores que lhe so passados so atribudos a variveis chamadas parmetros. Veja um exemplo de uma funo definida pelo usurio, que recebe um parmetro:
def imprimeDobrado(bruno): print bruno, bruno

Esta funo recebe um nico argumento e o atribui a um parmetro chamado bruno. O valor do parmetro (a essa altura, no sabemos qual ser) impresso duas vezes, seguido de uma nova linha. Estamos usando bruno para mostrar que o nome do parmetro deciso sua, mas claro que melhor escolher um nome que seja mais ilustrativo. A funo imprimeDobrado funciona para qualquer tipo que possa ser impresso:

>>> imprimeDoobrado('Spam') Spam Spam >>> imprimeDobrado(5) 55 >>> imprimeDobrado(3.14159) 3.14159 3.14159

Na primeira chamada da funo, o argumento uma string. Na segunda, um inteiro. Na terceira um float. As mesmas regras de composio que se aplicam a funes nativas tambm se aplicam s funes definidas pelo usurio, assim, podemos usar qualquer tipo de expresso como um argumento para imprimeDobrado:
>>> imprimeDobrado('Spam'*4) SpamSpamSpamSpam SpamSpamSpamSpam >>> imprimeDobrado(math.cos(math.pi)) -1.0 -1.0

Como acontece normalmente, a expresso avaliada antes da execuo da funo, assim imprimeDobrado imprime SpamSpamSpamSpam SpamSpamSpamSpam em vez de 'Spam'*4 'Spam'*4. Como exerccio, escreva um chamada a imprimeDobrado que imprima 'Spam'*4 'Spam'*4. Dica: strings podem ser colocadas tanto entre aspas simples quanto duplas e o tipo de aspas que no for usado para envolver a string pode ser usado dentro da string, como parte dela. Tambm podemos usar uma varivel como argumento:
>>> miguel = 'Eric, the half a bee.' >>> imprimeDobrado(miguel) Eric, the half a bee. Eric, the half a bee.

N.T.: "Eric, the half a bee" uma msica do grupo humorstico britnico Monty Python. A linguagem Python foi batizada em homenagem ao grupo e, por isso, os programadores gostam de citar piadas deles em seus exemplos. Repare numa coisa importante: o nome da varivel que passamos como um argumento (miguel) no tem nada a ver com o nome do parmetro (bruno). No importa de que modo o valor foi chamado de onde veio (do 'chamador'); aqui, em imprimeDobrado, chamamos a todo mundo de bruno. 3.10 Variveis e parmetros so locais Quando voc cria uma varivel local dentro de uma funo, ela s existe dentro da funo e voc no pode us-la fora de l. Por exemplo:
def concatDupla(parte1, parte2) concat = parte1 + parte2 imprimeDobrado(concat)

Esta funo recebe dois argumentos, concatena-os, e ento imprime o resultado duas vezes. Podemos chamar a funo com duas strings:
>>> canto1 = 'Pie Jesu domine, ' >>> canto2 = 'dona eis requiem. ' >>> concatDupla(canto1, canto2) Pie Jesu domine, Dona eis requiem. Pie Jesu domine, Dona eis requiem.

Quando a funo concatDupla termina, a varivel concat destruda. Se tentarmos imprimi-la, teremos um erro:
>>> print concat NameError: concat

Parmetros so sempre locais. Por exemplo, fora da funo imprimeDobrado, no existe alguma coisa chamada bruno. Se voc tentar utiliz-la, Python vai reclamar. 3.11 Diagramas da pilha Para entender que variveis podem ser usadas aonde, s vezes til desenhar um diagrama da pilha. Como os diagramas de estado, diagramas da pilha mostram o valor de cada varivel, mas tambm a funo qual cada varivel pertence. Cada funo representada por um frame (quadro). Um frame uma caixa com o nome de uma funo ao lado dela e os parmetros e variveis da funo dentro dela. O diagrama de pilha para o exemplo anterior tem a seguinte aparncia: figura A ordem da pilha mostra o fluxo de execuo. imprimeDobrado foi chamado por concatDupla, e concatDupla foi chamado por __main__ (principal), que um nome especial para a funo mais no topo. Quando voc cria uma varivel fora de qualquer funo, ela pertence __main__. Cada parmetro se refere ao mesmo valor que o seu argumento correspondente. Assim, parte1 tem o mesmo valor de canto1, parte2 tem o mesmo valor de canto2 e bruno tem o mesmo valor de concat. Se um erro acontece durante uma chamada de funo, Python imprime o nome da funo, e o nome da funo que a chamou, e o nome da funo que chamou a que chamou, percorrendo todo o caminho de volta a __main__. Por exemplo, se tentssemos acessar concat de dentro de imprimeDobrado, teramos um NameError:
Traceback (innermost last): File "teste.py", line 13, in __main__

concatDupla(canto1, canto2) File "teste.py", line 5, in concatDupla imprimeDobrado(concat) File "teste.py", line 9, in imprimeDobrado print concat NameError: concat

Esta lista de funes chamada de traceback. Ela mostra em qual arquivo de programa o erro ocorreu, em que linha, e quais funes estavam sendo executadas naquele momento. Mostra tambm a linha de cdigo que causou o erro. Note a similaridade entre o traceback e o diagrama da pilha; no coincidncia. 3.12 Funes com resultados A essa altura, voc deve ter percebido que algumas das funes que estamos usando, tais como as funes matemticas, produzem resultados. Outras funes, como novaLinha, executam uma ao, mas no retornam um valor. O que levanta algumas questes: 1. O que acontece se voc chama uma funo e no faz nada com o resultado (por exemplo, no atribui o resultado a uma varivel ou o usa como parte de uma expresso maior)? 2. O que acontece se voc usa uma funo que no produz resultado em uma expresso tal como novaLinha() + 7? 3. Voc pode escrever funes que produzem resultados, ou est preso a funes como novaLinha e imprimeDobrado? A resposta para a terceira questo afirmativa e ns vamos fazer isso no Captulo 5. A ttulo de exerccio, responda as outras duas questes testando-as. Se tiver dvida sobre o que vlido ou invlido em Python, tente buscar a resposta perguntando ao interpretador. 3.13 Glossrio chamada de funo (function call) Comando que executa uma funo. Consiste do nome da funo seguido de uma lista de argumentos entre parnteses. argumento (argument) Valor fornecido a uma funo quando ela chamada. Este valor atribudo ao parmetro correspondente na funo. valor de retorno (return value) O resultado da funo. Se uma chamada de funo usada como expresso, o valor de retorno o valor da expresso. converso de tipo (type conversion) Comando explcito que pega um valor de um tipo e devolve o valor correspondente em outro tipo.

coercividade de tipo (type coercion) Uma converso de tipo que ocorre automaticamente, de acordo com as regras de coercividade do Python. mdulo (module) Arquivo que contm uma coleo de funes e classes relacionadas entre si. notao de ponto (dot notation) A sintaxe para chamar uma funo que est em outro mdulo, especificando o nome do mdulo, seguido por um ponto (.) e o nome da funo. funo (function) Seqncia de comandos nomeada, que realiza alguma tarefa til. As funes podem ou no receber parmetros e podem ou no retornar valores. definio de funo (function definition) Comando que cria uma nova funo, especificando seu nome, parmetros e comandos que ela executa. fluxo de execuo (flow of execution) A ordem na qual os comandos so executados durante a execuo do programa. parmetro (parameter) Nome usado numa funo para referir-se ao valor passado como argumento. varivel local (local variable) Varivel definida dentro da funo. Uma varivel local s pode ser usada dentro da funo onde foi definida. diagrama da pilha (stack diagram) Representao grfica da pilha de funes, suas variveis e os valores aos quais elas se referem. frame Retngulo no diagrama da pilha que representa uma chamada de funo. Contm as variveis locais e os parmetros da funo. traceback Lista de funes que esto em execuo, impressa quando um erro de execuo ocorre.

Captulo 3: Funes
System Message: INFO/1 (<string>, line 2140); backlink Duplicate implicit target name: "captulo 3: funes". Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas

2.4 Comandos 2.5 Avaliando expresses 2.6 Operadores e operandos 2.7 Ordem dos operadores 2.8 Operaes com strings 2.9 Composio 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos o 3.4 Funes matemticas o 3.5 Composio o 3.6 Adicionando novas funes o 3.7 Definies e uso o 3.8 Fluxo de execuo o 3.9 Parmetros e argumentos o 3.10 Variveis e parmetros so locais o 3.11 Diagramas da pilha o 3.12 Funes com resultados o 3.13 Glossrio Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas
o o o o o o o

4.3 Operadores lgicos 4.4 Execuo condicional 4.5 Execuo alternativa 4.6 Condicionais encadeados 4.7 Condicionais aninhados 4.8 A instruo return 4.9 Recursividade 4.10 Diagramas de pilha para funes recursivas 4.11 Recursividade infinita 4.12 Entrada pelo teclado 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos
o o o o o o o o o o o

Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores

3.1 Chamadas de funes

Voc j viu um exemplo de uma chamada de funo:


>>> type(?32?) <type ?string?>

O nome da funo type, e ela exibe o tipo de valor de uma varivel. O valor ou varivel, o qual chamado de argumento da funo, tem que vir entre parntesis. comum se dizer que uma funo ?recebe? um valor e ?retorna? um resultado. O resultado chamado de valor de retorno. Em vez de imprimir um valor de retorno, podemos atribu-lo a uma varivel:
>>> beth = type(?32?) >>> print beth <type ?string?>

Como outro exemplo, a funo id recebe um valor ou uma varivel e retorna um inteiro que atua como um identificador nico para aquele valor:
>>> id(3) 134882108 >>> beth = 3 >>> id(beth) 134882108

Todo valor tem um id, que um nmero nico relacionado ao local onde ele est guardado na memria do computador. O id de uma varivel o id de um valor a qual ela se refere.

3.2 Converso entre tipos

Python prov uma coleo de funes nativas que convertem valores de um tipo em outro. A funo int recebe um valor e o converte para inteiro, se possvel, ou, se no, reclama:
>>> int(?32?) 32 >>> int(?Al?) ValueError: invalid literal for int() : Al

int tambm pode converter valores em ponto flutuante para inteiro, mas lembre-se que isso trunca a parte fracionria:
>>> int(3.99999) 3 >>> int(-2.3) -2

A funo float converte inteiros e strings em nmeros em ponto flutuante:


>>> float(32) 32.0 >>> float(?3.14159?) 3.14159

Finalmente, a funo str converte para o tipo string:


>>> str(32) ?32? >>> str(3.14149) ?3.14149?

Pode parecer curioso que Python distingua o valor inteiro 1 do valor em ponto flutuante 1.0. Eles podem representar o mesmo nmero, mas pertencem a tipos diferentes. A razo que eles so representados de modo diferente dentro do computador.

3.3 Coero entre tipos

Agora que podemos converter entre tipos, temos outra maneira de lidar com a diviso inteira. Voltando ao exemplo do captulo anterior, suponha que queiramos calcular a frao de hora que j passou. A expresso mais bvia, minuto / 60, faz aritmtica inteira, assim o resultado sempre 0, mesmo aos 59 minutos passados da hora. Uma soluo converter minuto para ponto flutuante e fazer a diviso em ponto flutuante:
>>> minuto = 59 >>> float(minuto) / 60 0.983333333333

Alternativamente, podemos tirar vantagem das regras de converso automtica entre tipos, a qual e chamada que coero de tipos. Para os operadores matemticos, se qualquer operando for um float, ou outros so automaticamente convertidos para float:
>>> minuto = 59 >>> minuto / 60.0 0.983333333333

Fazendo o denominador um float, foramos o Python a fazer a diviso em ponto flutuante.

3.4 Funes matemticas

Em matemtica, voc provavelmente j viu funes como seno (sin) e log, e voc aprendeu a resolver expresses como sin(pi/2) e log(1/x). Primeiro voc resolve e expresso entre parnteses (o argumento). Por exemplo, pi/2 aproximadamente 1,571, e 1/x 0.1 (se x for 10,0). A voc avalia a funo propriamente dita, seja procurando numa tabela ou realizando vrios clculos. O sin de 1,571 1 e o log de 0,1 -1 (assumindo que log indica o logaritmo na base 10). Este processo pode ser aplicado repetidamente para avaliar expresses mais

complicadas, como log(1/sin(pi/2)). Primeiro voc avalia o argumento na funo mais interna, depois voc avalia a funo e assim por diante. Python tem um mdulo matemtico que prov a maioria das funes matemticas mais familiares. Um mdulo um arquivo que contm uma coleo de funes relacionadas agrupadas juntas. Antes de podermos usar as funes contidas em um mdulo, temos de import-lo:
>>> import math

Para chamar uma das funes, temos que especificar o nome do mdulo e o nome da funo, separados por um ponto. Este formato chamado de notao de ponto:
>>> decibel = math.log10(17.0) >>> angulo = 1.5 >>> altura = math.sin(angulo)

A primeira instruo atribui a decibel o logaritmo de 17 na base 10. Existe tambm uma funo chamada log que pega o logaritmo na base e. A terceira instruo encontra o seno do valor da varivel angulo. sin e as outras funes trigonomtricas (cs, tan, etc.) recebem argumentos em radianos. Para converter de graus em radianos, divida por 360 e multiplique por 2*pi. Por exemplo, para encontrar o seno de 45 graus, primeiro calcule o ngulo em radianos e depois ache o seno:
>>> graus = 45 >>> angulo = graus * 2 * math.pi / 360.0 >>> math.sin(angulo) 0.707106781187

A constante pi tambm e parte do mdulo math. Se voc sabe geometria, voc pode checar o resultado anterior comparando-o com a raiz quadrada de dois dividido por dois:
>>> math.sqrt(2) / 2.0 0.707106781187

3.5 Composio

Do mesmo modo como nas funes matemticas, as funes do Python podem ser compostas, significando que voc pode usar uma expresso como parte de outra. Por exemplo, voc pode usar qualquer expresso como um argumento para uma funo:
>>> x = math.cos(angulo + pi/2)

Esta instruo toma o valor de pi, o divide por 2, e soma o resultado ao valor de angulo. A soma ento passada como um argumento para a funo cos. Voc tambm pode pegar o resultado de uma funo e pass-lo como um argumento para outra:
>>> x = math.exp(math.log(10.0))

Esta instruo encontra o logaritmo base e de 10 e ento eleva e quela potncia. O resultado atribudo a x.

3.6 Adicionando novas funes

At aqui, temos utilizado somente as funes que vm com Python, mas tambm possvel adicionar novas funes. Criar novas funes para resolver seus prprios problemas uma das coisas mais teis de uma linguagem de programao de propsito geral. No contexto de programao, uma funo uma seqncia nomeada de instrues ou comandos que realizam uma operao desejada. Esta operao especificada numa definio de funo. As funes que temos usado at agora foram definidas para ns, e estas definies tm estado escondidas. Isto uma coisa boa, porque nos permite usar as funes sem que nos preocupemos com os detalhes de suas definies. A sintaxe para uma definio de funo :
def NOME( LISTA DE PARAMETROS ) : COMANDOS

Voc pode usar qualquer nome que queira para as funes que voc criar, exceto que voc no pode usar um nome que uma palavra reservada em Python. A lista de parmetros especifica que informao, se houver alguma, voc tem que fornecer para poder usar a nova funo. Pode existir qualquer nmero de comandos dentro de uma funo, mas eles tm que ser indentados a partir da margem esquerda. Nos exemplos deste

livro, usaremos uma indentao de dois espaos. As primeiras funes que escreveremos no tero parmetros, assim a sintaxe se parecer com esta:
def novaLinha(): print

Esta funo chamada de novaLinha. Os parnteses vazios indicam que ela no tem parmetros. Ela contm apenas um nico comando, o qual gera como sada um caractere de nova linha. (Isto o que acontece quando voc usa um comando print sem qualquer argumento.). A sintaxe para a chamada desta nova funo a mesma sintaxe para as funes nativas:
print ?Primeira Linha.? novaLinha() print ?Segunda Linha.?

A sada deste programa :


Primeira Linha.

Segunda Linha.

Repare o espao extra entre as duas linhas. E se quisssemos mais espao entre as linhas? Poderamos chamar a mesma funo repetidamente:
print ?Primeira Linha.? novaLinha() novaLinha() novaLinha() print ?Segunda Linha.?

Ou poderamos escrever uma nova funo chamada tresLinhas que produzisse trs novas linhas:
def tresLinhas() : novaLinha() novaLinha() novaLinha()

print ?Primeira Linha.? tresLinhas() print ?Segunda Linha.?

Esta funo contm trs comandos, todos eles endentados em dois espaos. J que o prximo comando no est endentado, Python reconhece que ele no faz parte da funo. Voc deve tomar nota de algumas coisas sobre este programa: 1. Voc pode chamar o mesmo procedimento repetidamente. De fato, muito comum e til faz-lo. 2. Voc pode ter uma funo chamando outra funo; neste caso tresLinhas chama novaLinha. At agora, pode no estar claro de que valeria o esforo de se criar todas estas novas funes. Na verdade existem vrias razes, mas este exemplo demonstra duas delas: Criar uma nova funo d a voc a oportunidade de colocar um nome em um grupo de comandos. As funes podem simplificar um programa ao ocultar uma computao complexa por trs de um simples comando e pelo uso do Portugus em vez de algum cdigo misterioso. Criar uma nova funo pode fazer um programa menor ao eliminar cdigo repetido. Por exemplo, um atalho para de maneira curta ?imprimir? nove novas linhas consecutivas chamar tresLinhas trs vezes. Como exerccio, escreva uma funo chamada noveLinhas que use tresLinhas para imprimir nove linhas em branco. Como voc poderia imprimir vinte e sete novas linhas?

3.7 Definies e uso

Colocando juntos os fragmentos de cdigo da Seo 3.6, o programa completo se parece com isto:
def novaLinha() : print

def tresLinhas() :

novaLinha() novaLinha() novaLinha()

print ?Primeira Linha.? tresLinhas() print ?Segunda Linha.?

Este programa contm duas definies de funes: novaLinha e tresLinhas. Definies de funes so executadas como quaisquer outros comandos, mas o efeito criar a nova funo. Os comando dentro da definio da funo no so executados at que a funo seja chamada, logo a definio da funo no gera nenhuma sada. Como voc poderia esperar, voc tem que criar uma funo antes de poder execut-la. Em outras palavras, a definio da funo tem que ser executada antes que ela seja chamada pela primeira vez. Como exerccio, mova as ltimas trs linhas deste programa para o topo, de modo que a chamada da funo aparea antes das definies. Rode o programa e veja que mensagem de erro voc ter. Como outro exerccio, comece com a verso que funciona do programa e mova a definio de novaLinha para depois da definio de tresLinhas. O que acontece quando voc roda este programa?

3.8 Fluxo de execuo

Para se assegurar que uma funo est definida antes de seu primeiro uso, voc tem que saber a ordem em que os comandos so executados, o que chamado de fluxo de execuo. A execuo sempre comea com o primeiro comando do programa. Os comandos so executados um de cada vez, pela ordem, de cima para baixo. As definies de funo no alteram o fluxo de execuo do programa, mas lembre-se que comandos dentro da funo no so executados at a funo ser chamada. Embora no seja comum, voc pode definir uma funo dentro de outra. Neste caso, a definio mais interna no executada at que a funo mais externa seja chamada.

Chamadas de funo so como um desvio no fluxo de execuo. Em vez de ir para o prximo comando, o fluxo salta para a primeira linha da funo chamada, executa todos os comandos l e ento volta atrs para retomar de onde havia deixado. Isto soa bastante simples, at que voc se lembra que uma funo pode chamar outra. Enquanto estiver no meio de uma funo, o programa poderia ter de executar os comandos em uma outra funo. Mas enquanto estivesse executando esta nova funo, o programa poderia ter de executar ainda outra funo! Felizmente, Python adepto de monitorar a posio onde est, assim, cada vez que uma funo se completa, o programa retoma de onde tinha parado na funo que a chamou. Quando chega ao fim do programa, ele termina. Qual a moral desta histria srdida? Quando voc ler um programa, no o leia de cima para baixo. Em vez disso, siga o fluxo de execuo.

3.9 Parmetros e argumentos

Algumas das funes nativas que voc j usou requerem argumentos, aqueles valores que controlam como a funo faz seu trabalho. Por exemplo, se voc quer achar o seno de um nmero, voc tem que indicar qual nmero . Deste modo, sin recebe um valor numrico como um argumento. Algumas funes recebem mais de um argumento. Por exemplo, pow recebe dois argumentos, a base e o expoente. Dentro da funo, os valores que lhe so passados so atribudos a variveis chamadas parmetros. Aqui est um exemplo de uma funo definida pelo usurio que recebe um parmetro:
def imprimeDobrado(bruno): print bruno, bruno

Esta funo recebe um nico argumento e o atribui a um parmetro chamado bruno. O valor do parmetro (neste ponto ns no temos qualquer idia de qual ser) impresso duas vezes, seguido de uma nova linha. O nome bruno foi escolhido para sugerir aqui que o nome que voc d a um parmetro problema seu, mas em geral, voc deve escolher algo mais ilustrativo do que Bruno. A funo imprimeDobrado funciona para qualquer tipo que possa ser impresso:

>>> imprimeDoobrado(?Spam?) Spam Spam >>> imprimeDobrado(5) 55 >>> imprimeDobrado(3.14159) 3.14159 3.14159

Na primeira chamada da funo, o argumento uma string. Na segunda, um inteiro. Na terceira um float. As mesmas regras de composio que se aplicam funes nativas tambm se aplicam s funes definidas pelo usurio, assim podemos usar qualquer tipo de expresso como um argumento para imprimeDobrado:
>>> imprimeDobrado(?Span?*4) SpamSpamSpamSpam SpamSpamSpamSpam >>> imprimeDobrado(math.cos(math.pi)) -1.0 -1.0

Como acontece normalmente, a expresso e avaliada antes da execuo da funo, assim imprimeDobrado imprime SpamSpamSpamSpam SpamSpamSpamSpam em vez de ?Spam?*4 ?Spam?*4. Como exerccio, escreva um chamada a imprimeDobrado que imprima ?Spam?*4 ?Spam?*4. Dica: strings podem ser colocadas tanto entre aspas simples quanto duplas, e o tipo de aspas que no for usado para envolver a string pode ser usado dentro da string como parte dela. Ns tambm podemos usar uma varivel como argumento:
>>> miguel = ?Erico, a metade de uma abelha.? >>> imprimeDobrado(miguel) Erico, a metade de uma abelha. Erico, a metade de uma abelha.

Repare numa coisa muito importante aqui. O nome da varivel que passamos como um argumento (miguel) no tem nada a ver com o nome do parmetro (bruno). No importa de que modo o valor foi chamado de onde veio (do ?chamador?); aqui, em imprimeDobrado, chamamos a todo mundo de bruno.

3.10 Variveis e parmetros so locais

Quando voc cria uma varivel local dentro de uma funo, ela s existe dentro da funo e voc no pode us-la fora de l. Por exemplo:
def concatDupla(parte1, parte2) concat = parte1 + parte2 imprimeDobrado(concat)

Esta funo recebe dois argumentos, concatena-os, e ento imprime o resultado duas vezes. Podemos chamar a funo com duas strings:
>>> canto1 = ?Pie Jesu domine, ? >>> canto2 = ?dona eis requiem. ? >>> concatDupla(canto1, canto2) Pie Jesu domine, Dona eis requiem. Pie Jesu domine, Dona eis requiem.

Quando a funo concatDupla termina, a varivel concat destruda. Se tentarmos imprim-la, teremos um erro:
>>> print concat NameError: concat

Parmetros so sempre locais. Por exemplo, fora da funo imprimeDobrado, no existe alguma coisa chamada bruno. Se voc tentar utiliz-la, Python vai reclamar.

3.11 Diagramas da pilha

Para manter a pista de que variveis podem ser usadas aonde, s vezes til desenhar um diagrama da pilha. Como os diagramas de estado, diagramas da pilha mostram o valor de cada varivel, mas eles tambm mostram a funo a qual cada varivel pertence. Cada funo representada por um frame (quadro). Um frame uma caixa com o nome de uma funo ao lado dela e os parmetros e variveis da funo dentro dela. O diagrama de pilha para o exemplo anterior tem a seguinte aparncia: figura A ordem da pilha mostra o fluxo de execuo. imprimeDobrado foi chamado por concatDupla, e concatDupla foi chamado por __main__ (principal), que

um nome especial para a funo mais no topo. Quando voc cria uma varivel fora de qualquer funo, ela pertence __main__. Cada parmetro se refere ao mesmo valor como seu argumento correspondente. Assim, parte1 tem o mesmo valor de canto1, parte2 tem o mesmo valor de canto2 e bruno tem o mesmo valor de concat. Se um erro acontece durante uma chamada de funo, Python imprime o nome da funo, e o nome da funo que a chamou e o nome da funo que chamou a que chamou, por todos os caminhos voltando a __main__. Por exemplo, se tentssemos acessar concat de dentro de imprimeDobrado, teramos um NameError:
Traceback (innermost last): File "teste.py", line 13, in __main__ concatDupla(canto1, canto2) File "teste.py", line 5, in concatDupla imprimeDobrado(concat) File "teste.py", line 9, in imprimeDobrado print concat NameError: concat

Esta lista de funes chamada de um traceback. Ela mostra para voc em qual arquivo de programa o erro ocorreu, em que linha, e quais funes estavam sendo executadas naquele momento. Ela tambm mostra a linha de cdigo que causou o erro. Note a similaridade entre o traceback e o diagrama da pilha. Isto no uma coincidncia.

3.12 Funes com resultados

Voc pode ter notado por ora que algumas das funes que usamos, tais quais as funes matemticas, produzem resultados. Outras funes, como novaLinha, executam uma ao, mas no retornam um valor. O que levanta algumas questes: 1. O que acontece se voc chama uma funo e no faz nada com o resultado (por exemplo, no atribui o resultado a uma varivel ou o usa como parte de uma expresso maior)?

2. O que acontece se voc usa uma funo que no produz resultado em uma expresso tal como novaLinha() + 7? 3. Voc pode escrever funes que produzem resultados, ou est preso a funes como novaLinha e imprimeDobrado? A resposta para a terceira questo sim e faremos isso no Captulo 5. Como exerccio, responda as outras duas questes experimentando-as. Quando voc tiver uma dvida sobre o que vlido ou invlido em Python, uma boa maneira de encontrar a resposta perguntar ao interpretador.

3.13 Glossrio

chamada de funo (function call) Um comando que executa uma funo. Consiste do nome da funo seguido de uma lista de argumentos entre parntesis. argumento (argument) Um valor fornecido a uma funo quando ela chamada. Este valor atribudo ao parmetro correspondente na funo. valor de retorno (return value) O resultado da funo. Se uma chamada de funo usada como expresso, o valor de retorno o valor da expresso. converso de tipo (type conversion) Um comando explcito que pega um valor de um tipo e devolve o valor correspondente em outro tipo. coercividade de tipo (type coercion) Uma converso de tipo que ocorre automaticamente, de acordo com as regras de coercividade do Python. mdulo (module) Um arquivo que contm uma coleo de funces e classes relacionadas entre si. notao de ponto (dot notation) A sintaxe para chamar uma funo que est em outro mdulo, especificando o nome do mdulo seguido por um ponto (.) e o nome da funo.

funo (function) Uma sequncia de comandos nomeada que realiza alguma tarefa til. As funes podem ou no receber parmetros e podem ou no retornar valores. definio de funo (function definition) Um comando que cria uma nova funo, especificando seu nome, parmetros e comandos que ela executa. fluxo de execuo (flow of execution) A ordem na qual os comandos so executados durante a execuo do programa. parmetro (parameter) Um nome usado numa funo para referir-se ao valor passado como argumento. varivel local (local variable) Uma varivel definida dentro da funo. Uma varivel local s pode ser usada dentro da fuo onde foi definida. diagrama da pilha (stack diagram) Uma representao grfica da pilha de funes, suas variveis e os valores aos quais elas se referem. frame Um retngulo no diagrama da pilha que representa uma chamada de funo. Contm as variveis locais e os parmetros da funo. traceback Uma lista de funes que esto em execuo, impressa quando um erro de execuo ocorre. System Message: WARNING/2 (<string>, line 2971) Block quote ends without a blank line; unexpected unindent.

Captulo 4: Condicionais e recurso


Tpicos

Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos o 3.4 Funes matemticas o 3.5 Composio o 3.6 Adicionando novas funes o 3.7 Definies e uso o 3.8 Fluxo de execuo o 3.9 Parmetros e argumentos o 3.10 Variveis e parmetros so locais o 3.11 Diagramas da pilha o 3.12 Funes com resultados o 3.13 Glossrio Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas

4.11 Recursividade infinita 4.12 Entrada pelo teclado 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos
o o o

Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores 4.1 O operador mdulo O operador mdulo trabalha com inteiros (e expresses que tm inteiros como resultado) e produz o resto da diviso do primeiro pelo segundo. Em Python, o operador mdulo um smbolo de porcentagem (%). A sintaxe a mesma que a de outros operadores:
>>> quociente = 7 / 3 >>> print quociente 2 >>> resto = 7 % 3 >>> print resto 1

Ento, 7 dividido por 3 2 e o resto 1. O operador mdulo se revela surpreendentemente til. Por exemplo, voc pode checar se um nmero divisvel por outro -- se x % y d zero, ento x divisvel por y. Voc tambm pode extrair o algarismo ou algarismos mais direita de um nmero. Por exemplo, x % 10 resulta o algarismo mais direita de x (na base 10). Similarmente, x % 100 resulta nos dois dgitos mais direita. 4.2 Expresses booleanas Uma expresso booleana uma expresso que verdadeira (true) ou falsa (false). Em Python, uma expresso que verdadeira tem o valor 1, e uma expresso que falsa tem o valor 0. O operador == compara dois valores e produz uma expresso booleana:
>>> 5 == 5 True

>>> 5 == 6 False

No primeiro comando, os dois operadores so iguais, ento a expresso avalia como True (verdadeiro); no segundo comando, 5 no igual a 6, ento temos False (falso). O operador == um dos operadores de comparao; os outros so:
x != y x>y x<y x >= y x <= y # x diferente de y # x maior que y # x menor que y # x maior ou igual a y # x menor ou igual a y

Embora estes operadores provavelmente sejam familiares a voc, os smbolos em Python so diferentes dos smbolos da matemtica. Um erro comum usar um sinal de igual sozinho (=) em vez de um duplo (==). Lembre-se que = um operador de atribuio e == um operador de comparao. Tambm no existem coisas como =< ou =>. 4.3 Operadores lgicos Existem trs operadores lgicos: and, or, not (e, ou, no). A semntica (significado) destes operadores similar aos seus significados em ingls (ou portugus). Por exemplo, x > 0 and x < 10 verdadeiro somente se x for maior que 0 e menor que 10. n%2 == 0 or n%3 == 0 verdadeiro se qualquer das condies for verdadeira, quer dizer, se o nmero n for divisvel por 2 ou por 3. Finalmente o operador lgico not nega uma expresso booleana, assim not(x > y) verdadeiro se (x > y) for falso, quer dizer, se x for menor ou igual a y. A rigor, os operandos de operadores lgicos deveriam ser expresses booleanas, mas Python no muito rigoroso. Qualquer nmero diferente de zero interpretado como verdadeiro (True):
>>> x = 5 >>> x and 1 1 >>> y = 0 >>> y and 1 0

Em geral, este tipo de coisa no considerado de bom estilo. Se voc precisa comparar um valor com zero, deve faz-lo explicitamente. 4.4 Execuo condicional Para poder escrever programas teis, ns quase sempre precisamos da habilidade de checar condies e mudar o comportamento do programa de

acordo com elas. Comandos condicionais nos do esta habilidade. A forma mais simples a instruo if (se):
if x > 0 print "x positivo"

A expresso booleana depois da instruo if chamada de condio. Se ela verdadeira (true), ento a instruo endentada executada. Se no, nada acontece. Assim como outras instrues compostas, a instruo if constituda de um cabealho e de um bloco de instrues:
CABECALHO: PRIMEIRO COMANDO ... ULTIMO COMANDO

O cabealho comea com uma nova linha e termina com dois pontos (:). Os comandos ou instrues endentados que seguem so chamados de bloco. A primeira instruo no endentada marca o fim do bloco. Um bloco de comandos dentro de um comando composto ou instruo composta chamado de corpo do comando. No existe limite para o nmero de instrues que podem aparecer no corpo de uma instruo if, mas tem que haver pelo menos uma. Ocasionalmente, til ter um corpo sem nenhuma instruo (usualmente como um delimitador de espao para cdigo que voc ainda no escreveu). Neste caso, voc pode usar o comando pass, o qual no faz nada. 4.5 Execuo alternativa Um segundo formato da instruo if a execuo alternativa, na qual existem duas possibilidades e a condio determina qual delas ser executada. A sintaxe se parece com:
if x % 2 == 0: print x, " par" else: print x, " impar"

Se o resto da diviso de x por 2 for 0, ento sabemos que x par, e o programa exibe a mensagem para esta condio. Se a condio falsa, o segundo grupo de instrues executado. Desde que a condio deva ser verdadeira (true) ou falsa (false), precisamente uma das alternativas vai ser executada. As alternativas so chamadas ramos (branches), porque existem ramificaes no fluxo de execuo. Por sinal, se voc precisa checar a paridade de nmeros com freqncia, pode colocar este cdigo dentro de uma funo:
def imprimeParidade(x):

if x % 2 == 0: print x, " par" else: print x, " impar"

Para qualquer valor de x, imprimeParidade exibe uma mensagem apropriada. Quando voc a chama, deve fornecer uma expresso de resultado inteiro como um argumento:
>>> imprimeParidade(17) >>> imprimeParidade(y+1)

4.6 Condicionais encadeados s vezes existe mais de uma possibilidade e precisamos de mais de dois ramos. Podemos expressar uma computao como atravs de uma condicionais encadeados:
if x < y: print x, " menor que", y elif x > y: print x, " maior que", y else: print x, "e", y, "so iguais"

elif uma abreviao de "else if" ("ento se"). De novo, precisamente um ramo ser executado. No existe limite para o nmero de instrues elif, mas se existir uma instruo else ela tem que vir por ltimo:
if escolha == 'A': funcaoA() elif escolha == 'B': funcaoB() elif escolha == 'C': funcaoC() else: print "Escolha invlida."

Cada condio checada na ordem. Se a primeira falsa, a prxima checada, e assim por diante. Se uma delas verdadeira, o ramo correspondente executado, e a instruo termina. Mesmo que mais de uma condio seja verdadeira, apenas o primeiro ramo verdadeiro executa. Como exerccio, coloque os exemplos acima em funes chamadas comparar(x, y) e executar(escolha). 4.7 Condicionais aninhados Um condicional tambm pode ser aninhado dentro de outra. Poderamos ter escrito o exemplo tricotmico (dividido em trs) como segue:
if x == y: print x, "e", y, "so iguais" else:

if x < y: print x, " menor que", y else: print x, " maior que", y

O condicional mais externo tem dois ramos. O primeiro ramo contm uma nica instruo de sada. O segundo ramo contm outra instruo if, que por sua vez tem dois ramos. Os dois ramos so ambos instrues de sada, embora pudessem conter instrues condicionais tambm. Embora a endentao das instrues torne a estrutura aparente, condicionais aninhados tornam-se difceis de ler rapidamente. Em geral, uma boa idia evitar o aninhamento quando for possvel. Operadores lgicos muitas vezes fornecem uma maneira de simplificar instrues condicionais aninhadas. Por exemplo, ns podemos reescrever o seguinte cdigo usando uma nica condicional:
if 0 < x: if x < 10: print "x um nmero positivo de um s algarismo."

A instruo print executada somente se a fizermos passar por ambos os condicionais, ento podemos usar um operador and:
if 0 < x and x < 10: print "x um nmero positivo de um s algarismo."

Estes tipos de condio so comuns, assim Phython prov uma sintaxe alternativa que similar notao matemtica:
if 0 < x < 10: print "x um nmero positivo de um s algarismo."

4.8 A instruo return O comando return permite terminar a execuo de uma funo antes que ela alcance seu fim. Uma razo para us-lo se voc detectar uma condio de erro:
import math def imprimeLogaritmo(x): if x <= 0: print "Somente nmeros positivos, por favor." return resultado = math.log(x) print "O log de x ", resultado

A funo imprimeLogaritmo recebe um parmetro de nome x. A primeira coisa que ela faz checar se x menor ou igual a 0, neste caso ela exibe uma mensagem de erro e ento usa return para sair da funo. O fluxo de

execuo imediatamente retorna ao ponto chamador, quer dizer, de onde a funo foi chamada, e as linhas restantes da funo no so executadas. Lembre-se que para usar uma funo do mdulo de matemtica, math, voc tem de import-lo. 4.9 Recursividade J mencionamos que vlido que uma funo chame outra funo, e vimos vrios exemplos disto. O que faltou mencionar que tambm vlido uma funo chamar a ela mesma. Pode no ser bvio o porque disso ser uma boa coisa, mas se revela uma das coisas mais mgicas e interessantes que um programa pode fazer. Por exemplo, d uma olhada na seguinte funo:
def contagemRegressiva(n): if n == 0: print "Fogo!" else: print n contagemRegressiva(n-1)

contagemRegressiva espera que o parmetro, n, seja um inteiro positivo. Se n for 0, ela produz como sada a palavra "Fogo!" (Blastoff!). De outro modo, ela produz como sada n e ento chama uma funo de nome contagemRegressiva -- ela mesma -- passando n-1 como argumento. O que acontece se chamarmos esta funo desta maneira:
>>> contagemRegressiva(3)

A execuo de contagemRegressiva comea com n=3, e desde que n no 0, produz como sada o valor 3, e ento chama a si mesma... A execuo de contagemRegressiva comea com n=2, e desde que n no 0, produz como sada o valor 2, e ento chama a si mesma... A execuo de contagemRegressiva comea com n=1, e desde que n no 0, produz como sada o valor 1, e ento chama a si mesma... A execuo de contagemRegressiva comea com n=0, e desde que n 0, produz como sada a palavra "Fogo!" e ento retorna. A contagemRegressiva que tem n=1 retorna. A contagemRegressiva que tem n=2 retorna. A contagemRegressiva que tem n=1 retorna. E ento estamos de volta em __main__ (que viagem!). Assim, a sada completa se parece com:

3 2 1 Fogo!

Como um segundo exemplo, d uma olhada novamente nas funes novaLinha e tresLinhas:
def novaLinha(): print def tresLinhas(): novaLinha() novaLinha() novaLinha()

Muito embora isto funcione, no seria de muita ajuda se precisssemos gerar como sada 2 novas linhas, ou 106. Uma alternativa melhor seria esta:
def nLinhas(n): if n > 0: print nLinhas(n-1)

Este programa similar a contagemRegressiva; sempre que n for maior que 0 ele gera como sada uma nova linha e ento chama a si mesmo para gerar como sada n-1 linhas adicionais. Deste modo, o nmero total de novas linhas 1 + (n - 1) o que, se voc estudou lgebra direitinho, vem a ser o prprio n. O processo em que uma funo chama a ela mesma chamado de recursividade, e tais funes so ditas recursivas. 4.10 Diagramas de pilha para funes recursivas Na Seo 3.11, usamos um diagrama de pilha para representar o estado de um programa durante uma chamada de funo. O mesmo tipo de diagrama pode ajudar a interpretar uma funo recursiva. Toda vez que uma funo chamada, Python cria um novo quadro (frame) para a funo, o qual contm as variveis locais e parmetros da funo. Para uma funo recursiva, ter que existir mais de um quadro na pilha ao mesmo tempo. Esta figura mostra um diagrama de pilha para contagemRegressiva, chamada com n = 3: figura Como de costume, no topo da pilha est o quadro para __main__. Ele est vazio porque nem criamos qualquer varivel em __main__ nem passamos qualquer valor para ele.

Os quatro quadros contagemRegressiva tm valores diferentes para o parmetro n. A parte mais em baixo na pilha, onde n=0, chamada de caso base. Ele no faz uma chamada recursiva, ento no h mais quadros. Como exerccio, desenhe um diagrama de pilha para nLinhas chamada com n=4. 4.11 Recursividade infinita Se uma recursividade nunca chega ao caso base, ela prossegue fazendo chamadas recursivas para sempre, e o programa nunca termina. Isto conhecido como recursividade infinita, e geralmente no considerada uma boa idia. Aqui est um programa mnimo com uma recursividade infinita:
def recursiva(): recursiva()

Na maioria dos ambientes de programao, um programa com recursividade infinita na verdade no roda para sempre. Python reporta uma mensagem de erro quando a profundidade mxima de recursividade alcanada:
File "<stdin>", line 2, in recursiva (98 repetitions omitted) File "<stdin>", line 2, in recursiva RuntimeError: Maximum recursion depth exceeded

Este traceback um pouco maior do que aquele que vimos no captulo anterior. Quando o erro ocorre, existem 100 quadros recursiva na pilha! Como exerccio, escreva uma funo com recursividade infinita e rode-a no interpretador Python. 4.12 Entrada pelo teclado Os programas que temos escrito at agora so um pouco crus no sentido de no aceitarem dados entrados pelo usurio. Eles simplesmente fazem a mesma coisa todas s vezes. Python fornece funes nativas que pegam entradas pelo teclado. A mais simples chamada raw_input. Quando esta funo chamada, o programa pra e espera que o usurio digite alguma coisa. Quando o usurio aperta as teclas Enter ou Return, o programa reassume e raw_input retorna o que o usurio digitou como uma string:
>>> entrada = raw_input() O que voc est esperando? >>> print entrada O que voc est esperando?

Antes de chamar raw_input, uma boa idia exibir uma mensagem dizendo ao usurio o que ele deve entrar. Esta mensagem chamada um prompt.

Podemos suprir um prompt como um argumento para raw_input:


>>> nome = raw_input("Qual... o seu nome? ") Qual... o seu nome? Arthur, Rei dos Bretes! >>> print nome Arthur, Rei dos Bretes!

Se esperamos que a entrada seja um inteiro, podemos usar a funo input:


prompt = "Qual... a velocidade de vo de uma andorinha?\n" velocidade = input(prompt)

Se o usurio digita uma string de nmeros, ela convertida para um inteiro e atribuda a velocidade. Infelizmente, se o usurio digitar um caractere que no seja um nmero, o programa trava:
>>> velocidade = input(prompt) Qual... a velocidade de vo uma andorinha? De qual voc fala, uma andorinha africana ou uma europia? SyntaxError: invalid syntax

Para evitar este tipo de erro, geralmente uma boa idia usar raw_input para pegar uma string e ento usar funes de converso para converter para outros tipos. 4.13 Glossrio operador mdulo (modulus operator) Um operador, denotado com um smbolo de porcentagem (%), que trabalha com inteiros e retorna o resto da diviso de um nmero por outro. expresso booleana (boolean expression) Uma expresso que verdadeira ou falsa. operador de comparao (comparison operator) Um dos operadores que comparam dois valores: ==, !=, >, <, >=, e <=. operador lgico (logical operator) Um dos operadores que combinam expresses booleanas: and, or, e not. comando condicional (conditional statement) Um comando que controla o fluxo de execuo dependendo de alguma condio. condio (condition) A expresso booleana que determina qual bloco ser executado num comando condicional. comando composto (compound statement) Um comando que consiste de um cabealho e um corpo. O cabealho termina com um dois-pontos (:). O corpo endentado com relao ao cabealho. bloco (block) Um grupo de comandos consecutivos com a mesma endentao. corpo (body)

O bloco que se segue ao cabealho em um comando composto. aninhamento (nesting) Uma estrutura de programa dentro da outra, como um comando condicional dentro de um bloco de outro comando condicional. recursividade (recursion) O processo de chamar a prpria funo que est sendo executada. caso base (base case) Um bloco do comando condicional numa funo recursiva que no resulta em uma chamada recursiva. recurso infinita (infinite recursion) Uma funo que chama a si mesma recursivamente sem nunca chegar ao caso base. Aps algum tempo, uma recurso infinita causa um erro de execuo. deixa (prompt) Uma indicao visual que diz ao usurio para entrar com os dados.

Captulo 4: Condicionais e recurso


System Message: INFO/1 (<string>, line 3356); backlink Duplicate implicit target name: "captulo 4: condicionais e recurso". Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes

3.2 Converso entre tipos 3.3 Coero entre tipos 3.4 Funes matemticas 3.5 Composio 3.6 Adicionando novas funes 3.7 Definies e uso 3.8 Fluxo de execuo 3.9 Parmetros e argumentos 3.10 Variveis e parmetros so locais 3.11 Diagramas da pilha 3.12 Funes com resultados 3.13 Glossrio Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos
o o o o o o o o o o o o

o 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores

4.1 O operador mdulo System Message: INFO/1 (<string>, line 3362); backlink Duplicate implicit target name: "4.1 o operador mdulo". O operador mdulo trabalha com inteiros (e expresses que tm inteiros como resultado) e produz o resto da diviso do primeiro pelo segundo. Em Python, o operador mdulo um smbolo de porcentagem (%). A sintaxe a

mesma que a de outros operadores:


>>> quociente = 7 / 3 >>> print quociente 2 >>> resto = 7 % 3 >>> print resto 1

Ento, 7 dividido por 3 2 e o resto 1. O operador mdulo se revela surpreendentemente til. Por exemplo, voc pode checar se um nmero divisvel por outro -- se x % y d zero, ento x divisvel por y. Voc tambm pode extrair o algarismo ou algarismos mais direita de um nmero. Por exemplo, x % 10 resulta o algarismo mais direita de x (na base 10). Similarmente, x % 100 resulta nos dois dgitos mais direita. 4.2 Expresses booleanas System Message: INFO/1 (<string>, line 3381); backlink Duplicate implicit target name: "4.2 expresses booleanas". Uma expresso booleana uma expresso que verdadeira (true) ou falsa (false). Em Python, uma expresso que verdadeira tem o valor 1, e uma expresso que falsa tem o valor 0. O operador == compara dois valores e produz uma expresso booleana:
>>> 5 == 5 True >>> 5 == 6 False

No primeiro comando, os dois operadores so iguais, ento a expresso avalia como True (verdadeiro); no segundo comando, 5 no igual a 6, ento temos False (falso). O operador == um dos operadores de comparao; os outros so:
x != y x>y x<y x >= y x <= y # x diferente de y # x maior que y # x menor que y # x maior ou igual a y # x menor ou igual a y

Embora estes operadores provavelmente sejam familiares a voc, os smbolos em Python so diferentes dos smbolos da matemtica. Um erro comum usar um sinal de igual sozinho (=) em vez de um duplo (==). Lembre-se que = um operador de atribuio e == um operador de comparao. Tambm no

existem coisas como =< ou =>. 4.3 Operadores lgicos System Message: INFO/1 (<string>, line 3406); backlink Duplicate implicit target name: "4.3 operadores lgicos". Existem trs operadores lgicos: and, or, not (e, ou, no). A semntica (significado) destes operadores similar aos seus significados em ingls (ou portugus). Por exemplo, x > 0 and x < 10 verdadeiro somente se x for maior que 0 e menor que 10. n%2 == 0 or n%3 == 0 verdadeiro se qualquer das condies for verdadeira, quer dizer, se o nmero n for divisvel por 2 ou por 3. Finalmente o operador lgico not nega uma expresso booleana, assim not(x > y) verdadeiro se (x > y) for falso, quer dizer, se x for menor ou igual a y. A rigor, os operandos de operadores lgicos deveriam ser expresses booleanas, mas Python no muito rigoroso. Qualquer nmero diferente de zero interpretado como verdadeiro (True):
>>> x = 5 >>> x and 1 1 >>> y = 0 >>> y and 1 0

Em geral, este tipo de coisa no considerado de bom estilo. Se voc precisa comparar um valor com zero, deve faz-lo explicitamente. 4.4 Execuo condicional System Message: INFO/1 (<string>, line 3427); backlink Duplicate implicit target name: "4.4 execuo condicional". Para poder escrever programas teis, ns quase sempre precisamos da habilidade de checar condies e mudar o comportamento do programa de acordo com elas. Comandos condicionais nos do esta habilidade. A forma mais simples a instruo if (se):
if x > 0 print "x positivo"

A expresso booleana depois da instruo if chamada de condio. Se ela verdadeira (true), ento a instruo endentada executada. Se no, nada acontece.

Assim como outras instrues compostas, a instruo if constituda de um cabealho e de um bloco de instrues:
CABECALHO: PRIMEIRO COMANDO ... ULTIMO COMANDO

O cabealho comea com uma nova linha e termina com dois pontos (:). Os comandos ou instrues endentados que seguem so chamados de bloco. A primeira instruo no endentada marca o fim do bloco. Um bloco de comandos dentro de um comando composto ou instruo composta chamado de corpo do comando. No existe limite para o nmero de instrues que podem aparecer no corpo de uma instruo if, mas tem que haver pelo menos uma. Ocasionalmente, til ter um corpo sem nenhuma instruo (usualmente como um delimitador de espao para cdigo que voc ainda no escreveu). Neste caso, voc pode usar o comando pass, o qual no faz nada. 4.5 Execuo alternativa System Message: INFO/1 (<string>, line 3449); backlink Duplicate implicit target name: "4.5 execuo alternativa". Um segundo formato da instruo if a execuo alternativa, na qual existem duas possibilidades e a condio determina qual delas ser executada. A sintaxe se parece com:
if x % 2 == 0: print x, " par" else: print x, " impar"

Se o resto da diviso de x por 2 for 0, ento sabemos que x par, e o programa exibe a mensagem para esta condio. Se a condio falsa, o segundo grupo de instrues executado. Desde que a condio deva ser verdadeira (true) ou falsa (false), precisamente uma das alternativas vai ser executada. As alternativas so chamadas ramos (branches), porque existem ramificaes no fluxo de execuo. Por sinal, se voc precisa checar a paridade de nmeros com freqncia, pode colocar este cdigo dentro de uma funo:
def imprimeParidade(x): if x % 2 == 0: print x, " par" else: print x, " impar"

Para qualquer valor de x, imprimeParidade exibe uma mensagem apropriada.

Quando voc a chama, deve fornecer uma expresso de resultado inteiro como um argumento:
>>> imprimeParidade(17) >>> imprimeParidade(y+1)

4.6 Condicionais encadeados System Message: INFO/1 (<string>, line 3475); backlink Duplicate implicit target name: "4.6 condicionais encadeados". s vezes existe mais de uma possibilidade e precisamos de mais de dois ramos. Podemos expressar uma computao como atravs de uma condicionais encadeados:
if x < y: print x, " menor que", y elif x > y: print x, " maior que", y else: print x, "e", y, "so iguais"

elif uma abreviao de "else if" ("ento se"). De novo, precisamente um ramo ser executado. No existe limite para o nmero de instrues elif, mas se existir uma instruo else ela tem que vir por ltimo:
if escolha == 'A': funcaoA() elif escolha == 'B': funcaoB() elif escolha == 'C': funcaoC() else: print "Escolha invlida."

Cada condio checada na ordem. Se a primeira falsa, a prxima checada, e assim por diante. Se uma delas verdadeira, o ramo correspondente executado, e a instruo termina. Mesmo que mais de uma condio seja verdadeira, apenas o primeiro ramo verdadeiro executa. Como exerccio, coloque os exemplos acima em funes chamadas comparar(x, y) e executar(escolha). 4.7 Condicionais aninhados System Message: INFO/1 (<string>, line 3503); backlink Duplicate implicit target name: "4.7 condicionais aninhados". Um condicional tambm pode ser aninhado dentro de outra. Poderamos ter

escrito o exemplo tricotmico (dividido em trs) como segue:


if x == y: print x, "e", y, "so iguais" else: if x < y: print x, " menor que", y else: print x, " maior que", y

O condicional mais externo tem dois ramos. O primeiro ramo contm uma nica instruo de sada. O segundo ramo contm outra instruo if, que por sua vez tem dois ramos. Os dois ramos so ambos instrues de sada, embora pudessem conter instrues condicionais tambm. Embora a endentao das instrues torne a estrutura aparente, condicionais aninhados tornam-se difceis de ler rapidamente. Em geral, uma boa idia evitar o aninhamento quando for possvel. Operadores lgicos muitas vezes fornecem uma maneira de simplificar instrues condicionais aninhadas. Por exemplo, ns podemos reescrever o seguinte cdigo usando uma nica condicional:
if 0 < x: if x < 10: print "x um nmero positivo de um s algarismo."

A instruo print executada somente se a fizermos passar por ambos os condicionais, ento podemos usar um operador and:
if 0 < x and x < 10: print "x um nmero positivo de um s algarismo."

Estes tipos de condio so comuns, assim Phython prov uma sintaxe alternativa que similar notao matemtica:
if 0 < x < 10: print "x um nmero positivo de um s algarismo."

4.8 A instruo return System Message: INFO/1 (<string>, line 3538); backlink Duplicate implicit target name: "4.8 a instruo return". O comando return permite terminar a execuo de uma funo antes que ela alcance seu fim. Uma razo para us-lo se voc detectar uma condio de erro:
import math def imprimeLogaritmo(x): if x <= 0:

print "Somente nmeros positivos, por favor." return resultado = math.log(x) print "O log de x ", resultado

A funo imprimeLogaritmo recebe um parmetro de nome x. A primeira coisa que ela faz checar se x menor ou igual a 0, neste caso ela exibe uma mensagem de erro e ento usa return para sair da funo. O fluxo de execuo imediatamente retorna ao ponto chamador, quer dizer, de onde a funo foi chamada, e as linhas restantes da funo no so executadas. Lembre-se que para usar uma funo do mdulo de matemtica, math, voc tem de import-lo. 4.9 Recursividade System Message: INFO/1 (<string>, line 3558); backlink Duplicate implicit target name: "4.9 recursividade". J mencionamos que vlido que uma funo chame outra funo, e vimos vrios exemplos disto. O que faltou mencionar que tambm vlido uma funo chamar a ela mesma. Pode no ser bvio o porque disso ser uma boa coisa, mas se revela uma das coisas mais mgicas e interessantes que um programa pode fazer. Por exemplo, d uma olhada na seguinte funo:
def contagemRegressiva(n): if n == 0: print "Fogo!" else: print n contagemRegressiva(n-1)

contagemRegressiva espera que o parmetro, n, seja um inteiro positivo. Se n for 0, ela produz como sada a palavra "Fogo!" (Blastoff!). De outro modo, ela produz como sada n e ento chama uma funo de nome contagemRegressiva -- ela mesma -- passando n-1 como argumento. O que acontece se chamarmos esta funo desta maneira:
>>> contagemRegressiva(3)

A execuo de contagemRegressiva comea com n=3, e desde que n no 0, produz como sada o valor 3, e ento chama a si mesma... A execuo de contagemRegressiva comea com n=2, e desde que n no 0, produz como sada o valor 2, e ento chama a si mesma... A execuo de contagemRegressiva comea com n=1, e desde que n no 0, produz como sada o valor 1, e ento chama a si mesma...

A execuo de contagemRegressiva comea com n=0, e desde que n 0, produz como sada a palavra "Fogo!" e ento retorna. A contagemRegressiva que tem n=1 retorna. A contagemRegressiva que tem n=2 retorna. A contagemRegressiva que tem n=1 retorna. E ento estamos de volta em __main__ (que viagem!). Assim, a sada completa se parece com:
3 2 1 Fogo!

Como um segundo exemplo, d uma olhada novamente nas funes novaLinha e tresLinhas:
def novaLinha(): print def tresLinhas(): novaLinha() novaLinha() novaLinha()

Muito embora isto funcione, no seria de muita ajuda se precisssemos gerar como sada 2 novas linhas, ou 106. Uma alternativa melhor seria esta:
def nLinhas(n): if n > 0: print nLinhas(n-1)

Este programa similar a contagemRegressiva; sempre que n for maior que 0 ele gera como sada uma nova linha e ento chama a si mesmo para gerar como sada n-1 linhas adicionais. Deste modo, o nmero total de novas linhas 1 + (n - 1) o que, se voc estudou lgebra direitinho, vem a ser o prprio n. O processo em que uma funo chama a ela mesma chamado de recursividade, e tais funes so ditas recursivas. 4.10 Diagramas de pilha para funes recursivas System Message: INFO/1 (<string>, line 3619); backlink Duplicate implicit target name: "4.10 diagramas de pilha para funes recursivas". Na Seo 3.11, usamos um diagrama de pilha para representar o estado de

um programa durante uma chamada de funo. O mesmo tipo de diagrama pode ajudar a interpretar uma funo recursiva. Toda vez que uma funo chamada, Python cria um novo quadro (frame) para a funo, o qual contm as variveis locais e parmetros da funo. Para uma funo recursiva, ter que existir mais de um quadro na pilha ao mesmo tempo. Esta figura mostra um diagrama de pilha para contagemRegressiva, chamada com n = 3: figura Como de costume, no topo da pilha est o quadro para __main__. Ele est vazio porque nem criamos qualquer varivel em __main__ nem passamos qualquer valor para ele. Os quatro quadros contagemRegressiva tm valores diferentes para o parmetro n. A parte mais em baixo na pilha, onde n=0, chamada de caso base. Ele no faz uma chamada recursiva, ento no h mais quadros. Como exerccio, desenhe um diagrama de pilha para nLinhas chamada com n=4. 4.11 Recursividade infinita System Message: INFO/1 (<string>, line 3638); backlink Duplicate implicit target name: "4.11 recursividade infinita". Se uma recursividade nunca chega ao caso base, ela prossegue fazendo chamadas recursivas para sempre, e o programa nunca termina. Isto conhecido como recursividade infinita, e geralmente no considerada uma boa idia. Aqui est um programa mnimo com uma recursividade infinita:
def recursiva(): recursiva()

Na maioria dos ambientes de programao, um programa com recursividade infinita na verdade no roda para sempre. Python reporta uma mensagem de erro quando a profundidade mxima de recursividade alcanada:
File "<stdin>", line 2, in recursiva (98 repetitions omitted) File "<stdin>", line 2, in recursiva RuntimeError: Maximum recursion depth exceeded

Este traceback um pouco maior do que aquele que vimos no captulo anterior. Quando o erro ocorre, existem 100 quadros recursiva na pilha! Como exerccio, escreva uma funo com recursividade infinita e rode-a no

interpretador Python. 4.12 Entrada pelo teclado System Message: INFO/1 (<string>, line 3658); backlink Duplicate implicit target name: "4.12 entrada pelo teclado". Os programas que temos escrito at agora so um pouco crus no sentido de no aceitarem dados entrados pelo usurio. Eles simplesmente fazem a mesma coisa todas s vezes. Python fornece funes nativas que pegam entradas pelo teclado. A mais simples chamada raw_input. Quando esta funo chamada, o programa pra e espera que o usurio digite alguma coisa. Quando o usurio aperta as teclas Enter ou Return, o programa reassume e raw_input retorna o que o usurio digitou como uma string:
>>> entrada = raw_input() O que voc est esperando? >>> print entrada O que voc est esperando?

Antes de chamar raw_input, uma boa idia exibir uma mensagem dizendo ao usurio o que ele deve entrar. Esta mensagem chamada um prompt. Podemos suprir um prompt como um argumento para raw_input:
>>> nome = raw_input("Qual... o seu nome? ") Qual... o seu nome? Arthur, Rei dos Bretes! >>> print nome Arthur, Rei dos Bretes!

Se esperamos que a entrada seja um inteiro, podemos usar a funo input:


prompt = "Qual... a velocidade de vo de uma andorinha?\n" velocidade = input(prompt)

Se o usurio digita uma string de nmeros, ela convertida para um inteiro e atribuda a velocidade. Infelizmente, se o usurio digitar um caractere que no seja um nmero, o programa trava:
>>> velocidade = input(prompt) Qual... a velocidade de vo uma andorinha? De qual voc fala, uma andorinha africana ou uma europia? SyntaxError: invalid syntax

Para evitar este tipo de erro, geralmente uma boa idia usar raw_input para pegar uma string e ento usar funes de converso para converter para outros tipos. 4.13 Glossrio

System Message: INFO/1 (<string>, line 3692); backlink Duplicate implicit target name: "4.13 glossrio". operador mdulo (modulus operator) Um operador, denotado com um smbolo de porcentagem (%), que trabalha com inteiros e retorna o resto da diviso de um nmero por outro. expresso booleana (boolean expression) Uma expresso que verdadeira ou falsa. operador de comparao (comparison operator) Um dos operadores que comparam dois valores: ==, !=, >, <, >=, e <=. operador lgico (logical operator) Um dos operadores que combinam expresses booleanas: and, or, e not. comando condicional (conditional statement) Um comando que controla o fluxo de execuo dependendo de alguma condio. condio (condition) A expresso booleana que determina qual bloco ser executado num comando condicional. comando composto (compound statement) Um comando que consiste de um cabealho e um corpo. O cabealho termina com um dois-pontos (:). O corpo endentado com relao ao cabealho. bloco (block) Um grupo de comandos consecutivos com a mesma endentao. corpo (body) O bloco que se segue ao cabealho em um comando composto. aninhamento (nesting) Uma estrutura de programa dentro da outra, como um comando condicional dentro de um bloco de outro comando condicional. recursividade (recursion) O processo de chamar a prpria funo que est sendo executada. caso base (base case) Um bloco do comando condicional numa funo recursiva que no resulta em uma chamada recursiva. recurso infinita (infinite recursion) Uma funo que chama a si mesma recursivamente sem nunca chegar ao caso base. Aps algum tempo, uma recurso infinita causa um erro de execuo. deixa (prompt) Uma indicao visual que diz ao usurio para entrar com os dados. System Message: WARNING/2 (<string>, line 3735) Definition list ends without a blank line; unexpected unindent.

Captulo 5: Funes frutferas

Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos o 3.4 Funes matemticas o 3.5 Composio o 3.6 Adicionando novas funes o 3.7 Definies e uso o 3.8 Fluxo de execuo o 3.9 Parmetros e argumentos o 3.10 Variveis e parmetros so locais o 3.11 Diagramas da pilha o 3.12 Funes com resultados o 3.13 Glossrio Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return

4.9 Recursividade 4.10 Diagramas de pilha para funes recursivas 4.11 Recursividade infinita 4.12 Entrada pelo teclado 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees
o o o o o

Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores 5.1 Valores de retorno Algumas das funes nativas do Python que temos usado, como as funes matemticas, produziram resultados. Chamar a funo gerou um novo valor, o qual geralmente atribumos uma varivel ou usamos como parte de uma expresso:
e = math.exp(1.0) altura = raio * math.sin(angulo)

Mas at agora, nenhuma das funes que ns mesmos escrevemos retornou um valor. Neste captulo, iremos escrever funes que retornam valores, as quais chamaremos de funes frutferas, ou funes que do frutos, na falta de um nome melhor. O primeiro exemplo area, que retorna a rea de um crculo dado o seu raio:
import math def area(raio): temp = math.pi * raio**2 return temp

J vimos a instruo return antes, mas em uma funo frutfera a instruo return inclui um valor de retorno. Esta instruo significa: "Retorne imediatamente desta funo e use a expresso em seguida como um valor de retorno". A expresso fornecida pode ser arbitrariamente complicada, de modo que poderamos ter escrito esta funo de maneira mais concisa:
def area(raio): return math.pi * raio**2

Por outro lado, variveis temporrias como temp muitas vezes tornam a depurao mais fcil. s vezes til ter mltiplos comandos return, um em cada ramo de uma condicional:
def valorAbsoluto(x): if x < 0: return -x else: return x

J que estes comandos return esto em ramos alternativos da condicional, apenas um ser executado. To logo um seja executado, a funo termina sem executar qualquer instruo ou comando subseqente. O cdigo que aparece depois de uma instruo return, ou em qualquer outro lugar que o fluxo de execuo jamais alcance, chamado cdigo morto (dead code). Em uma funo frutfera, uma boa idia assegurar que todo caminho possvel dentro do programa encontre uma instruo return. Por exemplo:
def valorAbsoluto(x): if x < 0: return -x elif x > 0: return x

Este programa no est correto porque se x for 0, nenhuma das condies ser verdadeira, e a funo terminar sem encontrar um comando return. Neste caso, o valor de retorno ser um valor especial chamado None:
>>> print valorAbsoluto(0) None

Como exerccio, escreva uma funo compare que retorne 1 se x > y, 0 se x == y e -1 se x < y. 5.2 Desenvolvimento de programas Neste ponto, voc deve estar apto a olhar para funes completas e dizer o que elas fazem. Tambm, se voc vem fazendo os exerccios, voc escreveu algumas pequenas funes. Conforme escrever funes maiores, voc pode comear a ter mais dificuldade, especialmente com erros em tempo de execuo (erros de runtime) ou erros semnticos. Para lidar com programas de crescente complexidade, vamos sugerir uma tcnica chamada desenvolvimento incremental. A meta do desenvolvimento incremental evitar sees de depurao (debugging) muito longas pela

adio e teste de somente uma pequena quantidade de cdigo de cada vez. Como exemplo, suponha que voc queira encontrar a distncia entre dois pontos, dados pelas coordenadas (x1,y1) e (x2,y2). Pelo teorema de Pitgoras, a distncia :
distancia = V (x2 - x1)2 + (y2 - y1)2 (5.1)

XXX: falta o sinal de raiz e elevar os expoentes desta frmula O primeiro passo considerar como deveria ser uma funo distancia em Python. Em outras palavras, quais so as entradas (parmetros) e qual a sada (valor de retorno)? Neste caso, os dois pontos so as entradas, os quais podemos representar usando quatro parmetros. O valor de retorno a distncia, que um valor em ponto flutuante. J podemos escrever um esboo da funo:
def distancia(x1, y1, x2, y2): return 0.0

Obviamente, esta verso da funo no computa distncias; ela sempre retorna zero. Mas ela est sintaticamente correta, e vai rodar, o que significa que podemos test-la antes de torn-la mais complicada. Para testar a nova funo, vamos cham-la com valores hipotticos:
>>> distancia(1, 2, 4, 6) 0.0

Escolhemos estes valores de modo que a distncia horizontal seja igual a 3 e a distncia vertical seja igual a 4; deste modo, o resultado 5 (a hipotenusa de um tringulo 3-4-5). Quando testamos uma funo, til sabermos qual o resultado correto. Neste ponto, j confirmamos que a funo est sintaticamente correta, e podemos comear a adicionar linhas de cdigo. Depois de cada mudana adicionada, testamos a funo de novo. Se um erro ocorre em qualquer ponto, sabemos aonde ele deve estar: nas linhas adicionadas mais recentemente. Um primeiro passo lgico nesta computao encontrar as diferenas x2 - x1 e y2 - y1. Ns iremos guardar estes valores em variveis temporrias chamadas dx e dy e imprimi-las:
def distancia(x1, y1, x2, y2): dx = x2 - x1 dy = y2 - y1 print "dx vale", dx print "dy vale", dy return 0.0

Se a funo estiver funcionando, as sadas devero ser 3 e 4. Se assim, sabemos que a funo est recebendo os parmetros corretos e realizando a primeira computao corretamente. Se no, existem poucas linhas para checar. Em seguida, computaremos a soma dos quadrados de dx e dy:
def distancia(x1, y1, x2, y2): dx = x2 - x1 dy = y2 - y1 dquadrado = dx**2 + dy**2 print "dquadrado vale: ", dquadrado return 0.0

Note que removemos os comandos print que havamos escrito no passo anterior. Cdigo como este chamado de andaime XXX (scaffolding) porque ajuda a escrever o programa, mas no parte do produto final. De novo, ns vamos rodar o programa neste estgio e checar a sada (que deveria ser 25). Finalmente, se ns tnhamos importado o mdulo matemtico math, podemos usar a funo sqrt para computar e retornar o resultado:
def distancia(x1, x2, y1, y2): dx = x2 - x1 dy = y2 - y1 dquadrado = dx**2 + dy**2 resultado = math.sqrt(dquadrado) return resultado

Se isto funcionar corretamente, voc conseguiu. Caso contrrio, talvez fosse preciso imprimir (exibir) o valor de resultado antes da instruo return. Enquanto for iniciante, voc deve acrescentar apenas uma ou duas linhas de cdigo de cada vez. Conforme ganhar mais experincia, voc se ver escrevendo e depurando pedaos maiores. De qualquer modo, o processo de desenvolvimento incremental pode poupar um bocado de tempo de depurao. Os aspectos chave do processo so: 1. Comece com um programa que funciona e faa pequenas mudanas incrementais. Em qualquer ponto do processo, se houver um erro, voc saber exatamente onde ele est. 2. Use variveis temporrias para manter valores intermedirios de modo que voc possa exibi-los e chec-los. 3. Uma vez que o programa funcione, voc pode querer remover algum cdigo muleta, ou andaime (scaffolding) ou consolidar mltiplos comandos dentro de expresses compostas, mas somente se isto no

tornar o programa difcil de ler. Como um exerccio, use o desenvolvimento incremental para escrever uma funo chamada hipotenusa que retorna a medida da hipotenusa de um tringulo retngulo dadas as medidas dos dois catetos como parmetros. Registre cada estgio do desenvolvimento incremental conforme voc avance. 5.3 Composio Conforme voc poderia esperar agora, voc pode chamar uma funo de dentro de outra. Esta habilidade chamada de composio. Como um exemplo, vamos escrever uma funo que recebe dois pontos, o centro de um crculo e um ponto em seu permetro, e calcula a rea do crculo. Assuma que o ponto do centro est guardado nas variveis xc e yc, e que o ponto do permetro est nas variveis xp e yp. O primeiro passo encontrar o raio do crculo, o qual a distncia entre os dois pontos. Felizmente, temos uma funo, distancia, que faz isto:
Raio = distancia(xc, yc, xp, yp)

O segundo passo encontrar a rea de um crculo com o raio dado e retornla:


resultado = area(raio) return resultado

Juntando tudo numa funo, temos:


def area2(xc, yc, xp, yp): raio = distancia(xc, yc, xp, yp) resultado = area(raio) return resultado

Chamamos esta funo de area2 para distinguir da funo area, definida anteriormente. S pode existir uma nica funo com um determinado nome em um determinado mdulo. As variveis temporrias raio e resultado so teis para o desenvolvimento e para depurao (debugging), mas uma vez que o programa esteja funcionando, podemos torn-lo mais conciso atravs da composio das chamadas de funo:
def area2(xc, yc, xp, yp): return area(distancia(xc, yc, xp, yp))

Como exerccio, escreva uma funo inclinacao(x1, y1, x2, y2) que retorne a inclinao (ou coeficienteAngular? XXX) de uma linha dados os pontos (x1, y1) e (x2, y2). Depois use esta funo em uma funo chamada cortaY(x1, y1, x2, y2) que retorne a interseo da linha com o eixo y, dados os pontos (x1, y1) e

(x2, y2). 5.4 Funes booleanas Funes podem retornar valores booleanos, o que muitas vezes conveniente por ocultar testes complicados dentro de funes. Por exemplo:
def ehDivisivel(x, y): If x % y == 0: return True # verdadeiro (true), divisvel else: return False # falso (false), no divisvel

O nome desta funo ehDivisivel (" divisvel"). comum dar a uma funo booleana nomes que soem como perguntas sim/no. ehDivisivel retorna ou True ou False para indicar se x ou no divisvel por y. Podemos tornar a funo mais concisa se tirarmos vantagem do fato de a condio da instruo if ser ela mesma uma expresso booleana. Podemos retorn-la diretamente, evitando totalmente o if:
def ehDivisivel(x, y): return x % y == 0

Esta sesso mostra a nova funo em ao:


>>> ehDivisivel(6, 4) False >>> ehDivisivel(6, 3) True

Funes booleanas so freqentemente usadas em comandos condicionais:


if ehDivisivel(x, y): print "x divisvel por y" else: print "x no divisvel por y"

Mas a comparao extra desnecessria. Como exerccio, escreva uma funo estaEntre(x, y, z) que retorne True se y < x < z ou False se no. 5.5 Mais recursividade At aqui, voc aprendeu apenas um pequeno subconjunto da linguagem Python, mas pode ser que te interesse saber que este pequeno subconjunto uma linguagem de programao completa, o que significa que qualquer coisa que possa ser computada pode ser expressa nesta linguagem. Qualquer programa j escrito pode ser reescrito usando somente os aspectos da linguagem que voc aprendeu at agora (usualmente, voc precisaria de uns poucos comandos para controlar dispositivos como o teclado, mouse, discos,

etc., mas isto tudo). Provar esta afirmao um exerccio nada trivial, que foi alcanado pela primeira vez por Alan Turing, um dos primeiros cientistas da computao (algum poderia dizer que ele foi um matemtico, mas muitos dos primeiros cientistas da computao comearam como matemticos). Por isso, ficou conhecido como Tese de Turing. Se voc fizer um curso em Teoria da Computao, voc ter chance de ver a prova. Para te dar uma idia do que voc pode fazer com as ferramentas que aprendeu a usar at agora, vamos avaliar algumas funes matemticas recursivamente definidas. Uma definio recursiva similar uma definio circular, no sentido de que a definio faz referncia coisa que est sendo definida. Uma verdadeira definio circular no muito til: vorpal: adjetivo usado para descrever algo que vorpal. Se voc visse esta definio em um dicionrio, ficaria confuso. Por outro lado, se voc procurasse pela definio da funo matemtica fatorial, voc encontraria algo assim:
0! = 1 n! = n.(n-1)!

Esta definio diz que o fatorial de 0 1, e que o fatorial de qualquer outro valor, n, n multiplicado pelo fatorial de n-1. Assim, 3! (l-se "3 fatorial" ou "fatorial de 3") 3 vezes 2!, o qual 2 vezes 1!, o qual 1 vezes 0!. Colocando tudo isso junto, 3! igual 3 vezes 2 vezes 1 vezes 1, o que 6. Se voc pode escrever uma definio recursiva de alguma coisa, voc geralmente pode escrever um programa em Python para execut-la. O primeiro passo decidir quais so os parmetros para esta funo. Com pouco esforo, voc dever concluir que fatorial recebe um nico parmetro:
def fatorial(n):

Se acontece de o argumento ser 0, tudo o que temos de fazer retornar 1:


def fatorial(n): if n == 0: return 1

Por outro lado, e esta a parte interessante, temos que fazer uma chamada recursiva para encontrar o fatorial de n-1 e ento multiplic-lo por n:
def fatorial(n): if n == 0: return 1 else: recursivo = fatorial(n-1)

resultado = n * recursivo return resultado

O fluxo de execuo para este programa similar ao fluxo de contagemRegressiva na Seo 4.9. Se chamarmos fatorial com o valor 3: J que 3 no 0, tomamos o segundo ramo e calculamos o fatorial de n-1 ... J que 2 no 0, tomamos o segundo ramo e calculamos o fatorial de n-1 ... J que 1 no 0, tomamos o segundo ramo e calculamos o fatorial de n-1 ... J que 0 0, tomamos o primeiro ramo e retornamos 1 sem fazer mais qualquer chamada recursiva. O valor retornado (1) multiplicado por n, que 1, e o resultado retornado. O valor retornado (1) multiplicado por n, que 2, e o resultado retornado. O valor retornado (2) multiplicado por n, que 1, e o resultado, 6, se torna o valor de retorno da chamada de funo que iniciou todo o processo. Eis o diagrama de pilha para esta seqncia de chamadas de funo: figura Os valores de retorno so mostrados sendo passados de volta para cima da pilha. Em cada quadro, o valor de retorno o valor de resultado, o qual o produto de n por recursivo. 5.6 Voto de confiana (Leap of faith) Seguir o fluxo de execuo uma maneira de ler programas, mas que pode rapidamente se transformar em um labirinto. Uma alternativa o que chamamos de "voto de confiana". Quando voc tem uma chamada de funo, em vez de seguir o fluxo de execuo, voc assume que a funo funciona corretamente e retorna o valor apropriado. De fato, voc est agora mesmo praticando este voto de confiana ao usar as funes nativas. Quando voc chama math.cos ou math.exp, voc no examina a implementao destas funes. Voc apenas assume que elas funcionam porque as pessoas que escreveram as bibliotecas nativas eram bons programadores. O mesmo tambm verdade quando voc chama uma de suas prprias funes. Por exemplo, na Seo 5.4, escrevemos a funo chamada ehDivisivel que determina se um nmero divisvel por outro. Uma vez que nos convencemos que esta funo est correta -- ao testar e examinar o cdigo -- podemos usar a funo sem examinar o cdigo novamente.

O mesmo tambm verdadeiro para programas recursivos. Quando voc tem uma chamada recursiva, em vez de seguir o fluxo de execuo, voc poderia assumir que a chamada recursiva funciona (produz o resultado correto) e ento perguntar-se, "Assumindo que eu possa encontrar o fatorial de n-1, posso calcular o fatorial de n?" Neste caso, claro que voc pode, multiplicando por n. Naturalmente, um pouco estranho que uma funo funcione corretamente se voc ainda nem terminou de escrev-la, mas por isso que se chama voto de confiana! 5.7 Mais um exemplo No exemplo anterior, usamos variveis temporrias para explicitar (spell out XXX) os passos e tornar o cdigo mais fcil de depurar, mas poderamos ter economizado algumas linhas:
def fatorial(n): if n == 0: return 1 else: return n * fatorial(n-1)

De agora em diante, tenderemos a utilizar um formato mais conciso, mas recomendamos que voc use a verso mais explcita enquanto estiver desenvolvendo cdigo. Quando ele estiver funcionando, voc pode enxug-lo se estiver se sentindo inspirado. Depois de fatorial, o exemplo mais comum de uma funo matemtica definida recursivamente fibonacci, a qual tem a seguinte definio:
fibonacci(0) = 1 fibonacci(1) = 1 fibonacci(n) = fibonacci(n-1) + fibonacci(n-2);

Traduzido em Python, parecer assim:


def fibonacci(n): if n == 0 or n == 1: return 1 else: return fibonacci(n-1) + fibonacci(n-2)

Se voc tentar seguir o fluxo de execuo aqui, mesmo para valores bem pequenos de n, sua cabea explodir. Mas, de acordo com o voto de confiana, se voc assume que as duas chamadas recursivas funcionam corretamente, ento claro que voc ter o resultado correto ao junt-las. 5.8 Checagem de tipos O que acontece se chamamos fatorial e damos a ela 1.5 como argumento?:

>>> fatorial (1.5) RuntimeError: Maximum recursion depth exceeded

Parece um caso de recursividade infinita. Mas o que ser que de fato? Existe um caso base -- quando n == 0. O problema que o valor de n nunca encontra o caso base. Na primeira chamada recursiva, o valor de n 0.5. Na prxima, ele igual a 0.5. Da em diante, ele se torna cada vez menor, mas jamais ser 0. Temos ento duas alternativas. Podemos tentar generalizar a funo fatorial para que funcione com nmeros em ponto flutuante, ou fazemos fatorial realizar a checagem de tipo de seus parmetros. A primeira chamada funo gamma e est um pouco alm do escopo deste livro. Sendo assim, ficaremos com a segunda. Podemos usar type para comparar o tipo do parmetro com o tipo de um valor inteiro conhecido (como 1). Ao mesmo tempo em que fazemos isto, podemos nos certificar tambm de que o parmetro seja positivo:
def fatorial (n): if type(n) != type(1): print "Fatorial somente definido para inteiros." return -1 elif n < 0: print "Fatorial somente definido para inteiros positivos." return -1 elif n ==0: return 1 else: return n * fatorial(n-1)

Agora temos trs casos base. O primeiro pega os no-inteiros. O segundo pega os inteiros negativos. Em ambos os casos, o programa exibe uma mensagem de erro e retorna um valor especial, -1, para indicar que alguma coisa saiu errada:
>>> fatorial ("Fred") Fatorial somente definido para inteiros. -1 >>> fatorial (-2) Fatorial somente definido para inteiros positivos. -1

Se passarmos pelas duas checagens, ento saberemos que n um inteiro positivo, e poderemos provar que a recursividade encontra seu trmino. Este programa demonstra um padro (pattern) chamado s vezes de guardio. As duas primeiras condicionais atuam como guardis, protegendo o cdigo que vem em seguida de valores que poderiam causar um erro. Os guardies tornam possvel garantir a correo do cdigo.

5.9 Glossrio funo frutfera (fruitful function) Uma funo que produz um valor de retorno. valor de retorno (return value) O valor entregue como resultado de uma chamada de funo. varivel temporria (temporary variable) Uma varivel usada para guardar um valor intermedirio em um clculo complexo. cdigo morto (dead code) Parte de um programa que nunca pode ser executada, muitas vezes por que ela aparece depois de uma instruo return. None Um valor especial em Python, retornado por funes que no possuem uma instruo return ou tm uma instruo return sem argumento. desenvolvimento incremental (incremental development) Uma estratgia de desenvolvimento de programas que evita a depurao ao adicionar e testar somente uma pequena quantidade de cdigo de cada vez. andaime (scaffolding) Cdigo usado durante o desenvolvimento do programa, mas que no faz parte do produto final. guardio (guardian) Uma condio que checa e manipula circunstncias que poderiam causar um erro.

Captulo 5: Funes frutferas


System Message: INFO/1 (<string>, line 4126); backlink Duplicate implicit target name: "captulo 5: funes frutferas". Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis

2.3 Nomes de variveis e palavras reservadas 2.4 Comandos 2.5 Avaliando expresses 2.6 Operadores e operandos 2.7 Ordem dos operadores 2.8 Operaes com strings 2.9 Composio 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos o 3.4 Funes matemticas o 3.5 Composio o 3.6 Adicionando novas funes o 3.7 Definies e uso o 3.8 Fluxo de execuo o 3.9 Parmetros e argumentos o 3.10 Variveis e parmetros so locais o 3.11 Diagramas da pilha o 3.12 Funes com resultados o 3.13 Glossrio Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado
o o o o o o o o

o 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores

Captulo 20: rvores 5.1 Valores de retorno System Message: INFO/1 (<string>, line 4132); backlink Duplicate implicit target name: "5.1 valores de retorno". Algumas das funes nativas do Python que temos usado, como as funes matemticas, produziram resultados. Chamar a funo gerou um novo valor, o qual geralmente atribumos uma varivel ou usamos como parte de uma expresso:
e = math.exp(1.0) altura = raio * math.sin(angulo)

Mas at agora, nenhuma das funes que ns mesmos escrevemos retornou um valor. Neste captulo, iremos escrever funes que retornam valores, as quais chamaremos de funes frutferas, ou funes que do frutos, na falta de um nome melhor. O primeiro exemplo area, que retorna a rea de um crculo dado o seu raio:
import math def area(raio): temp = math.pi * raio**2 return temp

J vimos a instruo return antes, mas em uma funo frutfera a instruo return inclui um valor de retorno. Esta instruo significa: "Retorne imediatamente desta funo e use a expresso em seguida como um valor de retorno". A expresso fornecida pode ser arbitrariamente complicada, de modo que poderamos ter escrito esta funo de maneira mais concisa:
def area(raio): return math.pi * raio**2

Por outro lado, variveis temporrias como temp muitas vezes tornam a depurao mais fcil. s vezes til ter mltiplos comandos return, um em cada ramo de uma condicional:
def valorAbsoluto(x): if x < 0: return -x else: return x

J que estes comandos return esto em ramos alternativos da condicional,

apenas um ser executado. To logo um seja executado, a funo termina sem executar qualquer instruo ou comando subseqente. O cdigo que aparece depois de uma instruo return, ou em qualquer outro lugar que o fluxo de execuo jamais alcance, chamado cdigo morto (dead code). Em uma funo frutfera, uma boa idia assegurar que todo caminho possvel dentro do programa encontre uma instruo return. Por exemplo:
def valorAbsoluto(x): if x < 0: return -x elif x > 0: return x

Este programa no est correto porque se x for 0, nenhuma das condies ser verdadeira, e a funo terminar sem encontrar um comando return. Neste caso, o valor de retorno ser um valor especial chamado None:
>>> print valorAbsoluto(0) None

Como exerccio, escreva uma funo compare que retorne 1 se x > y, 0 se x == y e -1 se x < y. 5.2 Desenvolvimento de programas System Message: INFO/1 (<string>, line 4185); backlink Duplicate implicit target name: "5.2 desenvolvimento de programas". Neste ponto, voc deve estar apto a olhar para funes completas e dizer o que elas fazem. Tambm, se voc vem fazendo os exerccios, voc escreveu algumas pequenas funes. Conforme escrever funes maiores, voc pode comear a ter mais dificuldade, especialmente com erros em tempo de execuo (erros de runtime) ou erros semnticos. Para lidar com programas de crescente complexidade, vamos sugerir uma tcnica chamada desenvolvimento incremental. A meta do desenvolvimento incremental evitar sees de depurao (debugging) muito longas pela adio e teste de somente uma pequena quantidade de cdigo de cada vez. Como exemplo, suponha que voc queira encontrar a distncia entre dois pontos, dados pelas coordenadas (x1,y1) e (x2,y2). Pelo teorema de Pitgoras, a distncia :
distancia = V (x2 - x1)2 + (y2 - y1)2 (5.1)

XXX: falta o sinal de raiz e elevar os expoentes desta frmula

O primeiro passo considerar como deveria ser uma funo distancia em Python. Em outras palavras, quais so as entradas (parmetros) e qual a sada (valor de retorno)? Neste caso, os dois pontos so as entradas, os quais podemos representar usando quatro parmetros. O valor de retorno a distncia, que um valor em ponto flutuante. J podemos escrever um esboo da funo:
def distancia(x1, y1, x2, y2): return 0.0

Obviamente, esta verso da funo no computa distncias; ela sempre retorna zero. Mas ela est sintaticamente correta, e vai rodar, o que significa que podemos test-la antes de torn-la mais complicada. Para testar a nova funo, vamos cham-la com valores hipotticos:
>>> distancia(1, 2, 4, 6) 0.0

Escolhemos estes valores de modo que a distncia horizontal seja igual a 3 e a distncia vertical seja igual a 4; deste modo, o resultado 5 (a hipotenusa de um tringulo 3-4-5). Quando testamos uma funo, til sabermos qual o resultado correto. Neste ponto, j confirmamos que a funo est sintaticamente correta, e podemos comear a adicionar linhas de cdigo. Depois de cada mudana adicionada, testamos a funo de novo. Se um erro ocorre em qualquer ponto, sabemos aonde ele deve estar: nas linhas adicionadas mais recentemente. Um primeiro passo lgico nesta computao encontrar as diferenas x2 - x1 e y2 - y1. Ns iremos guardar estes valores em variveis temporrias chamadas dx e dy e imprimi-las:
def distancia(x1, y1, x2, y2): dx = x2 - x1 dy = y2 - y1 print "dx vale", dx print "dy vale", dy return 0.0

Se a funo estiver funcionando, as sadas devero ser 3 e 4. Se assim, sabemos que a funo est recebendo os parmetros corretos e realizando a primeira computao corretamente. Se no, existem poucas linhas para checar. Em seguida, computaremos a soma dos quadrados de dx e dy:
def distancia(x1, y1, x2, y2): dx = x2 - x1

dy = y2 - y1 dquadrado = dx**2 + dy**2 print "dquadrado vale: ", dquadrado return 0.0

Note que removemos os comandos print que havamos escrito no passo anterior. Cdigo como este chamado de andaime XXX (scaffolding) porque ajuda a escrever o programa, mas no parte do produto final. De novo, ns vamos rodar o programa neste estgio e checar a sada (que deveria ser 25). Finalmente, se ns tnhamos importado o mdulo matemtico math, podemos usar a funo sqrt para computar e retornar o resultado:
def distancia(x1, x2, y1, y2): dx = x2 - x1 dy = y2 - y1 dquadrado = dx**2 + dy**2 resultado = math.sqrt(dquadrado) return resultado

Se isto funcionar corretamente, voc conseguiu. Caso contrrio, talvez fosse preciso imprimir (exibir) o valor de resultado antes da instruo return. Enquanto for iniciante, voc deve acrescentar apenas uma ou duas linhas de cdigo de cada vez. Conforme ganhar mais experincia, voc se ver escrevendo e depurando pedaos maiores. De qualquer modo, o processo de desenvolvimento incremental pode poupar um bocado de tempo de depurao. Os aspectos chave do processo so: 1. Comece com um programa que funciona e faa pequenas mudanas incrementais. Em qualquer ponto do processo, se houver um erro, voc saber exatamente onde ele est. 2. Use variveis temporrias para manter valores intermedirios de modo que voc possa exibi-los e chec-los. 3. Uma vez que o programa funcione, voc pode querer remover algum cdigo muleta, ou andaime (scaffolding) ou consolidar mltiplos comandos dentro de expresses compostas, mas somente se isto no tornar o programa difcil de ler. Como um exerccio, use o desenvolvimento incremental para escrever uma funo chamada hipotenusa que retorna a medida da hipotenusa de um tringulo retngulo dadas as medidas dos dois catetos como parmetros. Registre cada estgio do desenvolvimento incremental conforme voc avance. 5.3 Composio

System Message: INFO/1 (<string>, line 4266); backlink Duplicate implicit target name: "5.3 composio". Conforme voc poderia esperar agora, voc pode chamar uma funo de dentro de outra. Esta habilidade chamada de composio. Como um exemplo, vamos escrever uma funo que recebe dois pontos, o centro de um crculo e um ponto em seu permetro, e calcula a rea do crculo. Assuma que o ponto do centro est guardado nas variveis xc e yc, e que o ponto do permetro est nas variveis xp e yp. O primeiro passo encontrar o raio do crculo, o qual a distncia entre os dois pontos. Felizmente, temos uma funo, distancia, que faz isto:
Raio = distancia(xc, yc, xp, yp)

O segundo passo encontrar a rea de um crculo com o raio dado e retornla:


resultado = area(raio) return resultado

Juntando tudo numa funo, temos:


def area2(xc, yc, xp, yp): raio = distancia(xc, yc, xp, yp) resultado = area(raio) return resultado

Chamamos esta funo de area2 para distinguir da funo area, definida anteriormente. S pode existir uma nica funo com um determinado nome em um determinado mdulo. As variveis temporrias raio e resultado so teis para o desenvolvimento e para depurao (debugging), mas uma vez que o programa esteja funcionando, podemos torn-lo mais conciso atravs da composio das chamadas de funo:
def area2(xc, yc, xp, yp): return area(distancia(xc, yc, xp, yp))

Como exerccio, escreva uma funo inclinacao(x1, y1, x2, y2) que retorne a inclinao (ou coeficienteAngular? XXX) de uma linha dados os pontos (x1, y1) e (x2, y2). Depois use esta funo em uma funo chamada cortaY(x1, y1, x2, y2) que retorne a interseo da linha com o eixo y, dados os pontos (x1, y1) e (x2, y2). 5.4 Funes booleanas

System Message: INFO/1 (<string>, line 4299); backlink Duplicate implicit target name: "5.4 funes booleanas". Funes podem retornar valores booleanos, o que muitas vezes conveniente por ocultar testes complicados dentro de funes. Por exemplo:
def ehDivisivel(x, y): If x % y == 0: return True # verdadeiro (true), divisvel else: return False # falso (false), no divisvel

O nome desta funo ehDivisivel (" divisvel"). comum dar a uma funo booleana nomes que soem como perguntas sim/no. ehDivisivel retorna ou True ou False para indicar se x ou no divisvel por y. Podemos tornar a funo mais concisa se tirarmos vantagem do fato de a condio da instruo if ser ela mesma uma expresso booleana. Podemos retorn-la diretamente, evitando totalmente o if:
def ehDivisivel(x, y): return x % y == 0

Esta sesso mostra a nova funo em ao:


>>> ehDivisivel(6, 4) False >>> ehDivisivel(6, 3) True

Funes booleanas so freqentemente usadas em comandos condicionais:


if ehDivisivel(x, y): print "x divisvel por y" else: print "x no divisvel por y"

Mas a comparao extra desnecessria. Como exerccio, escreva uma funo estaEntre(x, y, z) que retorne True se y < x < z ou False se no. 5.5 Mais recursividade System Message: INFO/1 (<string>, line 4336); backlink Duplicate implicit target name: "5.5 mais recursividade". At aqui, voc aprendeu apenas um pequeno subconjunto da linguagem Python, mas pode ser que te interesse saber que este pequeno subconjunto uma linguagem de programao completa, o que significa que qualquer coisa

que possa ser computada pode ser expressa nesta linguagem. Qualquer programa j escrito pode ser reescrito usando somente os aspectos da linguagem que voc aprendeu at agora (usualmente, voc precisaria de uns poucos comandos para controlar dispositivos como o teclado, mouse, discos, etc., mas isto tudo). Provar esta afirmao um exerccio nada trivial, que foi alcanado pela primeira vez por Alan Turing, um dos primeiros cientistas da computao (algum poderia dizer que ele foi um matemtico, mas muitos dos primeiros cientistas da computao comearam como matemticos). Por isso, ficou conhecido como Tese de Turing. Se voc fizer um curso em Teoria da Computao, voc ter chance de ver a prova. Para te dar uma idia do que voc pode fazer com as ferramentas que aprendeu a usar at agora, vamos avaliar algumas funes matemticas recursivamente definidas. Uma definio recursiva similar uma definio circular, no sentido de que a definio faz referncia coisa que est sendo definida. Uma verdadeira definio circular no muito til: vorpal: adjetivo usado para descrever algo que vorpal. Se voc visse esta definio em um dicionrio, ficaria confuso. Por outro lado, se voc procurasse pela definio da funo matemtica fatorial, voc encontraria algo assim:
0! = 1 n! = n.(n-1)!

Esta definio diz que o fatorial de 0 1, e que o fatorial de qualquer outro valor, n, n multiplicado pelo fatorial de n-1. Assim, 3! (l-se "3 fatorial" ou "fatorial de 3") 3 vezes 2!, o qual 2 vezes 1!, o qual 1 vezes 0!. Colocando tudo isso junto, 3! igual 3 vezes 2 vezes 1 vezes 1, o que 6. Se voc pode escrever uma definio recursiva de alguma coisa, voc geralmente pode escrever um programa em Python para execut-la. O primeiro passo decidir quais so os parmetros para esta funo. Com pouco esforo, voc dever concluir que fatorial recebe um nico parmetro:
def fatorial(n):

Se acontece de o argumento ser 0, tudo o que temos de fazer retornar 1:


def fatorial(n): if n == 0: return 1

Por outro lado, e esta a parte interessante, temos que fazer uma chamada recursiva para encontrar o fatorial de n-1 e ento multiplic-lo por n:

def fatorial(n): if n == 0: return 1 else: recursivo = fatorial(n-1) resultado = n * recursivo return resultado

O fluxo de execuo para este programa similar ao fluxo de contagemRegressiva na Seo 4.9. Se chamarmos fatorial com o valor 3: J que 3 no 0, tomamos o segundo ramo e calculamos o fatorial de n-1 ... J que 2 no 0, tomamos o segundo ramo e calculamos o fatorial de n-1 ... J que 1 no 0, tomamos o segundo ramo e calculamos o fatorial de n-1 ... J que 0 0, tomamos o primeiro ramo e retornamos 1 sem fazer mais qualquer chamada recursiva. O valor retornado (1) multiplicado por n, que 1, e o resultado retornado. O valor retornado (1) multiplicado por n, que 2, e o resultado retornado. O valor retornado (2) multiplicado por n, que 1, e o resultado, 6, se torna o valor de retorno da chamada de funo que iniciou todo o processo. Eis o diagrama de pilha para esta seqncia de chamadas de funo: figura Os valores de retorno so mostrados sendo passados de volta para cima da pilha. Em cada quadro, o valor de retorno o valor de resultado, o qual o produto de n por recursivo. 5.6 Voto de confiana (Leap of faith) System Message: INFO/1 (<string>, line 4400); backlink Duplicate implicit target name: "5.6 voto de confiana (leap of faith)". Seguir o fluxo de execuo uma maneira de ler programas, mas que pode rapidamente se transformar em um labirinto. Uma alternativa o que chamamos de "voto de confiana". Quando voc tem uma chamada de funo, em vez de seguir o fluxo de execuo, voc assume que a funo funciona corretamente e retorna o valor apropriado. De fato, voc est agora mesmo praticando este voto de confiana ao usar as funes nativas. Quando voc chama math.cos ou math.exp, voc no examina a implementao destas funes. Voc apenas assume que elas funcionam porque as pessoas que escreveram as bibliotecas nativas eram

bons programadores. O mesmo tambm verdade quando voc chama uma de suas prprias funes. Por exemplo, na Seo 5.4, escrevemos a funo chamada ehDivisivel que determina se um nmero divisvel por outro. Uma vez que nos convencemos que esta funo est correta -- ao testar e examinar o cdigo -- podemos usar a funo sem examinar o cdigo novamente. O mesmo tambm verdadeiro para programas recursivos. Quando voc tem uma chamada recursiva, em vez de seguir o fluxo de execuo, voc poderia assumir que a chamada recursiva funciona (produz o resultado correto) e ento perguntar-se, "Assumindo que eu possa encontrar o fatorial de n-1, posso calcular o fatorial de n?" Neste caso, claro que voc pode, multiplicando por n. Naturalmente, um pouco estranho que uma funo funcione corretamente se voc ainda nem terminou de escrev-la, mas por isso que se chama voto de confiana! 5.7 Mais um exemplo System Message: INFO/1 (<string>, line 4414); backlink Duplicate implicit target name: "5.7 mais um exemplo". No exemplo anterior, usamos variveis temporrias para explicitar (spell out XXX) os passos e tornar o cdigo mais fcil de depurar, mas poderamos ter economizado algumas linhas:
def fatorial(n): if n == 0: return 1 else: return n * fatorial(n-1)

De agora em diante, tenderemos a utilizar um formato mais conciso, mas recomendamos que voc use a verso mais explcita enquanto estiver desenvolvendo cdigo. Quando ele estiver funcionando, voc pode enxug-lo se estiver se sentindo inspirado. Depois de fatorial, o exemplo mais comum de uma funo matemtica definida recursivamente fibonacci, a qual tem a seguinte definio:
fibonacci(0) = 1 fibonacci(1) = 1 fibonacci(n) = fibonacci(n-1) + fibonacci(n-2);

Traduzido em Python, parecer assim:


def fibonacci(n): if n == 0 or n == 1: return 1

else: return fibonacci(n-1) + fibonacci(n-2)

Se voc tentar seguir o fluxo de execuo aqui, mesmo para valores bem pequenos de n, sua cabea explodir. Mas, de acordo com o voto de confiana, se voc assume que as duas chamadas recursivas funcionam corretamente, ento claro que voc ter o resultado correto ao junt-las. 5.8 Checagem de tipos System Message: INFO/1 (<string>, line 4444); backlink Duplicate implicit target name: "5.8 checagem de tipos". O que acontece se chamamos fatorial e damos a ela 1.5 como argumento?:
>>> fatorial (1.5) RuntimeError: Maximum recursion depth exceeded

Parece um caso de recursividade infinita. Mas o que ser que de fato? Existe um caso base -- quando n == 0. O problema que o valor de n nunca encontra o caso base. Na primeira chamada recursiva, o valor de n 0.5. Na prxima, ele igual a 0.5. Da em diante, ele se torna cada vez menor, mas jamais ser 0. Temos ento duas alternativas. Podemos tentar generalizar a funo fatorial para que funcione com nmeros em ponto flutuante, ou fazemos fatorial realizar a checagem de tipo de seus parmetros. A primeira chamada funo gamma e est um pouco alm do escopo deste livro. Sendo assim, ficaremos com a segunda. Podemos usar type para comparar o tipo do parmetro com o tipo de um valor inteiro conhecido (como 1). Ao mesmo tempo em que fazemos isto, podemos nos certificar tambm de que o parmetro seja positivo:
def fatorial (n): if type(n) != type(1): print "Fatorial somente definido para inteiros." return -1 elif n < 0: print "Fatorial somente definido para inteiros positivos." return -1 elif n ==0: return 1 else: return n * fatorial(n-1)

Agora temos trs casos base. O primeiro pega os no-inteiros. O segundo pega os inteiros negativos. Em ambos os casos, o programa exibe uma mensagem de erro e retorna um valor especial, -1, para indicar que alguma

coisa saiu errada:


>>> fatorial ("Fred") Fatorial somente definido para inteiros. -1 >>> fatorial (-2) Fatorial somente definido para inteiros positivos. -1

Se passarmos pelas duas checagens, ento saberemos que n um inteiro positivo, e poderemos provar que a recursividade encontra seu trmino. Este programa demonstra um padro (pattern) chamado s vezes de guardio. As duas primeiras condicionais atuam como guardis, protegendo o cdigo que vem em seguida de valores que poderiam causar um erro. Os guardies tornam possvel garantir a correo do cdigo. 5.9 Glossrio System Message: INFO/1 (<string>, line 4486); backlink Duplicate implicit target name: "5.9 glossrio". funo frutfera (fruitful function) Uma funo que produz um valor de retorno. valor de retorno (return value) O valor entregue como resultado de uma chamada de funo. varivel temporria (temporary variable) Uma varivel usada para guardar um valor intermedirio em um clculo complexo. cdigo morto (dead code) Parte de um programa que nunca pode ser executada, muitas vezes por que ela aparece depois de uma instruo return. None Um valor especial em Python, retornado por funes que no possuem uma instruo return ou tm uma instruo return sem argumento. desenvolvimento incremental (incremental development) Uma estratgia de desenvolvimento de programas que evita a depurao ao adicionar e testar somente uma pequena quantidade de cdigo de cada vez. andaime (scaffolding) Cdigo usado durante o desenvolvimento do programa, mas que no faz parte do produto final. guardio (guardian) Uma condio que checa e manipula circunstncias que poderiam causar um erro. System Message: WARNING/2 (<string>, line 4511) Definition list ends without a blank line; unexpected unindent.

Captulo 6: Iterao
Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos o 3.4 Funes matemticas o 3.5 Composio o 3.6 Adicionando novas funes o 3.7 Definies e uso o 3.8 Fluxo de execuo o 3.9 Parmetros e argumentos o 3.10 Variveis e parmetros so locais o 3.11 Diagramas da pilha o 3.12 Funes com resultados o 3.13 Glossrio Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa

4.6 Condicionais encadeados 4.7 Condicionais aninhados 4.8 A instruo return 4.9 Recursividade 4.10 Diagramas de pilha para funes recursivas 4.11 Recursividade infinita 4.12 Entrada pelo teclado 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas
o o o o o o o o

Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores

6.1 Atribuio mltipla

Como voc talvez j tenha descoberto, permitido fazer mais de uma atribuio mesma varivel. Uma nova atribuio faz uma varivel existente referir-se a um novo valor (sem se referir mais ao antigo).:
bruno = 5 print bruno, bruno = 7 print bruno

A sada deste programa 5 7, porque na primeira vez que bruno impresso, seu valor 5 e na segunda vez, seu valor 7. A vrgula no final do primeiro comando print suprime a nova linha no final da sada, que o motivo pelo qual as duas sadas aparecem na mesma linha. Aqui est como se parece a atribuio mltipla em um diagrama de estado: XXXfigura pg.59 Com a atribuio mltipla especialmente importante distinguir entre uma operao de atribuio e um comando de igualdade. Porque Python usa o

sinal de igual ( = ) para atribuio, existe a tendncia de interpretar um comando como a = b como um comando de igualdade. Ele no ! Em primeiro lugar, igualdade comutativa e atribuio no . Por exemplo, em matemtica, se a = 7 ento 7 = a. Mas em Python, o comando a = 7 permitido e 7 = a no . Alm disso, em matemtica, uma expresso de igualdade sempre verdadeira. Se a = b agora, ento, a ser sempre igual a b. Em Python, um comando de atribuio pode tornar duas variveis iguais, mas elas no tm que permanecer assim:
a=5 b = a # a e b agora so iguais b = 3 # a e b no so mais iguais

A terceira linha muda o valor de a mas no muda o valor de b, ento, elas no so mais iguais. (Em algumas linguagens de programao, um smbolo diferente usado para atribuio, como <- ou :=, para evitar confuso.) Embora a atribuio mltipla seja freqentemente til, voc deve us-la com cautela. Se o valor das variveis muda freqentemente, isto pode fazer o cdigo difcil de ler e de depurar.

6.2 O comando while

Os computadores so muito utilizados para automatizar tarefas repetitivas. Repetir tarefas idnticas ou similares sem cometer erros uma coisa que os computadores fazem bem e que as pessoas fazem poorly. Vimos dois programas, nLinhas e contagemRegressiva, que usam recursividade (recurso) para fazer a repetio, que tambm chamada iterao. Porque a iterao muito comum, Python tem vrias caractersticas para torn-la mais fcil. A primeira delas em que vamos dar uma olhada o comando while. Aqui est como fica contagemRegressiva com um comando while:
def contagemRegressiva(n): while n > 0: print n n = n-1

print "Fogo!"

Desde que removemos a chamada recursiva, esta funo no recursiva. Voc quase pode ler o comando while como se fosse Ingls. Ele significa, "Enquanto (while) n for maior do que 0, siga exibindo o valor de n e diminuindo 1 do valor de n. Quando chegar a 0, exiba a palavra Fogo!". Mais formalmente, aqui est o fluxo de execuo para um comando while: 1. Teste a condio, resultando 0 ou 1. 2. Se a condio for falsa (0), saia do comando while e continue a execuo a partir do prximo comando. 3. Se a condio for verdadeira (1), execute cada um dos comandos dentro do corpo e volte ao passo 1. O corpo consiste de todos os comandos abaixo do cabealho, com a mesma endentao. Este tipo de fluxo chamado de um loop (ou lao) porque o terceiro passo cria um "loop" ou um lao de volta ao topo. Note que se a condio for falsa na primeira vez que entrarmos no loop, os comandos dentro do loop jamais sero executados. O corpo do loop poderia alterar o valor de uma ou mais variveis de modo que eventualmente a condio se torne falsa e o loop termine. Se no for assim, o loop se repetir para sempre, o que chamado de um loop infinito. Uma fonte de diverso sem fim para os cientistas da computao a observao de que as instrues da embalagem de shampoo, "Lave, enxge, repita" um loop infinito. No caso de contagemRegressiva, podemos provar que o loop terminar porque sabemos que o valor de n finito, e podemos ver que o valor de n diminui dentro de cada repetio (iterao) do loop, ento, eventualmente chegaremos ao 0. Em outros casos, isto no to simples de afirmar:
def sequencia(n): while n != 1: print n, if n%2 == 0: n = n/2 else: n = n*3+1 # n impar # n par

A condio para este loop n != 1, ento o loop vai continuar at que n seja 1,

o que tornar a condio falsa. Dentro de cada repetio (iterao) do loop, o programa gera o valor de n e ento checa se ele par ou impar. Se ele for par, o valor de n dividido por 2. Se ele for impar, o valor substitudo por n*3+1. Por exemplo, se o valor inicial (o argumento passado para seqncia) for 3, a seqncia resultante ser 3, 10, 5, 16, 8, 4, 2, 1. J que n s vezes aumenta e s vezes diminui, no existe uma prova bvia de que n jamais venha a alcanar 1, ou de que o programa termine. Para alguns valores particulares de n, podemos provar o trmino. Por exemplo, se o valor inicial for uma potncia de dois, ento o valor de n ser par dentro de cada repetio (iterao) do loop at que alcance 1. O exemplo anterior termina com uma dessas seqncias comeando em 16. Valores especficos parte, A questo interessante se h como provarmos que este programa termina para todos os valores de n. At hoje, ningum foi capaz de provar que sim ou que no! Como um exerccio, reescreva a funo nLinhas da seo 4.9 usando iterao em vez de recurso.

6.3 Tabelas

Uma das coisas para qual os loops so bons para gerar dados tabulares. Antes que os computadores estivessem readily disponveis, as pessoas tinham que calcular logaritmos, senos, cossenos e outras funes matemticas mo. Para tornar isto mais fcil, os livros de matemtica continham longas tabelas listando os valores destas funes. Criar as tabelas era demorado e entediante, e elas tendiam a ser cheias de erros. Quando os computadores entraram em cena, uma das reaes iniciais foi "Isto timo! Podemos usar computadores para geras as tabelas, assim no haver erros." Isto veio a se tornar verdade (na maioria das vezes) mas shortsighted. Rapidamente, porm, computadores e calculadoras tornaram-se to pervasivos que as tabelas ficaram obsoletas. Bem, quase. Para algumas operaes, os computadores usam tabelas de valores para conseguir uma resposta aproximada e ento realizar clculos para melhorar a aproximao. Em alguns casos, tm havido erros nas tabelas underlying, o caso mais famoso sendo o da tabela usada pelo processador Pentium da Intel para executar a diviso em ponto-flutuante. Embora uma tabela de logaritmos no seja mais to til quanto j foi um dia, ela ainda d um bom exemplo de iterao. O seguinte programa gera uma seqncia de valores na coluna da esquerda e seus respectivos logaritmos na

coluna da direita:
x = 1.0 while x < 10.0: print x, '\t', math.log(x) x = x + 1.0

A string '\t' representa um caracter de tabulao. Conforme caracteres e strings vo sendo mostrados na tela, um ponteiro invisvel chamado cursor marca aonde aparecer o prximo caractere. Depois de um comando print, o cursor normalmente vai para o incio de uma nova linha. O caractere de tabulao desloca o cursor para a direita at que ele encontre uma das marcas de tabulao. Tabulao til para fazer colunas de texto line up, como na sada do programa anterior:
1.0 0.0 2.0 0.69314718056 3.0 1.09861228867 4.0 1.38629436112 5.0 1.60943791243 6.0 1.79175946923 7.0 1.94591014906 8.0 2.07944154168 9.0 2.19722457734

Se estes valores parecem odd, lembre-se que a funo log usa a base e. J que potncias de dois so to importantes em cincia da computao, ns freqentemente temos que achar logaritmos referentes base 2. Para fazermos isso, podemos usar a seguinte frmula: System Message: WARNING/2 (<string>, line 4759) Literal block expected; none found. log2 x = loge x (6.1) loge 2 Alterando o comando de sada para:

print x, '\t', math.log(x)/math.log(2.0)

o que resultar em:


1.0 0.0 2.0 1.0 3.0 1.58496250072 4.0 2.0 5.0 2.32192809489 6.0 2.58496250072 7.0 2.80735492206 8.0 3.0 9.0 3.16992500144

Podemos ver que 1, 2, 4 e 8 so potncias de dois porque seus logaritmos na base 2 so nmeros redondos. Se precisssemos encontrar os logaritmos de outras potncias de dois, poderamos modificar o programa deste modo:
x = 1.0 while x < 100.0: print x, '\t', math.log(x)/math.log(2.0) x = x * 2.0

Agora, em vez de somar algo a x a cada iterao do loop, o que resulta numa seqncia aritmtica, ns multiplicamos x por algo, resultando numa seqncia geomtrica. O resultado :
1.0 0.0 2.0 1.0 4.0 2.0 8.0 3.0 16.0 4.0 32.0 5.0 64.0 6.0

Por causa do caractere de tabulao entre as colunas, a posio da segunda coluna no depende do nmero de dgitos na primeira coluna. Tabelas de logaritmos podem no ser mais teis, mas para cientistas da

computao, conhecer as potncias de dois ! Como um exerccio, modifique este programa de modo que ele produza as potncias de dois acima de 65.535 (ou seja, 216). Imprima e memorize-as. O caractere de barra invertida em '\t' indica o incio de uma seqncia de escape. Seqncias de escape so usadas para representar caracteres invisveis como de tabulao e de nova linha. A seqncia \n representa uma nova linha. Uma seqncia de escape pode aparecer em qualquer lugar em uma string; no exemplo, a seqncia de escape de tabulao a nica coisa dentro da string. Como voc acha que se representa uma barra invertida em uma string? Como um exerccio, escreva um nica string que produza esta sada.

6.4 Tabelas de duas dimenses (ou bi-dimensionais)

Uma tabela de duas dimenses uma tabela em que voc l o valor na interseo entre uma linha e uma coluna. Uma tabela de multiplicao um bom exemplo. Digamos que voc queira imprimir uma tabela de multiplicao de 1 a 6. Uma boa maneira de comear escrever um loop que imprima os mltiplos de 2, todos em uma linha:
i=1 while i <= 6: print 2*i, ' ', i=i+1 print

A primeira linha inicializa a varivel chamada i, a qual age como um contador ou varivel de controle do loop. Conforme o loop executado, o valor de i incrementado de 1 a 6. Quando i for 7, o loop termina. A cada repetio

(iterao) do loop, mostrado o valor de 2*i, seguido de trs espaos. De novo, a vrgula no comando print suprime a nova linha. Depois que o loop se completa, o segundo comando print inicia uma nova linha. A sada do programa :
2 4 6 8 10 12

At aqui, tudo bem. O prximo passo encapsular e generalizar.

6.5 Encapsulamento e generalizao

Encapsulamento o processo de wrapping um pedao de cdigo em uma funo, permitindo que voc tire vantagem de todas as coisas para as quais as funes so boas. Voc j viu dois exemplos de encapsulamento: imprimeParidade na seo 4.5; e eDivisivel na seo 5.4 Generalizao significa tomar algo que especfico, tal como imprimir os mltiplos de 2, e torn-lo mais geral, tal como imprimir os mltiplos de qualquer inteiro. Esta funo encapsula o loop anterior e generaliza-o para imprimir mltiplos de n:
def imprimeMultiplos(n): i=1 while i <= 6: print n*i, '\t ', i=i+1 print

Para encapsular, tudo o que tivemos que fazer foi adicionar a primeira linha, que declara o nome de uma funo e sua lista de parmetros. Para generalizar, tudo o que tivemos que fazer foi substituir o valor 2 pelo parmetro n. Se chamarmos esta funo com o argumento 2, teremos a mesma sada que antes. Com o argumento 3, a sada :
3 6 9 12 15 18

Com o argumento 4, a sada :


4 8 12 16 20 24

Agora voc provavelmente pode adivinhar como imprimir uma tabela de multiplicao - chamando imprimeMultiplos repetidamente com argumentos diferentes. De fato, podemos usar um outro loop:
i=1 while i <= 6: imprimeMultiplos(i) i=i+1

Note o quanto este loop parecido com aquele dentro de imprimeMultiplos. Tudo o que fiz foi substituir o comando print pela chamada funo. A sada deste programa uma tabela de multiplicao:
1 2 3 4 5 6 2 4 6 8 10 12 3 6 9 12 15 18 4 8 12 16 20 24 5 10 15 20 25 30 6 12 18 24 30 36

6.6 Mais encapsulamento

Para demonstrar de novo o encapsulamento, vamos pegar o cdigo do final da seo 6.5 e acondicion-lo, envolv-lo em uma funo:
def imprimeTabMult(): i=1 while i <= 6: imprimeMultiplos(i) i=i+1

Este processo um plano de desenvolvimento comum. Ns desenvolvemos cdigo escrevendo linhas de cdigo fora de qualquer funo, ou digitando-as

no interpretador. Quando temos o cdigo funcionando, extramos ele e o embalamos em uma funo. Este plano de desenvolvimento particularmente til se voc no sabe, quando voc comea a escrever, como dividir o programa em funes. Esta tcnica permite a voc projetar enquanto desenvolve.

6.7 Variveis locais

Voc pode estar pensando como podemos utilizar a mesma varivel, i, em ambos, imprimeMultiplos e imprimeTabMult. Isto no causaria problemas quando uma das funes mudasse o valor da varivel? A resposta no, porque o i em imprimeMultiplos e o i em imprimeTabMult no so a mesma varivel. Variveis criadas dentro de uma definio de funo so locais; voc no pode acessar uma varivel local de fora da funo em que ela "mora". Isto significa que voc livre para ter mltiplas variveis com o mesmo nome, desde que elas no estejam dentro da mesma funo. O diagrama de pilha para este programa mostra que duas variveis chamadas i no so a mesma varivel. Elas podem se referir a valores diferentes e alterar o valor de uma no afeta outra. XXXfigura pg.67 O valor de i em imprimeTabMult vai de 1 a 6. No diagrama, i agora 3. Na prxima iterao do loop i ser 4. A cada iterao do loop, imprimeTabMult chama imprimeMultiplos com o valor corrente de i como argumento. O valor atribudo ao parmetro n. Dentro de imprimeMultiplos, o valor de i vai de 1 a 6. No diagrama, i agora 2. Mudar esta varivel no tem efeito sobre o valor de i em imprimeTabMult. comum e perfeitamente legal ter variveis locais diferentes com o mesmo nome. Em particular, nomes como i e j so muito usados para variveis de controle de loop. Se voc evitar utiliz-los em uma funo s porque voc j os usou em outro lugar, voc provavelmente tornar seu programa mais difcil de ler.

6.8 Mais generalizao

Como um outro exemplo de generalizao, imagine que voc precise de um programa que possa imprimir uma tabela de multiplicao de qualquer tamanho, no apenas uma tabela de seis por seis. Voc poderia adicionar um parmetro a imprimeTabMult:
def imprimeTabMult(altura): i=1 while i <= altura: imprimeMultiplos(i) i=i+1

Ns substitumos o valor 6 pelo parmetro altura. Se chamarmos imprimeTabMult com o argumento 7, ela mostra:
1 2 3 4 5 6 7 2 4 6 8 10 12 14 3 6 9 12 15 18 21 4 8 12 16 20 24 28 5 10 15 20 25 30 35 6 12 18 24 30 36 42

Isto bom, exceto que ns provavelmente quereramos que a tabela fosse quadrada - com o mesmo nmero de linhas e colunas. Para fazer isso, adicionamos outro parmetro a imprimeMultiplos para especificar quantas colunas a tabela deveria ter. S para confundir, chamamos este novo parmetro de altura, demonstrando que diferentes funes podem ter parmetros com o mesmo nome (como acontece com as variveis locais). Aqui est o programa completo:
def imprimeMultiplos(n, altura): i=1 while i <= altura: print n*i, 't', i=i+1 print

def imprimeTabMult(altura): i=1 while i <= altura: imprimeMultiplos(i, altura) i=i+1

Note que quando adicionamos um novo parmetro, temos que mudar a primeira linha da funo (o cabealho da funo), e ns tambm temos que mudar o lugar de onde a funo chamada em imprimeTabMult. Como esperado, este programa gera uma tabela quadrada de sete por sete:
1 2 3 4 5 6 7 2 4 6 8 10 12 14 3 6 9 12 15 18 21 4 8 12 16 20 24 28 5 10 15 20 25 30 35 6 12 18 24 30 36 42 7 14 21 28 35 42 49

Quando voc generaliza uma funo apropriadamente, voc muitas vezes tem um programa com capacidades que voc no planejou. Por exemplo, voc pode ter notado que, porque ab = ba, todas as entradas na tabela aparecem duas vezes. Voc poderia economizar tinta imprimindo somente a metade da tabela. Para fazer isso, voc tem que mudar apenas uma linha em imprimeTabMult. Mude:
imprimeTabMult(i, altura)

para:
imprimeTabMult(i, i)

e voc ter:
1 2 3 4 5 6 4 6 8 10 12 9 12 15 18 16 20 24 25 30 36

14

21

28

35

42

49

Como um exerccio, trace a execuo desta verso de imprimeTabMult e explique como ela funciona.

6.9 Funes

H pouco tempo mencionamos "todas as coisas para as quais as funes so boas." Agora, voc pode estar pensando que coisas exatamente so estas. Aqui esto algumas delas: Dar um nome para uma seqncia de comandos torna seu programa mais fcil de ler e de depurar. Dividir um programa longo em funes permite que voc separe partes do programa, depure-as isoladamente, e ento as componha em um todo. Funes facilitam tanto recurso quanto iterao. Funes bem projetadas so freqentemente teis para muitos programas. Uma vez que voc escreva e depure uma, voc pode reutiliz-la.

6.10 Glossrio

atribuio mltipla: Fazer mais de uma atribuio mesma varivel durante a execuo de um programa. iterao: Execuo repetida de um conjunto de comandos usando ou uma chamada a uma funo recursiva ou um loop (ou lao). loop (ou lao): Um comando ou grupo de comandos que so executados repetidamente at que uma condio de trmino seja satisfeita. loop infinito (ou lao infinito): Um loop (ou lao) cuja condio de trmino nunca satisfeita.

corpo: Os comandos dentro de um loop (ou lao). varivel de controle do loop (ou lao): Uma varivel usada como parte da condio de trmino de um loop (ou lao). tabulao: Um caractere especial que leva o cursor a se mover para a prxima marca de tabulao na linha corrente. nova linha: Um caractere especial que leva o cursor a se mover para o incio da prxima linha. cursor: Um ponteiro invisvel que marca aonde o prximo caractere ser impresso. seqncia de escape: Um caractere de escape () seguido por um ou mais caracteres imprimveis usado para designar um caractere no imprimvel. encapsulamento: Dividir um programa longo e complexo em componentes (como funes) e isolar os componentes um dos outros (usando variveis locais por exemplo). generalizao: Substituir algo desnecessariamente especfico (como um valor constante) por algo apropriadamente geral (como uma varivel ou parmetro). A generalizao torna o cdigo mais verstil, mais likely a ser reutilizado e s vezes at mais fcil de escrever. plano de desenvolvimento: Um processo para o desenvolvimento de um programa. Neste captulo, demonstramos um estilo de desenvolvimento baseado em desenvolver cdigo para fazer coisas simples e especficas e ento encapsul-lo e generaliz-lo.

6.10 Glossrio

atribuio mltipla (multiple assignment) quando mais de um valor atribudo a mesma varivel durante a execuo do programa. iterao (iteration) execuo repetida de um conjunto de comandos/instrues (statements) usando uma chamada recursiva de funo ou um lao (loop). lao (loop) um comando/instruo ou conjunto de comandos/instrues que executam repetidamente at que uma condio de interrupo seja atingida. lao infinito (infinite loop) um lao em que a condio de interrupo nunca ser atingida. corpo (body) o conjunto de comandos/instrues que pertencem a um lao. varivel de lao (loop variable) uma varivel usada como parte da condio de interrupo do lao. tabulao (tab) um carcter especial que faz com que o cursor mova-se para a prxima parada estabelecida de tabulao na linha atual. nova-linha (newline) um carcter especial que faz com que o cursor mova-se para o incio da prxima linha. cursor (cursor) um marcador invisvel que determina onde o prximo carcter var ser impresso. sequncia de escape (escape sequence) um carcter de escape () seguido por um ou mais caracteres imprimveis, usados para definir um carcter no imprimvel. encapsular (encapsulate)

quando um programa grande e complexo dividido em componentes (como funes) e estes so isolados um do outro (pelo uso de variveis locais, por exemplo). generalizar (generalize) quando algo que desnecessariamente especfico (como um valor constante) substitudo por algo apropriadamente geral (como uma varivel ou um parmetro). Generalizaes do maior versatilidade ao cdigo, maior possibilidade de reuso, e em algumas situaes at mesmo maior facilidade para escrev-lo. plano de desenvolvimento (development plan) um processo definido para desenvolvimento de um programa. Neste captulo, ns demonstramos um estilo de desenvolvimento baseado em escrever cdigo para executar tarefas simples e especficas, usando encapsulamento e generalizao.

Captulo 6: Iterao
System Message: INFO/1 (<string>, line 5432); backlink Duplicate implicit target name: "captulo 6: iterao". Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio

o 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos o 3.4 Funes matemticas o 3.5 Composio o 3.6 Adicionando novas funes o 3.7 Definies e uso o 3.8 Fluxo de execuo o 3.9 Parmetros e argumentos o 3.10 Variveis e parmetros so locais o 3.11 Diagramas da pilha o 3.12 Funes com resultados o 3.13 Glossrio Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade

5.6 Voto de confiana (Leap of faith) 5.7 Mais um exemplo 5.8 Checagem de tipos 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores
o o o o

6.1 Atribuio mltipla

Como voc talvez j tenha descoberto, permitido fazer mais de uma atribuio mesma varivel. Uma nova atribuio faz uma varivel existente referir-se a um novo valor (sem se referir mais ao antigo).:
bruno = 5 print bruno, bruno = 7 print bruno

A sada deste programa 5 7, porque na primeira vez que bruno impresso, seu valor 5 e na segunda vez, seu valor 7. A vrgula no final do primeiro comando print suprime a nova linha no final da sada, que o motivo pelo qual as duas sadas aparecem na mesma linha. Aqui est como se parece a atribuio mltipla em um diagrama de estado: XXXfigura pg.59 Com a atribuio mltipla especialmente importante distinguir entre uma operao de atribuio e um comando de igualdade. Porque Python usa o sinal de igual ( = ) para atribuio, existe a tendncia de interpretar um comando como a = b como um comando de igualdade. Ele no ! Em primeiro lugar, igualdade comutativa e atribuio no . Por exemplo, em matemtica, se a = 7 ento 7 = a. Mas em Python, o comando a = 7 permitido e 7 = a no . Alm disso, em matemtica, uma expresso de igualdade sempre verdadeira. Se a = b agora, ento, a ser sempre igual a b. Em Python, um comando de atribuio pode tornar duas variveis iguais, mas elas no tm que permanecer assim:
a=5 b = a # a e b agora so iguais b = 3 # a e b no so mais iguais

A terceira linha muda o valor de a mas no muda o valor de b, ento, elas no so mais iguais. (Em algumas linguagens de programao, um smbolo diferente usado para atribuio, como <- ou :=, para evitar confuso.) Embora a atribuio mltipla seja freqentemente til, voc deve us-la com cautela. Se o valor das variveis muda freqentemente, isto pode fazer o cdigo difcil de ler e de depurar.

6.2 O comando while

Os computadores so muito utilizados para automatizar tarefas repetitivas. Repetir tarefas idnticas ou similares sem cometer erros uma coisa que os computadores fazem bem e que as pessoas fazem poorly. Vimos dois programas, nLinhas e contagemRegressiva, que usam recursividade (recurso) para fazer a repetio, que tambm chamada iterao. Porque a iterao muito comum, Python tem vrias caractersticas para torn-la mais fcil. A primeira delas em que vamos dar uma olhada o comando while. Aqui est como fica contagemRegressiva com um comando while:
def contagemRegressiva(n): while n > 0: print n n = n-1 print "Fogo!"

Desde que removemos a chamada recursiva, esta funo no recursiva. Voc quase pode ler o comando while como se fosse Ingls. Ele significa, "Enquanto (while) n for maior do que 0, siga exibindo o valor de n e diminuindo 1 do valor de n. Quando chegar a 0, exiba a palavra Fogo!". Mais formalmente, aqui est o fluxo de execuo para um comando while: 1. Teste a condio, resultando 0 ou 1. 2. Se a condio for falsa (0), saia do comando while e continue a execuo a partir do prximo comando. 3. Se a condio for verdadeira (1), execute cada um dos comandos dentro do corpo e volte ao passo 1. O corpo consiste de todos os comandos abaixo do cabealho, com a mesma endentao. Este tipo de fluxo chamado de um loop (ou lao) porque o terceiro passo cria um "loop" ou um lao de volta ao topo. Note que se a condio for falsa na primeira vez que entrarmos no loop, os comandos dentro do loop jamais sero executados. O corpo do loop poderia alterar o valor de uma ou mais variveis de modo que eventualmente a condio se torne falsa e o loop termine. Se no for assim, o

loop se repetir para sempre, o que chamado de um loop infinito. Uma fonte de diverso sem fim para os cientistas da computao a observao de que as instrues da embalagem de shampoo, "Lave, enxge, repita" um loop infinito. No caso de contagemRegressiva, podemos provar que o loop terminar porque sabemos que o valor de n finito, e podemos ver que o valor de n diminui dentro de cada repetio (iterao) do loop, ento, eventualmente chegaremos ao 0. Em outros casos, isto no to simples de afirmar:
def sequencia(n): while n != 1: print n, if n%2 == 0: n = n/2 else: n = n*3+1 # n impar # n par

A condio para este loop n != 1, ento o loop vai continuar at que n seja 1, o que tornar a condio falsa. Dentro de cada repetio (iterao) do loop, o programa gera o valor de n e ento checa se ele par ou impar. Se ele for par, o valor de n dividido por 2. Se ele for impar, o valor substitudo por n*3+1. Por exemplo, se o valor inicial (o argumento passado para seqncia) for 3, a seqncia resultante ser 3, 10, 5, 16, 8, 4, 2, 1. J que n s vezes aumenta e s vezes diminui, no existe uma prova bvia de que n jamais venha a alcanar 1, ou de que o programa termine. Para alguns valores particulares de n, podemos provar o trmino. Por exemplo, se o valor inicial for uma potncia de dois, ento o valor de n ser par dentro de cada repetio (iterao) do loop at que alcance 1. O exemplo anterior termina com uma dessas seqncias comeando em 16. Valores especficos parte, A questo interessante se h como provarmos que este programa termina para todos os valores de n. At hoje, ningum foi capaz de provar que sim ou que no! Como um exerccio, reescreva a funo nLinhas da seo 4.9 usando iterao em vez de recurso.

6.3 Tabelas

Uma das coisas para qual os loops so bons para gerar dados tabulares. Antes que os computadores estivessem readily disponveis, as pessoas tinham que calcular logaritmos, senos, cossenos e outras funes matemticas mo. Para tornar isto mais fcil, os livros de matemtica continham longas tabelas listando os valores destas funes. Criar as tabelas era demorado e entediante, e elas tendiam a ser cheias de erros. Quando os computadores entraram em cena, uma das reaes iniciais foi "Isto timo! Podemos usar computadores para geras as tabelas, assim no haver erros." Isto veio a se tornar verdade (na maioria das vezes) mas shortsighted. Rapidamente, porm, computadores e calculadoras tornaram-se to pervasivos que as tabelas ficaram obsoletas. Bem, quase. Para algumas operaes, os computadores usam tabelas de valores para conseguir uma resposta aproximada e ento realizar clculos para melhorar a aproximao. Em alguns casos, tm havido erros nas tabelas underlying, o caso mais famoso sendo o da tabela usada pelo processador Pentium da Intel para executar a diviso em ponto-flutuante. Embora uma tabela de logaritmos no seja mais to til quanto j foi um dia, ela ainda d um bom exemplo de iterao. O seguinte programa gera uma seqncia de valores na coluna da esquerda e seus respectivos logaritmos na coluna da direita:
x = 1.0 while x < 10.0: print x, '\t', math.log(x) x = x + 1.0

A string '\t' representa um caracter de tabulao. Conforme caracteres e strings vo sendo mostrados na tela, um ponteiro invisvel chamado cursor marca aonde aparecer o prximo caractere. Depois de um comando print, o cursor normalmente vai para o incio de uma nova linha. O caractere de tabulao desloca o cursor para a direita at que ele encontre uma das marcas de tabulao. Tabulao til para fazer colunas de texto line up, como na sada do programa anterior:
1.0 0.0 2.0 0.69314718056 3.0 1.09861228867 4.0 1.38629436112

5.0 1.60943791243 6.0 1.79175946923 7.0 1.94591014906 8.0 2.07944154168 9.0 2.19722457734

Se estes valores parecem odd, lembre-se que a funo log usa a base e. J que potncias de dois so to importantes em cincia da computao, ns freqentemente temos que achar logaritmos referentes base 2. Para fazermos isso, podemos usar a seguinte frmula: System Message: WARNING/2 (<string>, line 5678) Literal block expected; none found. log2 x = loge x (6.1) loge 2 Alterando o comando de sada para:
print x, '\t', math.log(x)/math.log(2.0)

o que resultar em:


1.0 0.0 2.0 1.0 3.0 1.58496250072 4.0 2.0 5.0 2.32192809489 6.0 2.58496250072 7.0 2.80735492206 8.0 3.0 9.0 3.16992500144

Podemos ver que 1, 2, 4 e 8 so potncias de dois porque seus logaritmos na base 2 so nmeros redondos. Se precisssemos encontrar os logaritmos de outras potncias de dois, poderamos modificar o programa deste modo:
x = 1.0 while x < 100.0:

print x, '\t', math.log(x)/math.log(2.0) x = x * 2.0

Agora, em vez de somar algo a x a cada iterao do loop, o que resulta numa seqncia aritmtica, ns multiplicamos x por algo, resultando numa seqncia geomtrica. O resultado :
1.0 0.0 2.0 1.0 4.0 2.0 8.0 3.0 16.0 4.0 32.0 5.0 64.0 6.0

Por causa do caractere de tabulao entre as colunas, a posio da segunda coluna no depende do nmero de dgitos na primeira coluna. Tabelas de logaritmos podem no ser mais teis, mas para cientistas da computao, conhecer as potncias de dois ! Como um exerccio, modifique este programa de modo que ele produza as potncias de dois acima de 65.535 (ou seja, 216). Imprima e memorize-as. O caractere de barra invertida em '\t' indica o incio de uma seqncia de escape. Seqncias de escape so usadas para representar caracteres invisveis como de tabulao e de nova linha. A seqncia \n representa uma nova linha. Uma seqncia de escape pode aparecer em qualquer lugar em uma string; no exemplo, a seqncia de escape de tabulao a nica coisa dentro da string. Como voc acha que se representa uma barra invertida em uma string? Como um exerccio, escreva um nica string que produza esta sada.

6.4 Tabelas de duas dimenses (ou bi-dimensionais)

Uma tabela de duas dimenses uma tabela em que voc l o valor na interseo entre uma linha e uma coluna. Uma tabela de multiplicao um bom exemplo. Digamos que voc queira imprimir uma tabela de multiplicao de 1 a 6. Uma boa maneira de comear escrever um loop que imprima os mltiplos de 2, todos em uma linha:
i=1 while i <= 6: print 2*i, ' ', i=i+1 print

A primeira linha inicializa a varivel chamada i, a qual age como um contador ou varivel de controle do loop. Conforme o loop executado, o valor de i incrementado de 1 a 6. Quando i for 7, o loop termina. A cada repetio (iterao) do loop, mostrado o valor de 2*i, seguido de trs espaos. De novo, a vrgula no comando print suprime a nova linha. Depois que o loop se completa, o segundo comando print inicia uma nova linha. A sada do programa :
2 4 6 8 10 12

At aqui, tudo bem. O prximo passo encapsular e generalizar.

6.5 Encapsulamento e generalizao

Encapsulamento o processo de wrapping um pedao de cdigo em uma funo, permitindo que voc tire vantagem de todas as coisas para as quais as funes so boas. Voc j viu dois exemplos de encapsulamento: imprimeParidade na seo 4.5; e eDivisivel na seo 5.4 Generalizao significa tomar algo que especfico, tal como imprimir os mltiplos de 2, e torn-lo mais geral, tal como imprimir os mltiplos de qualquer

inteiro. Esta funo encapsula o loop anterior e generaliza-o para imprimir mltiplos de n:
def imprimeMultiplos(n): i=1 while i <= 6: print n*i, '\t ', i=i+1 print

Para encapsular, tudo o que tivemos que fazer foi adicionar a primeira linha, que declara o nome de uma funo e sua lista de parmetros. Para generalizar, tudo o que tivemos que fazer foi substituir o valor 2 pelo parmetro n. Se chamarmos esta funo com o argumento 2, teremos a mesma sada que antes. Com o argumento 3, a sada :
3 6 9 12 15 18

Com o argumento 4, a sada :


4 8 12 16 20 24

Agora voc provavelmente pode adivinhar como imprimir uma tabela de multiplicao - chamando imprimeMultiplos repetidamente com argumentos diferentes. De fato, podemos usar um outro loop:
i=1 while i <= 6: imprimeMultiplos(i) i=i+1

Note o quanto este loop parecido com aquele dentro de imprimeMultiplos. Tudo o que fiz foi substituir o comando print pela chamada funo. A sada deste programa uma tabela de multiplicao:
1 2 3 2 4 6 3 6 9 4 8 12 5 10 15 6 12 18

4 5 6

8 10 12

12 15 18

16 20 24

20 25 30

24 30 36

6.6 Mais encapsulamento

Para demonstrar de novo o encapsulamento, vamos pegar o cdigo do final da seo 6.5 e acondicion-lo, envolv-lo em uma funo:
def imprimeTabMult(): i=1 while i <= 6: imprimeMultiplos(i) i=i+1

Este processo um plano de desenvolvimento comum. Ns desenvolvemos cdigo escrevendo linhas de cdigo fora de qualquer funo, ou digitando-as no interpretador. Quando temos o cdigo funcionando, extramos ele e o embalamos em uma funo. Este plano de desenvolvimento particularmente til se voc no sabe, quando voc comea a escrever, como dividir o programa em funes. Esta tcnica permite a voc projetar enquanto desenvolve.

6.7 Variveis locais

Voc pode estar pensando como podemos utilizar a mesma varivel, i, em ambos, imprimeMultiplos e imprimeTabMult. Isto no causaria problemas quando uma das funes mudasse o valor da varivel? A resposta no, porque o i em imprimeMultiplos e o i em imprimeTabMult no so a mesma varivel. Variveis criadas dentro de uma definio de funo so locais; voc no pode acessar uma varivel local de fora da funo em que ela "mora". Isto significa que voc livre para ter mltiplas variveis com o mesmo nome, desde que elas no estejam dentro da mesma funo. O diagrama de pilha para este programa mostra que duas variveis chamadas

i no so a mesma varivel. Elas podem se referir a valores diferentes e alterar o valor de uma no afeta outra. XXXfigura pg.67 O valor de i em imprimeTabMult vai de 1 a 6. No diagrama, i agora 3. Na prxima iterao do loop i ser 4. A cada iterao do loop, imprimeTabMult chama imprimeMultiplos com o valor corrente de i como argumento. O valor atribudo ao parmetro n. Dentro de imprimeMultiplos, o valor de i vai de 1 a 6. No diagrama, i agora 2. Mudar esta varivel no tem efeito sobre o valor de i em imprimeTabMult. comum e perfeitamente legal ter variveis locais diferentes com o mesmo nome. Em particular, nomes como i e j so muito usados para variveis de controle de loop. Se voc evitar utiliz-los em uma funo s porque voc j os usou em outro lugar, voc provavelmente tornar seu programa mais difcil de ler.

6.8 Mais generalizao

Como um outro exemplo de generalizao, imagine que voc precise de um programa que possa imprimir uma tabela de multiplicao de qualquer tamanho, no apenas uma tabela de seis por seis. Voc poderia adicionar um parmetro a imprimeTabMult:
def imprimeTabMult(altura): i=1 while i <= altura: imprimeMultiplos(i) i=i+1

Ns substitumos o valor 6 pelo parmetro altura. Se chamarmos imprimeTabMult com o argumento 7, ela mostra:
1 2 3 4 5 2 4 6 8 10 3 6 9 12 15 4 8 12 16 20 5 10 15 20 25 6 12 18 24 30

6 7

12 14

18 21

24 28

30 35

36 42

Isto bom, exceto que ns provavelmente quereramos que a tabela fosse quadrada - com o mesmo nmero de linhas e colunas. Para fazer isso, adicionamos outro parmetro a imprimeMultiplos para especificar quantas colunas a tabela deveria ter. S para confundir, chamamos este novo parmetro de altura, demonstrando que diferentes funes podem ter parmetros com o mesmo nome (como acontece com as variveis locais). Aqui est o programa completo:
def imprimeMultiplos(n, altura): i=1 while i <= altura: print n*i, 't', i=i+1 print

def imprimeTabMult(altura): i=1 while i <= altura: imprimeMultiplos(i, altura) i=i+1

Note que quando adicionamos um novo parmetro, temos que mudar a primeira linha da funo (o cabealho da funo), e ns tambm temos que mudar o lugar de onde a funo chamada em imprimeTabMult. Como esperado, este programa gera uma tabela quadrada de sete por sete:
1 2 3 4 5 6 7 2 4 6 8 10 12 14 3 6 9 12 15 18 21 4 8 12 16 20 24 28 5 10 15 20 25 30 35 6 12 18 24 30 36 42 7 14 21 28 35 42 49

Quando voc generaliza uma funo apropriadamente, voc muitas vezes tem um programa com capacidades que voc no planejou. Por exemplo, voc pode ter notado que, porque ab = ba, todas as entradas na tabela aparecem duas vezes. Voc poderia economizar tinta imprimindo somente a metade da tabela. Para fazer isso, voc tem que mudar apenas uma linha em imprimeTabMult. Mude:
imprimeTabMult(i, altura)

para:
imprimeTabMult(i, i)

e voc ter:
1 2 3 4 5 6 7 4 6 8 10 12 14 9 12 15 18 21 16 20 24 28 25 30 35 36 42 49

Como um exerccio, trace a execuo desta verso de imprimeTabMult e explique como ela funciona.

6.9 Funes

H pouco tempo mencionamos "todas as coisas para as quais as funes so boas." Agora, voc pode estar pensando que coisas exatamente so estas. Aqui esto algumas delas: Dar um nome para uma seqncia de comandos torna seu programa mais fcil de ler e de depurar. Dividir um programa longo em funes permite que voc separe partes do programa, depure-as isoladamente, e ento as componha em um todo. Funes facilitam tanto recurso quanto iterao. Funes bem projetadas so freqentemente teis para muitos programas. Uma vez que voc escreva e depure uma, voc pode reutiliz-la.

6.10 Glossrio

atribuio mltipla: Fazer mais de uma atribuio mesma varivel durante a execuo de um programa. iterao: Execuo repetida de um conjunto de comandos usando ou uma chamada a uma funo recursiva ou um loop (ou lao). loop (ou lao): Um comando ou grupo de comandos que so executados repetidamente at que uma condio de trmino seja satisfeita. loop infinito (ou lao infinito): Um loop (ou lao) cuja condio de trmino nunca satisfeita. corpo: Os comandos dentro de um loop (ou lao). varivel de controle do loop (ou lao): Uma varivel usada como parte da condio de trmino de um loop (ou lao). tabulao: Um caractere especial que leva o cursor a se mover para a prxima marca de tabulao na linha corrente. nova linha: Um caractere especial que leva o cursor a se mover para o incio da prxima linha. cursor: Um ponteiro invisvel que marca aonde o prximo caractere ser impresso. seqncia de escape: Um caractere de escape () seguido por um ou mais caracteres imprimveis

usado para designar um caractere no imprimvel. encapsulamento: Dividir um programa longo e complexo em componentes (como funes) e isolar os componentes um dos outros (usando variveis locais por exemplo). generalizao: Substituir algo desnecessariamente especfico (como um valor constante) por algo apropriadamente geral (como uma varivel ou parmetro). A generalizao torna o cdigo mais verstil, mais likely a ser reutilizado e s vezes at mais fcil de escrever. plano de desenvolvimento: Um processo para o desenvolvimento de um programa. Neste captulo, demonstramos um estilo de desenvolvimento baseado em desenvolver cdigo para fazer coisas simples e especficas e ento encapsul-lo e generaliz-lo.

6.10 Glossrio

atribuio mltipla (multiple assignment) quando mais de um valor atribudo a mesma varivel durante a execuo do programa. iterao (iteration) execuo repetida de um conjunto de comandos/instrues (statements) usando uma chamada recursiva de funo ou um lao (loop). lao (loop) um comando/instruo ou conjunto de comandos/instrues que executam repetidamente at que uma condio de interrupo seja atingida. lao infinito (infinite loop) um lao em que a condio de interrupo nunca ser atingida. corpo (body) o conjunto de comandos/instrues que pertencem a um lao. varivel de lao (loop variable)

uma varivel usada como parte da condio de interrupo do lao. tabulao (tab) um carcter especial que faz com que o cursor mova-se para a prxima parada estabelecida de tabulao na linha atual. nova-linha (newline) um carcter especial que faz com que o cursor mova-se para o incio da prxima linha. cursor (cursor) um marcador invisvel que determina onde o prximo carcter var ser impresso. sequncia de escape (escape sequence) um carcter de escape () seguido por um ou mais caracteres imprimveis, usados para definir um carcter no imprimvel. encapsular (encapsulate) quando um programa grande e complexo dividido em componentes (como funes) e estes so isolados um do outro (pelo uso de variveis locais, por exemplo). generalizar (generalize) quando algo que desnecessariamente especfico (como um valor constante) substitudo por algo apropriadamente geral (como uma varivel ou um parmetro). Generalizaes do maior versatilidade ao cdigo, maior possibilidade de reuso, e em algumas situaes at mesmo maior facilidade para escrev-lo. plano de desenvolvimento (development plan) um processo definido para desenvolvimento de um programa. Neste captulo, ns demonstramos um estilo de desenvolvimento baseado em escrever cdigo para executar tarefas simples e especficas, usando encapsulamento e generalizao. System Message: WARNING/2 (<string>, line 6347) Block quote ends without a blank line; unexpected unindent.

Captulo 7: Strings

Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos o 3.4 Funes matemticas o 3.5 Composio o 3.6 Adicionando novas funes o 3.7 Definies e uso o 3.8 Fluxo de execuo o 3.9 Parmetros e argumentos o 3.10 Variveis e parmetros so locais o 3.11 Diagramas da pilha o 3.12 Funes com resultados o 3.13 Glossrio Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return

4.9 Recursividade 4.10 Diagramas de pilha para funes recursivas 4.11 Recursividade infinita 4.12 Entrada pelo teclado 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees
o o o o o

Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores

7.1 Um tipo de dado composto

At aqui, vimos trs diferentes tipos de dado: int, float e string. Strings so qualitativamente diferentes dos outros dois tipos porque so feitas de pedaos menores - caracteres. Tipos que consistem de pedaos menores so chamados tipos de dados compostos. Dependendo do que estejamos fazendo, pode ser que precisemos tratar um tipo de dado composto como uma coisa nica, ou pode ser que queiramos acessar suas partes. Esta ambigidade til. O operador colchete seleciona um nico caractere de uma string.:
>>> fruta = "banana" >>> letra = fruta[1] >>> print letra

A expresso fruta[1] seleciona o caractere nmero 1 de fruta. A varivel letra referencia ou refere-se ao resultado da expresso. Quando exibimos letra, temos uma surpresa:
a

A primeira letra de "banana" no a. A menos que voc seja um cientista da computao. Neste caso, voc deve entender a expresso dentro dos colchetes como um deslocamento (offset,) a partir do comeo da string, e o

deslocamento da primeira letra zero. Assim, b a 0 ("zero-sima") letra de "banana", a a 1 ("um-sima", diferente de primeira), e n a 2 ("dois-sima", diferente de segunda) letra. Para pegar a primeira letra de uma string, voc simplesmente pe 0, ou qualquer expresso que resulte o valor 0, dentro dos colchetes:
>>> letra = fruta[0] >>> print letra b

A expresso entre colchetes chamada de ndice. Um ndice especifica um membro de um conjunto ordenado, neste caso o conjunto de caracteres da string. O ndice indica aquele membro que voc quer, da seu nome. Ele pode ser qualquer expresso inteira.

7.2 Comprimento

A funo len retorna o nmero de caracteres de uma string:


>>> fruta = "banana" >>> len(fruta) 6

Para pegar a ltima letra de uma string, voc pode ficar tentado a fazer alguma coisa assim:
comprimento = len(fruta) ultima = fruta[comprimento] # ERRO!

No vai funcionar. Isto vai causar o seguinte erro em tempo de execuo (runtime error): IndexError: string index out of range. (ErroDeIndice: ndice da string fora do intervalo). A razo que no existe 6 letra em "banana". J que comeamos a contar do zero, as seis letras so numeradas de 0 a 5. Para pegar o ltimo caractere, temos que subtrair 1 de comprimento:
comprimento = len(fruta) ultima = fruta[comprimento-1]

Como alternativa, podemos usar ndices negativos, os quais contam de trs pra frente os elementos da string. A expresso fruta[-1] resulta a ltima letra, fruta[-2] resulta a penltima (a segunda de trs para frente), e assim por

diante.

7.3 Travessia e o loop for

Vrias computaes envolvem o processamento de uma string um caractere de cada vez. Muitas vezes elas comeam com o primeiro, selecionam um de cada vez, fazem alguma coisa com ele, e continuam at o fim. Este padro de processamento chamado uma travessia (traversal, com a idia de "percorrimento"). Uma maneira de codificar uma travessia com um comando while:
indice = 0 while indice < len(fruta): letra = fruta[indice] print letra indice = indice + 1

Este loop percorre a string e exibe cada letra em sua prpria linha. A condio do loop indice < len(fruta), assim, quando ndice igual ao comprimento da string, a condio se torna falsa, e o corpo do loop no executado. O ltimo caractere acessado aquele com o ndice len(fruta)-1, que vem a ser o ltimo caractere da string. Como um exerccio, escreva uma funo que tome uma string como argumento e devolva suas letras de trs para frente, uma por linha. Usar um ndice para percorrer um conjunto de valores to comum que Python oferece uma sintaxe alternativa simplificada - o loop for:
for char in fruta: print char

A cada vez atravs do loop, o prximo caractere da string atribudo varivel char. O loop continua at que no reste mais caracteres. O exemplo seguinte mostra como usar concatenao e um loop for para gerar uma srie abecedrio. "Abecedrio" se refere a uma srie ou lista na qual os elementos aparecem em ordem alfabtica. Por exemplo, no livro de Robert McCloskey's Make Way for Ducklings, os nomes dos "ducklings" so Jack, Kack, Lack, Mack, Nack, Ouack, Pack e Quack. O loop seguinte, produz como sada aqueles nomes, em ordem:
prefixos = "JKLMNOPQ"

sufixo = "ack"

for letra in prefixos: print letra + sufixo

A sada deste programa :


Jack Kack Lack Mack Nack Oack Pack Qack

Naturalmente, esta sada no est cem por cento certa porque "Ouack" e "Quack" esto escritos de maneira errada. Como um exerccio, modifique o programa para corrigir este erro.

7.4 Fatias de strings

Um segmento de uma string chamado de uma fatia. Selecionar uma fatia similar a selecionar um caractere:
>>> s = "Pedro, Paulo e Maria" >>> print s[0:5] Pedro >>> print s[7:12] Paulo >>> print s[16:21] Maria

O operador [n:m] retorna a parte da string do "n-simo" caractere ao "m-simo" caractere, incluindo o primeiro mas excluindo o ltimo. Este comportamento

contra intuitivo; ele faz mais sentido se voc imaginar os ndices apontando para os intervalos entre os caracteres, como no seguinte diagrama: XXXfigura p. Se voc omitir o primeiro ndice (antes dos dois pontos ":"), a fatia comea do incio da string. Se voc omitir o segundo ndice, a fatia vai at o final da string. Assim:
>>> fruta = "banana" >>> fruta[:3] 'ban' >>> fruta[3:] 'ana'

O que voc acha de s[:] significa?

7.5 Comparao de strings

O operador de comparao funciona com strings. Para ver se duas strings so iguais:
if palavra == "banana": print "Sim, ns no temos bananas!"

Outras operaes de comparao so teis para colocar palavras em ordem alfabtica:


if palavra < "banana": print "Sua palavra," + palavra + ", vem antes de banana." elif palavra > "banana": print "Sua palavra," + palavra + ", vem depois de banana." else: print "Sim, ns no temos bananas!"

Entretanto, voc deve atentar para o fato de que Pyhton no manipula letras maisculas e minsculas da mesma maneira que as pessoas o fazem. Todas as letras maisculas vm antes das minsculas. Como resultado:
Sua palavra, Zebra, vem antes de banana.

Uma maneira comum de resolver este problema converter as strings para um formato padro, seja todas minsculas, ou todas maisculas, antes de realizar a comparao. Um problema mais difcil fazer o programa perceber que zebras no so frutas.

7.6 Strings so imutveis

tentador usar o operador [] no lado esquerdo de uma expresso de atribuio, com a inteno de alterar um caractere em uma string. Por exemplo:
saudacao = "Al, mundo!" saudacao[0] = 'E' print saudacao # ERRO!

Em vez de produzir a sada El, Mundo!, este cdigo produz o erro em tempo de execuo (runtime error): TypeError: object doesn't support item assignment (ErroDeTipo: objeto no d suporte atribuio de item.) Strings so imutveis, o que significa que voc no pode mudar uma string que j existe. O melhor que voc pode fazer criar uma nova string que seja uma variao da original:
saudacao = "Al, mundo!" novaSaudacao = 'E' + saudao[1:] print novaSaudacao

A soluo aqui concatenar uma nova primeira letra com uma fatia de saudao. Esta operao no tem nenhum efeito sobre a string original.

7.7 Uma funo find (encontrar)

O que faz a seguinte funo?:


def find(str, ch): indice = 0 while indice < len(str):

if str[indice] == ch: return indice indice = indice + 1 return -1

Num certo sentido, find (encontrar) o oposto do operador []. Em vez de pegar um ndice e extrair o caractere correspondente, ela pega um caractere e encontra (finds) em qual ndice aquele caractere aparece. Se o caractere no encontrado, a funo retorna -1. Este o primeiro exemplo que vemos de uma instruo return dentro de um loop. Se str[indice] == ch, a funo retorna imediatamente, abandonando o loop prematuramente. Se o caractere no aparece na string, ento o programa sai do loop normalmente e retorna -1. Este padro de computao s vezes chamado de travessia "eureka", porque to logo ele encontra (find) o que est procurando, ele pode gritar "Eureka!" e parar de procurar. Como um exerccio, modifique a funo find (encontrar) de modo que ela receba um terceiro parmetro, o ndice da string por onde ela deve comear sua procura.

7.8 Iterando e contando

O programa seguinte conta o nmero e vezes que a letra a aparece em uma string:
fruta = "banana" contador = 0 for letra in fruta: if letra == 'a' contador = contador + 1 print contador

Este programa demonstra um outro padro de computao chamado de contador. A varivel contador inicializada em 0 e ento incrementada cada vez que um a encontrado. (Incrementar o mesmo que aumentar em um; o oposto de decrementar, e no tem relao com excremento, que um

substantivo.) Quando se sai do loop, contador guarda o resultado - o nmero total de a's. Como um exerccio, encapsule este cdigo em uma funo chamada contaLetras, e generalize-a de modo que possa aceitar uma string e uma letra como parmetros. Como um segundo exerccio, reescreva esta funo de modo que em vez de percorrer a string, ela use a verso com trs parmetros de find (encontrar) da seo anterior.

7.9 O mdulo string

O mdulo string contm funes teis que manipulam strings. Conforme usual, ns temos que importar o mdulo antes que possamos utiliz-lo:
>>> import string

O mdulo string inclui uma funo chamada find (encontrar) que faz a mesma coisa que a funo que escrevemos. Para cham-la, temos que especificar o nome do mdulo e o nome da funo usando a notao de ponto.:
>>> fruta = "banana" >>> indice = string.find(fruta, "a") >>> print indice 1

Este exemplo demonstra um dos benefcios dos mdulos - eles ajudam a evitar colises entre nomes de funes nativas e nomes de funes definidas pelo usurio. Usando a notao de ponto podemos especificar que verso de find (encontrar) ns queremos. De fato, string.find mais generalizada que a nossa verso. Primeiramente, ela pode encontrar substrings, no apenas caracteres:
>>> string.find("banana", "na") 2

Alm disso, ela recebe um argumento adicional que especifica o ndice pelo qual ela deve comear sua procura:
>>> string.find("banana", "na", 3) 4

Ou ela pode receber dois argumentos adicionais que especificam o intervalo de ndices:
>>> string.find("bob", "b", 1, 2) -1

Neste exemplo, a busca falha porque a letra b no aparece no intervalo entre 1 e 2 (no incluindo o 2) do ndice.

7.10 Classificao de caracteres

Muitas vezes til examinar um caractere e testar se ele maisculo ou minsculo, ou se ele um caractere ou um dgito. O mdulo string oferece vrias constantes que so teis para esses propsitos. A string string.lowercase contm todas as letras que o sistema considera como sendo minsculas. Similarmente, string.uppercase contm todas as letras maisculas. Tente o seguinte e veja o que voc obtm:
>>> print string.lowercase >>> print string.uppercase >>> print string.digits

Ns podemos usar essas constantes e find (encontrar) para classificar caracteres. Por exemplo, se find(lowercase, ch) retorna um valor outro que no -1, ento ch deve ser minsculo:
def eMinusculo(ch): return string.find(string.lowercase, ch) != -1

Como uma alternativa, podemos tirar vantagem do operador in, que determina se um caractere aparece em uma string:
def eMinusculo(ch): return ch in string.lowercase

Ainda, como uma outra alternativa, podemos usar o operador de comparao:


def eMinusculo(ch): return 'a' <= ch <= 'z'

Se ch estiver entre a e z, ele deve ser uma letra minscula. Como um exerccio, discuta que verso de eMinusculo voc acha que ser a mais rpida. Voc pode pensar em outras razes alm da velocidade para preferir uma em vez de outra? Outra constante definida no mdulo string pode te surpreender quando voc executar um print sobre ela:
>>> print string.whitespace

Caracteres de espaamento (ou espaos em branco) movem o cursor sem "imprimir" qualquer coisa. Eles criam os espaos em branco entre os caracteres visveis (pelo menos numa folha de papel branco). A string constante string.whitespace contm todos os caracteres de espaamento, incluindo espao, tabulao (\t) e nova linha (\n). Existem outras funes teis no mdulo string, mas este livro no pretende ser um manual de referncia. Por outro lado, Python Library Reference exatamente isto. Em meio a uma abundante documentao, ele est disponvel no site da web do Python, www.python.org.

7.11 Glossrio

tipo de dado composto (compound data type) Um tipo de dado no qual o valor consiste de componentes, ou elementos, que so eles mesmos valores. travessia (traverse) Iterar atravs dos elementos de um conjunto, realizando uma operao similar em cada um deles. ndice (index) Uma varivel ou valor usados para selecionar um membro de um conjunto ordenado, como um caractere em uma string. fatia (slice) Uma parte de uma string especificada por um intervalo de ndices. mutvel (mutable)

Um tipo de dado composto a cujos elementos podem ser atribudos novos valores. contador (counter) Uma varivel utilizada para contar alguma coisa, usualmente inicializada em zero e ento incrementada. incrementar (increment) aumentar o valor de uma varivel em 1. decrementar (decrement) diminuir o valor de uma varivel em 1. espaamento (whitespace) Qualquer um dos caracteres que move o cursor sem imprimir caracteres visveis. A constante string.whitespace contm todos os caracteres de espaamento.

7.11 Glossrio2

tipo de dado composto (compound data type) Um tipo de dado em que os valores so compostos de componentes, ou elementos, que so seus prprios valores. atravessar (traverse) Iterar atravs dos elementos definidos, executando uma operao similar em cada. ndice (index) Uma varivel ou valor usado para selecionar um membro de uma definio ordenada, como um caractere de uma string. fatia (slice) Uma parte da string especificada por um intervalo de ndice. mutvel (mutable) Um tipo de dado composto do qual elementos podem atribuir novos valores.

contador (counter) Uma varivel usada para contar alguma coisa, geralmente iniciada em zero e incrementada. incremento (increment) Para aumentar o valor da varivel. decremento (decrement) Para dimiuir o valor da varivel. espao em branco (whitespace) Qualquer caractere que move o cursor sem imprimir caracteres visveis. A constante string.whitespace contm todos os caracteres de espao em branco.

Captulo 7: Strings
System Message: INFO/1 (<string>, line 7050); backlink Duplicate implicit target name: "captulo 7: strings". Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio

o 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos o 3.4 Funes matemticas o 3.5 Composio o 3.6 Adicionando novas funes o 3.7 Definies e uso o 3.8 Fluxo de execuo o 3.9 Parmetros e argumentos o 3.10 Variveis e parmetros so locais o 3.11 Diagramas da pilha o 3.12 Funes com resultados o 3.13 Glossrio Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade

5.6 Voto de confiana (Leap of faith) 5.7 Mais um exemplo 5.8 Checagem de tipos 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores
o o o o

7.1 Um tipo de dado composto

At aqui, vimos trs diferentes tipos de dado: int, float e string. Strings so qualitativamente diferentes dos outros dois tipos porque so feitas de pedaos menores - caracteres. Tipos que consistem de pedaos menores so chamados tipos de dados compostos. Dependendo do que estejamos fazendo, pode ser que precisemos tratar um tipo de dado composto como uma coisa nica, ou pode ser que queiramos acessar suas partes. Esta ambigidade til. O operador colchete seleciona um nico caractere de uma string.:
>>> fruta = "banana" >>> letra = fruta[1] >>> print letra

A expresso fruta[1] seleciona o caractere nmero 1 de fruta. A varivel letra referencia ou refere-se ao resultado da expresso. Quando exibimos letra, temos uma surpresa:
a

A primeira letra de "banana" no a. A menos que voc seja um cientista da computao. Neste caso, voc deve entender a expresso dentro dos colchetes como um deslocamento (offset,) a partir do comeo da string, e o deslocamento da primeira letra zero. Assim, b a 0 ("zero-sima") letra de "banana", a a 1 ("um-sima", diferente de primeira), e n a 2 ("dois-sima", diferente de segunda) letra. Para pegar a primeira letra de uma string, voc simplesmente pe 0, ou qualquer expresso que resulte o valor 0, dentro dos colchetes:
>>> letra = fruta[0] >>> print letra b

A expresso entre colchetes chamada de ndice. Um ndice especifica um membro de um conjunto ordenado, neste caso o conjunto de caracteres da string. O ndice indica aquele membro que voc quer, da seu nome. Ele pode ser qualquer expresso inteira.

7.2 Comprimento

A funo len retorna o nmero de caracteres de uma string:


>>> fruta = "banana" >>> len(fruta) 6

Para pegar a ltima letra de uma string, voc pode ficar tentado a fazer alguma coisa assim:
comprimento = len(fruta) ultima = fruta[comprimento] # ERRO!

No vai funcionar. Isto vai causar o seguinte erro em tempo de execuo (runtime error): IndexError: string index out of range. (ErroDeIndice: ndice da string fora do intervalo). A razo que no existe 6 letra em "banana". J que comeamos a contar do zero, as seis letras so numeradas de 0 a 5. Para pegar o ltimo caractere, temos que subtrair 1 de comprimento:
comprimento = len(fruta) ultima = fruta[comprimento-1]

Como alternativa, podemos usar ndices negativos, os quais contam de trs pra frente os elementos da string. A expresso fruta[-1] resulta a ltima letra, fruta[-2] resulta a penltima (a segunda de trs para frente), e assim por diante.

7.3 Travessia e o loop for

Vrias computaes envolvem o processamento de uma string um caractere de cada vez. Muitas vezes elas comeam com o primeiro, selecionam um de cada vez, fazem alguma coisa com ele, e continuam at o fim. Este padro de processamento chamado uma travessia (traversal, com a idia de "percorrimento"). Uma maneira de codificar uma travessia com um comando while:
indice = 0 while indice < len(fruta): letra = fruta[indice] print letra indice = indice + 1

Este loop percorre a string e exibe cada letra em sua prpria linha. A condio do loop indice < len(fruta), assim, quando ndice igual ao comprimento da string, a condio se torna falsa, e o corpo do loop no executado. O ltimo caractere acessado aquele com o ndice len(fruta)-1, que vem a ser o ltimo caractere da string. Como um exerccio, escreva uma funo que tome uma string como argumento e devolva suas letras de trs para frente, uma por linha. Usar um ndice para percorrer um conjunto de valores to comum que Python oferece uma sintaxe alternativa simplificada - o loop for:
for char in fruta: print char

A cada vez atravs do loop, o prximo caractere da string atribudo varivel char. O loop continua at que no reste mais caracteres. O exemplo seguinte mostra como usar concatenao e um loop for para gerar uma srie abecedrio. "Abecedrio" se refere a uma srie ou lista na qual os elementos aparecem em ordem alfabtica. Por exemplo, no livro de Robert McCloskey's Make Way for Ducklings, os nomes dos "ducklings" so Jack, Kack, Lack, Mack, Nack, Ouack, Pack e Quack. O loop seguinte, produz como sada aqueles nomes, em ordem:
prefixos = "JKLMNOPQ" sufixo = "ack"

for letra in prefixos: print letra + sufixo

A sada deste programa :


Jack Kack Lack Mack Nack Oack Pack Qack

Naturalmente, esta sada no est cem por cento certa porque "Ouack" e "Quack" esto escritos de maneira errada. Como um exerccio, modifique o programa para corrigir este erro.

7.4 Fatias de strings

Um segmento de uma string chamado de uma fatia. Selecionar uma fatia similar a selecionar um caractere:
>>> s = "Pedro, Paulo e Maria" >>> print s[0:5] Pedro >>> print s[7:12] Paulo >>> print s[16:21] Maria

O operador [n:m] retorna a parte da string do "n-simo" caractere ao "m-simo" caractere, incluindo o primeiro mas excluindo o ltimo. Este comportamento contra intuitivo; ele faz mais sentido se voc imaginar os ndices apontando para os intervalos entre os caracteres, como no seguinte diagrama: XXXfigura p. Se voc omitir o primeiro ndice (antes dos dois pontos ":"), a fatia comea do incio da string. Se voc omitir o segundo ndice, a fatia vai at o final da string. Assim:
>>> fruta = "banana" >>> fruta[:3] 'ban' >>> fruta[3:] 'ana'

O que voc acha de s[:] significa?

7.5 Comparao de strings

O operador de comparao funciona com strings. Para ver se duas strings so iguais:
if palavra == "banana": print "Sim, ns no temos bananas!"

Outras operaes de comparao so teis para colocar palavras em ordem alfabtica:


if palavra < "banana": print "Sua palavra," + palavra + ", vem antes de banana." elif palavra > "banana": print "Sua palavra," + palavra + ", vem depois de banana." else: print "Sim, ns no temos bananas!"

Entretanto, voc deve atentar para o fato de que Pyhton no manipula letras maisculas e minsculas da mesma maneira que as pessoas o fazem. Todas as letras maisculas vm antes das minsculas. Como resultado:
Sua palavra, Zebra, vem antes de banana.

Uma maneira comum de resolver este problema converter as strings para um formato padro, seja todas minsculas, ou todas maisculas, antes de realizar a comparao. Um problema mais difcil fazer o programa perceber que zebras no so frutas.

7.6 Strings so imutveis

tentador usar o operador [] no lado esquerdo de uma expresso de atribuio, com a inteno de alterar um caractere em uma string. Por exemplo:
saudacao = "Al, mundo!" saudacao[0] = 'E' print saudacao # ERRO!

Em vez de produzir a sada El, Mundo!, este cdigo produz o erro em tempo de execuo (runtime error): TypeError: object doesn't support item assignment (ErroDeTipo: objeto no d suporte atribuio de item.) Strings so imutveis, o que significa que voc no pode mudar uma string que j existe. O melhor que voc pode fazer criar uma nova string que seja uma variao da original:
saudacao = "Al, mundo!" novaSaudacao = 'E' + saudao[1:] print novaSaudacao

A soluo aqui concatenar uma nova primeira letra com uma fatia de saudao. Esta operao no tem nenhum efeito sobre a string original.

7.7 Uma funo find (encontrar)

O que faz a seguinte funo?:


def find(str, ch): indice = 0 while indice < len(str): if str[indice] == ch: return indice indice = indice + 1 return -1

Num certo sentido, find (encontrar) o oposto do operador []. Em vez de pegar um ndice e extrair o caractere correspondente, ela pega um caractere e encontra (finds) em qual ndice aquele caractere aparece. Se o caractere no encontrado, a funo retorna -1. Este o primeiro exemplo que vemos de uma instruo return dentro de um loop. Se str[indice] == ch, a funo retorna imediatamente, abandonando o loop prematuramente. Se o caractere no aparece na string, ento o programa sai do loop normalmente e retorna -1. Este padro de computao s vezes chamado de travessia "eureka",

porque to logo ele encontra (find) o que est procurando, ele pode gritar "Eureka!" e parar de procurar. Como um exerccio, modifique a funo find (encontrar) de modo que ela receba um terceiro parmetro, o ndice da string por onde ela deve comear sua procura.

7.8 Iterando e contando

O programa seguinte conta o nmero e vezes que a letra a aparece em uma string:
fruta = "banana" contador = 0 for letra in fruta: if letra == 'a' contador = contador + 1 print contador

Este programa demonstra um outro padro de computao chamado de contador. A varivel contador inicializada em 0 e ento incrementada cada vez que um a encontrado. (Incrementar o mesmo que aumentar em um; o oposto de decrementar, e no tem relao com excremento, que um substantivo.) Quando se sai do loop, contador guarda o resultado - o nmero total de a's. Como um exerccio, encapsule este cdigo em uma funo chamada contaLetras, e generalize-a de modo que possa aceitar uma string e uma letra como parmetros. Como um segundo exerccio, reescreva esta funo de modo que em vez de percorrer a string, ela use a verso com trs parmetros de find (encontrar) da seo anterior.

7.9 O mdulo string

O mdulo string contm funes teis que manipulam strings. Conforme usual, ns temos que importar o mdulo antes que possamos utiliz-lo:
>>> import string

O mdulo string inclui uma funo chamada find (encontrar) que faz a mesma coisa que a funo que escrevemos. Para cham-la, temos que especificar o nome do mdulo e o nome da funo usando a notao de ponto.:
>>> fruta = "banana" >>> indice = string.find(fruta, "a") >>> print indice 1

Este exemplo demonstra um dos benefcios dos mdulos - eles ajudam a evitar colises entre nomes de funes nativas e nomes de funes definidas pelo usurio. Usando a notao de ponto podemos especificar que verso de find (encontrar) ns queremos. De fato, string.find mais generalizada que a nossa verso. Primeiramente, ela pode encontrar substrings, no apenas caracteres:
>>> string.find("banana", "na") 2

Alm disso, ela recebe um argumento adicional que especifica o ndice pelo qual ela deve comear sua procura:
>>> string.find("banana", "na", 3) 4

Ou ela pode receber dois argumentos adicionais que especificam o intervalo de ndices:
>>> string.find("bob", "b", 1, 2) -1

Neste exemplo, a busca falha porque a letra b no aparece no intervalo entre 1 e 2 (no incluindo o 2) do ndice.

7.10 Classificao de caracteres

Muitas vezes til examinar um caractere e testar se ele maisculo ou minsculo, ou se ele um caractere ou um dgito. O mdulo string oferece vrias constantes que so teis para esses propsitos.

A string string.lowercase contm todas as letras que o sistema considera como sendo minsculas. Similarmente, string.uppercase contm todas as letras maisculas. Tente o seguinte e veja o que voc obtm:
>>> print string.lowercase >>> print string.uppercase >>> print string.digits

Ns podemos usar essas constantes e find (encontrar) para classificar caracteres. Por exemplo, se find(lowercase, ch) retorna um valor outro que no -1, ento ch deve ser minsculo:
def eMinusculo(ch): return string.find(string.lowercase, ch) != -1

Como uma alternativa, podemos tirar vantagem do operador in, que determina se um caractere aparece em uma string:
def eMinusculo(ch): return ch in string.lowercase

Ainda, como uma outra alternativa, podemos usar o operador de comparao:


def eMinusculo(ch): return 'a' <= ch <= 'z'

Se ch estiver entre a e z, ele deve ser uma letra minscula. Como um exerccio, discuta que verso de eMinusculo voc acha que ser a mais rpida. Voc pode pensar em outras razes alm da velocidade para preferir uma em vez de outra? Outra constante definida no mdulo string pode te surpreender quando voc executar um print sobre ela:
>>> print string.whitespace

Caracteres de espaamento (ou espaos em branco) movem o cursor sem "imprimir" qualquer coisa. Eles criam os espaos em branco entre os caracteres visveis (pelo menos numa folha de papel branco). A string constante string.whitespace contm todos os caracteres de espaamento, incluindo espao, tabulao (\t) e nova linha (\n). Existem outras funes teis no mdulo string, mas este livro no pretende ser um manual de referncia. Por outro lado, Python Library Reference exatamente isto. Em meio a uma abundante documentao, ele est

disponvel no site da web do Python, www.python.org.

7.11 Glossrio

tipo de dado composto (compound data type) Um tipo de dado no qual o valor consiste de componentes, ou elementos, que so eles mesmos valores. travessia (traverse) Iterar atravs dos elementos de um conjunto, realizando uma operao similar em cada um deles. ndice (index) Uma varivel ou valor usados para selecionar um membro de um conjunto ordenado, como um caractere em uma string. fatia (slice) Uma parte de uma string especificada por um intervalo de ndices. mutvel (mutable) Um tipo de dado composto a cujos elementos podem ser atribudos novos valores. contador (counter) Uma varivel utilizada para contar alguma coisa, usualmente inicializada em zero e ento incrementada. incrementar (increment) aumentar o valor de uma varivel em 1. decrementar (decrement) diminuir o valor de uma varivel em 1. espaamento (whitespace) Qualquer um dos caracteres que move o cursor sem imprimir caracteres visveis. A constante string.whitespace contm todos os caracteres de espaamento.

7.11 Glossrio2

tipo de dado composto (compound data type) Um tipo de dado em que os valores so compostos de componentes, ou elementos, que so seus prprios valores. atravessar (traverse) Iterar atravs dos elementos definidos, executando uma operao similar em cada. ndice (index) Uma varivel ou valor usado para selecionar um membro de uma definio ordenada, como um caractere de uma string. fatia (slice) Uma parte da string especificada por um intervalo de ndice. mutvel (mutable) Um tipo de dado composto do qual elementos podem atribuir novos valores. contador (counter) Uma varivel usada para contar alguma coisa, geralmente iniciada em zero e incrementada. incremento (increment) Para aumentar o valor da varivel. decremento (decrement) Para dimiuir o valor da varivel. espao em branco (whitespace) Qualquer caractere que move o cursor sem imprimir caracteres visveis. A constante string.whitespace contm todos os caracteres de espao em branco.

Captulo 8: Listas

Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos o 3.4 Funes matemticas o 3.5 Composio o 3.6 Adicionando novas funes o 3.7 Definies e uso o 3.8 Fluxo de execuo o 3.9 Parmetros e argumentos o 3.10 Variveis e parmetros so locais o 3.11 Diagramas da pilha o 3.12 Funes com resultados o 3.13 Glossrio Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return

4.9 Recursividade 4.10 Diagramas de pilha para funes recursivas 4.11 Recursividade infinita 4.12 Entrada pelo teclado 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees
o o o o o

Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores Uma lista um conjunto ordenado de valores, onde cada valor identificado por um ndice. Os valores que compem uma lista so chamados elementos. Listas so similares a strings, que so conjuntos ordenados de caracteres, com a diferena que os elementos de uma lista podem possuir qualquer tipo. Listas e strings ? e outras coisas que se comportam como conjuntos ordenados ? so chamados seqncias.

8.1 Valores da lista

Existem vrias maneiras de criar uma nova lista; a mais simples envolver os elementos em colchetes ([ e ]):
>>> [10, 20, 30, 40] >>> [?spam?, ?bungee?, ?swallow?]

O primeiro exemplo uma lista de quatro inteiros. O segundo uma lista de trs strings. Os elementos de uma lista no necessitam ser do mesmo tipo. A lista a seguir contm uma string, um valor float, um valor inteiro, e mirabile dictu uma outra lista:
>>> [?alo?, 2.0, 5, [10,20]]

Uma lista dentro de outra lista dita estar aninhada. Listas que contm inteiros consecutivos so comuns, ento Python fornece uma maneira simples de cri-los:

>>> range(1,5)

[1, 2, 3, 4] A funo range pega dois argumentos e devolve uma lista que contm todos os inteiros do primeiro at o segundo, incluindo o primeiro mas no incluindo o segundo! Existem outras formas de range. Com um argumento simples, ela cria uma lista que inicia em 0:
>>> range(10)

[0,1, 2, 3, 4, 5, 6, 7, 8, 9] Se existe um terceiro argumento, ele especifica o espao entre os valores sucessivos, que chamado de tamanho do passo. Este exemplo conta de 1 at 10 em passos de 2:
>>> range(1, 10, 2)

[1, 3, 5, 7, 9] Finalmente, existe uma lista especial que no contm elementos. Ela chamada lista vazia, e sua notao []. Com todas estas formas de criar listas, seria decepcionante se no pudssemos atribuir valores de listas a variveis ou passar listas como parmetros a funes. Ns podemos.
>>> vocabulario = [?melhorar?, ?castigar?, ?defenestrar?] >>> numeros = [17, 123] >>> vazio = [] >>> print vocabulario, numeros, vazio

[?melhorar?, ?castigar?, ?defenestrar?] [17, 123] []

8.2 Acessado elementos

A sintaxe para acessar os elementos de uma lista a mesma que a sintaxe para acessar os caracteres de uma string ? o operator colchete ([]). A expresso dentro dos colchetes especifica o ndice. Lembre-se que os ndices iniciam em 0:
>>> print numeros[0] >>> numeros[1]= 5

O operador colchete pode aparecer em qualquer lugar em uma expresso. Quando ele aparece no lado esquerdo de uma atribuio, ele modifica um dos elementos em uma lista, de forma que o um-simo elemento de numeros, que era 123, agora 5. Qualquer expresso inteira pode ser utilizada como um ndice:
>>> numeros[3-2]

5
>>> numeros[1.0]

TypeError: sequence index must be integer Se voc tentar ler ou escrever um elemento que no existe, voc recebe um erro de tempo de execuo (runtime error):
>>> numeros[2]=5

IndexError: list assignment index out of range Se um ndice possui um valor negativo, ele conta ao contrrio a partir do final da lista:
>>> numeros[-1]

5
>>> numeros[-2]

17
>>> numeros[-3]

IndexError: list index out of range numeros[-1] o ltimo elemento da lista, numeros[-2] o penltimo e numeros[-3] no existe. comum utilizar uma varivel de lao como um ndice da lista.
>>> cavaleiros = [?guerra?, ?fome?, ?peste?, ?morte?]

i=0 while i < 4: print cavaleiros[i]

i=i+1 Este lao while conta de 0 at 4. Quando a varivel do lao i 4, a condio falha e o lao se encerra. Desta forma o corpo do lao executado somente quando i 0, 1, 2 e 3. Em cada vez dentro do lao, a varivel i utilizada como um ndice para a lista, exibindo o i-simo elemento. Este padro de computao chamado de percurso na lista.

8.3 Comprimento da lista

A funo len devolve o comprimento de uma lista. uma boa idia utilizar este valor como o limite superior de um lao ao invs de uma constante. Desta forma, se o tamanho da lista mudar, voc no precisar ir atravs de todo o programa modificando todos os laos; eles funcionaro corretamente para qualquer tamanho de lista:
>>> cavaleiros = [?guerra?, ?fome?, ?peste?, ?morte?]

i=0 while i < len(cavaleiros): print cavaleiros[i] i=i+1 A ltima vez que o corpo do lao executado, i len(cavaleiros) ? 1, que o ndice do ltimo elemento. Quando i igual a len(cavaleiros), a condio falha e o corpo no executado, o que uma boa coisa, porque len(cavaleiros) no um ndice legal. Embora uma lista possa conter uma outra lista, a lista aninhada ainda conta como um elemento simples. O comprimento desta lista quatro:
>>> [`spam!?, 1, [`Brie`, `Roquefort`, `Pol l Veq`], [1, ,2 3]]

Como um exerccio, escreva um lao que percorra a lista anterior e exiba o comprimento de cada elemento. O que acontece se voc manda um inteiro para ``len``?

8.4 Membros de uma lista

in um operador lgico que testa se um elemento membro de uma seqncia. Ns o utilizamos na Seo 7.10 com strings, mas ele tambm funciona com listas e outras seqncias:
>>> cavaleiros = [?guerra?, ?fome?, ?peste?, ?morte?] >>> ?peste? in cavaleiros

1
>>> ?depravao? in cavaleiros

0 Uma vez que ?peste? um membro da lista cavaleiros, o operador in devolve verdadeiro. Uma vez que depravao no est na lista, in devolve falso. Podemos utilizar tambm o not em combinao com o in para testar se um elemento no um membro de uma lista:
>>> ``depravao`` not in cavaleiros

8.5 Listas e laos for

O lao for que vimos na Seo 7.3 tambm funciona com listas. A sintaxe generalizada de um lao for :
>>> for VARIABLE in LIST:

BODY Esta declarao equivalente a:


>>> i = 0

while i < len(LIST): VARIABLE = LIST[i] BODY

i=i+1 O lao for mais conciso porque podemos eliminar a varivel do lao, i. Aqui est o lao anterior escrito com um`lao for:
>>> for cavaleiro in cavaleiros:

print cavaleiro Quase se l como Portugus: "For (para cada) cavaleiro in (na lista de) cavaleiros, print (imprima o nome do) cavaleiro." Qualquer expresso de lista pode ser utilizada num lao for:
>>> for numero in range(20):

if numero % 2 == 0: print numero


>>> for fruta in ["banana", "abacaxi", "laranja"]:

print "Eu gosto de comer " + fruta + "s!" O primeiro exemplo exibe todos os nmeros pares entre zero e dezenove. O segundo exemplo expressa o entusiasmo por vrias frutas.

8.6 Operaes em listas

O operador + concatena listas:


>>> a = [1, 2, 3] >>> b = [4, 5, 6] >>> c = a + b >>> print c

[1, 2, 3, 4, 5, 6] Similarmente, o operador * repete uma lista um nmero dado de vezes:


>>> [0] * 4

[0, 0, 0, 0]
>>> [1, 2, 3] * 3

[1, 2, 3, 1, 2, 3, 1, 2, 3] O primeiro exemplo repete [0] quatro vezes. O segundo exemplo repete a lista

[1, 2, 3] trs vezes.

8.7 Fatiamento de listas

A operao de fatiamento que vimos na Seo 7.4 tambm funciona sobre listas:
>>> lista = ['a', 'b', 'c', 'd', 'e', 'f'] >>> lista[1:3]

['b', 'c']
>>> lista[:4]

['a', 'b', 'c', 'd']


>>> lista[3:]

['d', 'e', 'f']


>>> lista[:]

['a', 'b', 'c', 'd', 'e', 'f']

8.8 Listas so mutveis

Diferente das strings, as listas so mutveis, o que significa que podemos modificar seus elementos. Utilizando o operador colchete no lado esquerdo de uma atribuio, podemos atualizar um de seus elementos:
>>> fruta = ["banana", "abacaxi", "laranja"] >>> fruta[0] = "abacate" >>> fruta[-1] = "tangerina" >>> print fruta

['abacate', 'abacaxi', 'tangerina'] Com o operador de fatiamento podemos atualizar vrios elementos de uma vez:
>>> lista = ['a', 'b', 'c', 'd', 'e', 'f'] >>> lista[1:3] = ['x', 'y'] >>> print lista

['a', 'x', 'y', 'd', 'e', 'f'] Tambm podemos remover elementos de uma lista atribuindo a lista vazia a eles:
>>> lista = ['a', 'b', 'c', 'd', 'e', 'f'] >>> lista[1:3] = [] >>> print lista

['a', 'd', 'e', 'f'] E podemos adicionar elementos a uma lista enfiando-os numa fatia vazia na posio desejada:
>>> lista = ['a', 'd', 'f'] >>> lista[1:1] = ['b', 'c'] >>> print lista

['a', 'b', 'c', 'd', 'f']


>>> lista[4:4] = ['e'] >>> print lista

['a', 'b', 'c', 'd', 'e', 'f']

8.9 Remoo em lista

Utilizando fatias para remover elementos pode ser complicado, e desta forma propenso a erro. Python fornece uma alternativa que mais legvel. del remove um elemento de uma lista:
>>> a = ['um', 'dois', 'tres'] >>> del a[1] >>> a

['um', 'tres'] Como voc deveria esperar, del trata valores negativos e causa erros de tempo de execuo se o ndice estiver fora da faixa. Voc tambm pode utilizar uma faixa como um ndice para del:
>>> lista = ['a', 'b', 'c', 'd', 'e', 'f'] >>> del lista[1:5] >>> print lista

['a', 'f'] Como de costume, fatias selecionam todos os elementos at, mas no incluindo, o segundo ndice.

8.10 Ojetos e valores

Se executamos estas declaraes de atribuio,


>>> a = "banana" >>> b = "banana"

sabemos que a e b se referem a uma string com as letras banana. Mas no podemos dizer se elas apontam para a mesma string. Existem dois possveis estados: ** XXX figura 1 ** Em um caso, a e b se referem a duas coisas diferentes que possuem o mesmo valor. No segundo caso, elas se referem mesma coisa. Estas "coisas" possume nomes - elas so chamadas objetos. Um objeto algo ao qual uma varivel pode se referenciar. Todo objeto possui um identificador nico, que podemos obter com a funo id. Exibindo o identificador de a e b, podemos dizer se elas se referem ao mesmo objeto.
>>> id(a)

135044008
>>> id(b)

135044008 De fato, obtivemos o mesmo identificador duas vezes, o que significa que Python criou apenas uma string, e tanto a quanto b se referem a ela. Interessantemente, listas se comportam de forma diferente. Quando criamos duas listas, obtemos dois objetos:
>>> a = [1, 2, 3] >>> b = [1, 2, 3] >>> id(a)

135045528
>>> id(b)

135041704 Ento o diagrama de estado se parece com isto: ** XXX figura 2 ** a e b possuem o mesmo valor mas no se referem ao mesmo objeto.

8.11 Apelidos

Uma vez que variveis se referem a objetos, se atribuimos uma varivel a uma outra, ambas as variveis se referem ao mesmo objeto:
>>> a = [1, 2, 3] >>> b = a

Neste caso, o diagrama de estado se parece com isto: ** XXX figura 3 ** Uma vez que a lista possui dois nomes diferentes, a e b, dizemos que ela est "apelidada" (aliased). Mudanas feitas em um apelido afetam o outro nome:
>>> b[0] = 5 >>> print a

[5, 2, 3] Embora este comportamento possa ser til, ele s vezes inesperado e indesejado. Em geral, mais seguro evitar os apelidos quando voc est trabalhando com objetos mutveis. claro, para objetos imutveis, no h problema. por isto que Python livre para apelidar cadeias de caracteres quando v uma oportunidade de economizar.

8.12 Clonando listas

Se queremos modificar uma lista e tambm manter uma cpia da original,

preciamos ter condies de fazer uma cpia da prpria lista, no apenas uma referncia. Este processo algumas vezes chamado clonagem, para evitar a ambigidade da palavra "cpia". A maneira mas fcil de clonar uma lista utilizar o operador de fatia:
>>> a = [1, 2, 3] >>> b = a[:] >>> print b

[1, 2, 3] Pegar qualquer fatia de a cria uma nova lista. Neste caso acontece da fatia consistir da lista inteira. Agora estamos livres para fazer alteraes a b sem nos preocuparmos com``a``:
>>> b[0] = 5 >>> print a

[1, 2, 3] Como exerccio, desenhe um diagrama de estado para``a`` e ``b`` antes e depois desta mudana.

8.13 Lista como parmetro

Passar uma lista como um argumento passa realmente uma referncia lista, no uma cpia da lista. Por exemplo, a funo cabea pega uma lista como parmetro e devolve o primeiro elemento:
>>> def cabeca(lista):

return lista[0] Aqui est a maneira como ela utilizada:


>>> numeros = [1, 2, 3] >>> cabeca(numeros)

1 O parmetro lista e a varivel numeros so apelidos para o mesmo objeto. O diagrama de estado se parece com isto: ** XXX figura 4 **

Uma vez que o objeto compartilhado pelos dois quadros, o desenhamos entre eles. Se a funo modifica um parmetro da lista, a funo chamadora v a mudana. Por exemplo, removeCabeca remove o primeiro elemento da lista:
>>> def removecabeca(lista):

del lista[0] Aqui est a maneira como ela utilizada:


>>> numeros = [1, 2, 3] >>> removeCabeca(numeros) >>> print numeros

[2, 3] Se uma funo devolve uma lista, ela devolve uma referncia lista. Por exemplo, cauda devolve uma lista que contm todos menos o primeiro elemento de uma determinada lista:
>>> def cauda(lista):

return lista[1:] Aqui est a maneira como ela utilizada:


>>> numeros = [1, 2, 3] >>> resto = cauda(numeros) >>> print resto

[2, 3] Uma vez que o valor de retorno foi criado com o operador de fatia, ele uma nova lista. A criao de resto, e qualquer alterao subseqente a resto, no tem efeito sobre numeros.

8.14 Lista aninhadas

Uma lista aninhada uma lista que aparece como um elemento de uma outra lista. Nesta lista, o terceiro elemento uma lista aninhada:
>>> lista = ["alo", 2.0, 5, [10, 20]]

Se exibimos lista[3], obtemos [10, 20]. Para extrairmos um elemento de uma lista aninhada, podemos agir em duas etapas:
>>> elt = lista[3]

>>> elt[0]

10 Ou podemos combin-las:
>>> lista[3][1]

20 Os operadores colchete avaliam da esquerda para a direita, ento a expresso pega o terceiro elemento de lista e extrai o primeiro elemento dela.

8.15 Matrizes

Listas aninhadas so freqentemente utilizadas para representar matrizes. Por exemplo, a matriz: XXX figura matriz 1 poderia ser representada como:
>>> matriz = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

matriz uma lista com trs elementos, onde cada elemento uma linha da matriz. Podemos selecionar uma linha inteira da matriz da maneira habitual:
>>> matriz[1]

[4, 5, 6] Ou podemos extrair um nico elemento da matriz utilinado a forma de duplo ndice:
>>> matriz[1][1]

5 O primeiro ndice seleciona a linha,e o segundo ndice seleciona a coluna. Embora esta maneira de representar matrizes seja comum, ela no a nica possibilidade. Uma pequena variao utilizar uma lista de colunas ao invs de uma lista de linhas. Mais adiante veremos uma alternativa mais radical utilizando um dicionrio.

8.16 Strings e listas

Duas das mais teis funes no mdulo string envolvem listas de strings. A funo split (separar) quebra uma string em uma lista de palavras. Por padro, qualquer nmero de caracteres espao em branco considerado um limite de uma palavra:
>>> import string >>> poesia = "O orvalho no carvalho..." >>> string.split(poesia)

['O', 'orvalho', 'no', 'carvalho...'] Um argumento opcional chamado um delimitador pode ser utilizado para especificar qual caracter utilizar como limites da palavra. O exemplo a seguir utiliza a string va
>>> string.split(poesia, 'va')

['O or', 'lho no car', 'lho...'] Perceba que o delimitador no aparece na lista. A funo join (juntar) o inverso de split. Ela pega uma lista de strings e concatena os elementos com um espao entre cada par:
>>> lista = ['O', 'orvalho', 'no', 'carvalho...'] >>> string.join(lista)

'O orvalho no carvalho...' Como split, join recebe um delimitador que inserido entre os elementos:
>>> string.join(lista, '_')

'O_orvalho_no_carvalho...' Como um execcio, descreva o relacionamento entre ``string.join(string.split(poesia))`` e ``poesia``. Eles so o mesmo para qualquer *string? Quando eles seriam diferentes?*

8.17 Glossrio

lista (list) Uma coleo denominada de objetos, onde cada objeto identificado por um ndice. ndice (index) Uma varivel inteira ou valor que indica um elemento de uma lista. elemento (element) Um dos valores em uma lista(ou outra seqncia). O operador colchete seleciona elementos de uma lista. seqncia (sequence) Qualquer um dos tipos de dados que consiste de um conjunto ordenado de elementos, com cada elemento identificado por um ndice. lista aninhada (nested list) Uma lista que um elemento de uma outra lista. percurso na lista (list traversal) O acesso seqencial de cada elemento em uma lista. objeto (object) Um coisa a qual uma varivel pode se referir. apelidos (aliases) Mltiplas variveis que contm referncias ao mesmo objeto. clonar (clone) Criar um novo objeto que possui o mesmo valor de um objeto existente. Copiar a referncia a um objeto cria um apelido (alias) mas no clona o objeto. delimitador (delimiter) Um caracter uma string utilizados para indicar onde uma string deveria ser dividida(split).

Outros termos utilizados neste captulo

(XXX esta lista deve ser retirada na verso final) XXX has, have possuir (ter?) XXX there is, there are existir (haver?) XXX use utilizar (usar?) XXX string Utilizei string em itlico, por ser tratar de um termo que no em portugus. XXX enclose envolver??? XXX provide fornecer XXX return devolve XXX denoted denotada ???? XXX disappointing decepcionante (desapontador?) XXX assign atribuir XXX change modificar XXX length comprimento (tamanho?)

XXX print exibir (imprimir?) XXX membership No creio que exista uma palavra que traduza este termo. Pelo menos em ingls no encontrei nenhum sinnimo. Vou tentar traduzir explicando o termo dependendo do contexto. XXX boolean lgico (booleano?) XXX handle tratar XXX proceed agir XXX By default por padro XXX notice perceber (observar?) XXX mirabile dictu Algum tem idia do que significa isto? Meu latim no chegou l. :) XXX traduzir os exemplos? considero melhor fazer a traduzir os exemplos sempre que possvel. S no gostaria de tirar o esprito que levou o autor a utilizar tais exemplos. Podem haver trocadilhos, homenagens e outros sentimentos no autor que no devemos retirar. Desta forma, estou traduzindo todos os termos que consigo entender e encontrar palavras que exprimam a idia. Nos demais, estou mantendo os termos originais para uma discusso futura.

Captulo 8: Listas
System Message: INFO/1 (<string>, line 8986); backlink Duplicate implicit target name: "captulo 8: listas".

Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos o 3.4 Funes matemticas o 3.5 Composio o 3.6 Adicionando novas funes o 3.7 Definies e uso o 3.8 Fluxo de execuo o 3.9 Parmetros e argumentos o 3.10 Variveis e parmetros so locais o 3.11 Diagramas da pilha o 3.12 Funes com resultados o 3.13 Glossrio Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados

4.8 A instruo return 4.9 Recursividade 4.10 Diagramas de pilha para funes recursivas 4.11 Recursividade infinita 4.12 Entrada pelo teclado 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas Captulo 10: Dicionrios Captulo 10: Dicionrios
o o o o o o

Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores Uma lista um conjunto ordenado de valores, onde cada valor identificado por um ndice. Os valores que compem uma lista so chamados elementos. Listas so similares a strings, que so conjuntos ordenados de caracteres, com a diferena que os elementos de uma lista podem possuir qualquer tipo. Listas e strings ? e outras coisas que se comportam como conjuntos ordenados ? so chamados seqncias.

8.1 Valores da lista

Existem vrias maneiras de criar uma nova lista; a mais simples envolver os elementos em colchetes ([ e ]):
>>> [10, 20, 30, 40] >>> [?spam?, ?bungee?, ?swallow?]

O primeiro exemplo uma lista de quatro inteiros. O segundo uma lista de trs strings. Os elementos de uma lista no necessitam ser do mesmo tipo. A lista a seguir contm uma string, um valor float, um valor inteiro, e mirabile dictu uma outra lista:
>>> [?alo?, 2.0, 5, [10,20]]

Uma lista dentro de outra lista dita estar aninhada. Listas que contm inteiros consecutivos so comuns, ento Python fornece

uma maneira simples de cri-los:


>>> range(1,5)

[1, 2, 3, 4] A funo range pega dois argumentos e devolve uma lista que contm todos os inteiros do primeiro at o segundo, incluindo o primeiro mas no incluindo o segundo! Existem outras formas de range. Com um argumento simples, ela cria uma lista que inicia em 0:
>>> range(10)

[0,1, 2, 3, 4, 5, 6, 7, 8, 9] Se existe um terceiro argumento, ele especifica o espao entre os valores sucessivos, que chamado de tamanho do passo. Este exemplo conta de 1 at 10 em passos de 2:
>>> range(1, 10, 2)

[1, 3, 5, 7, 9] Finalmente, existe uma lista especial que no contm elementos. Ela chamada lista vazia, e sua notao []. Com todas estas formas de criar listas, seria decepcionante se no pudssemos atribuir valores de listas a variveis ou passar listas como parmetros a funes. Ns podemos.
>>> vocabulario = [?melhorar?, ?castigar?, ?defenestrar?] >>> numeros = [17, 123] >>> vazio = [] >>> print vocabulario, numeros, vazio

[?melhorar?, ?castigar?, ?defenestrar?] [17, 123] []

8.2 Acessado elementos

A sintaxe para acessar os elementos de uma lista a mesma que a sintaxe para acessar os caracteres de uma string ? o operator colchete ([]). A expresso dentro dos colchetes especifica o ndice. Lembre-se que os ndices iniciam em 0:
>>> print numeros[0]

>>> numeros[1]= 5

O operador colchete pode aparecer em qualquer lugar em uma expresso. Quando ele aparece no lado esquerdo de uma atribuio, ele modifica um dos elementos em uma lista, de forma que o um-simo elemento de numeros, que era 123, agora 5. Qualquer expresso inteira pode ser utilizada como um ndice:
>>> numeros[3-2]

5
>>> numeros[1.0]

TypeError: sequence index must be integer Se voc tentar ler ou escrever um elemento que no existe, voc recebe um erro de tempo de execuo (runtime error):
>>> numeros[2]=5

IndexError: list assignment index out of range Se um ndice possui um valor negativo, ele conta ao contrrio a partir do final da lista:
>>> numeros[-1]

5
>>> numeros[-2]

17
>>> numeros[-3]

IndexError: list index out of range numeros[-1] o ltimo elemento da lista, numeros[-2] o penltimo e numeros[-3] no existe. comum utilizar uma varivel de lao como um ndice da lista.
>>> cavaleiros = [?guerra?, ?fome?, ?peste?, ?morte?]

i=0 while i < 4:

print cavaleiros[i] i=i+1 Este lao while conta de 0 at 4. Quando a varivel do lao i 4, a condio falha e o lao se encerra. Desta forma o corpo do lao executado somente quando i 0, 1, 2 e 3. Em cada vez dentro do lao, a varivel i utilizada como um ndice para a lista, exibindo o i-simo elemento. Este padro de computao chamado de percurso na lista.

8.3 Comprimento da lista

A funo len devolve o comprimento de uma lista. uma boa idia utilizar este valor como o limite superior de um lao ao invs de uma constante. Desta forma, se o tamanho da lista mudar, voc no precisar ir atravs de todo o programa modificando todos os laos; eles funcionaro corretamente para qualquer tamanho de lista:
>>> cavaleiros = [?guerra?, ?fome?, ?peste?, ?morte?]

i=0 while i < len(cavaleiros): print cavaleiros[i] i=i+1 A ltima vez que o corpo do lao executado, i len(cavaleiros) ? 1, que o ndice do ltimo elemento. Quando i igual a len(cavaleiros), a condio falha e o corpo no executado, o que uma boa coisa, porque len(cavaleiros) no um ndice legal. Embora uma lista possa conter uma outra lista, a lista aninhada ainda conta como um elemento simples. O comprimento desta lista quatro:
>>> [`spam!?, 1, [`Brie`, `Roquefort`, `Pol l Veq`], [1, ,2 3]]

Como um exerccio, escreva um lao que percorra a lista anterior e exiba o comprimento de cada elemento. O que acontece se voc manda um inteiro para ``len``?

8.4 Membros de uma lista

in um operador lgico que testa se um elemento membro de uma seqncia. Ns o utilizamos na Seo 7.10 com strings, mas ele tambm funciona com listas e outras seqncias:
>>> cavaleiros = [?guerra?, ?fome?, ?peste?, ?morte?] >>> ?peste? in cavaleiros

1
>>> ?depravao? in cavaleiros

0 Uma vez que ?peste? um membro da lista cavaleiros, o operador in devolve verdadeiro. Uma vez que depravao no est na lista, in devolve falso. Podemos utilizar tambm o not em combinao com o in para testar se um elemento no um membro de uma lista:
>>> ``depravao`` not in cavaleiros

8.5 Listas e laos for

O lao for que vimos na Seo 7.3 tambm funciona com listas. A sintaxe generalizada de um lao for :
>>> for VARIABLE in LIST:

BODY Esta declarao equivalente a:


>>> i = 0

while i < len(LIST): VARIABLE = LIST[i] BODY

i=i+1 O lao for mais conciso porque podemos eliminar a varivel do lao, i. Aqui est o lao anterior escrito com um`lao for:
>>> for cavaleiro in cavaleiros:

print cavaleiro Quase se l como Portugus: "For (para cada) cavaleiro in (na lista de) cavaleiros, print (imprima o nome do) cavaleiro." Qualquer expresso de lista pode ser utilizada num lao for:
>>> for numero in range(20):

if numero % 2 == 0: print numero


>>> for fruta in ["banana", "abacaxi", "laranja"]:

print "Eu gosto de comer " + fruta + "s!" O primeiro exemplo exibe todos os nmeros pares entre zero e dezenove. O segundo exemplo expressa o entusiasmo por vrias frutas.

8.6 Operaes em listas

O operador + concatena listas:


>>> a = [1, 2, 3] >>> b = [4, 5, 6] >>> c = a + b >>> print c

[1, 2, 3, 4, 5, 6] Similarmente, o operador * repete uma lista um nmero dado de vezes:


>>> [0] * 4

[0, 0, 0, 0]
>>> [1, 2, 3] * 3

[1, 2, 3, 1, 2, 3, 1, 2, 3] O primeiro exemplo repete [0] quatro vezes. O segundo exemplo repete a lista

[1, 2, 3] trs vezes.

8.7 Fatiamento de listas

A operao de fatiamento que vimos na Seo 7.4 tambm funciona sobre listas:
>>> lista = ['a', 'b', 'c', 'd', 'e', 'f'] >>> lista[1:3]

['b', 'c']
>>> lista[:4]

['a', 'b', 'c', 'd']


>>> lista[3:]

['d', 'e', 'f']


>>> lista[:]

['a', 'b', 'c', 'd', 'e', 'f']

8.8 Listas so mutveis

Diferente das strings, as listas so mutveis, o que significa que podemos modificar seus elementos. Utilizando o operador colchete no lado esquerdo de uma atribuio, podemos atualizar um de seus elementos:
>>> fruta = ["banana", "abacaxi", "laranja"] >>> fruta[0] = "abacate" >>> fruta[-1] = "tangerina" >>> print fruta

['abacate', 'abacaxi', 'tangerina'] Com o operador de fatiamento podemos atualizar vrios elementos de uma vez:
>>> lista = ['a', 'b', 'c', 'd', 'e', 'f'] >>> lista[1:3] = ['x', 'y'] >>> print lista

['a', 'x', 'y', 'd', 'e', 'f'] Tambm podemos remover elementos de uma lista atribuindo a lista vazia a eles:
>>> lista = ['a', 'b', 'c', 'd', 'e', 'f'] >>> lista[1:3] = [] >>> print lista

['a', 'd', 'e', 'f'] E podemos adicionar elementos a uma lista enfiando-os numa fatia vazia na posio desejada:
>>> lista = ['a', 'd', 'f'] >>> lista[1:1] = ['b', 'c'] >>> print lista

['a', 'b', 'c', 'd', 'f']


>>> lista[4:4] = ['e'] >>> print lista

['a', 'b', 'c', 'd', 'e', 'f']

8.9 Remoo em lista

Utilizando fatias para remover elementos pode ser complicado, e desta forma propenso a erro. Python fornece uma alternativa que mais legvel. del remove um elemento de uma lista:
>>> a = ['um', 'dois', 'tres'] >>> del a[1] >>> a

['um', 'tres'] Como voc deveria esperar, del trata valores negativos e causa erros de tempo de execuo se o ndice estiver fora da faixa. Voc tambm pode utilizar uma faixa como um ndice para del:
>>> lista = ['a', 'b', 'c', 'd', 'e', 'f'] >>> del lista[1:5] >>> print lista

['a', 'f'] Como de costume, fatias selecionam todos os elementos at, mas no incluindo, o segundo ndice.

8.10 Ojetos e valores

Se executamos estas declaraes de atribuio,


>>> a = "banana" >>> b = "banana"

sabemos que a e b se referem a uma string com as letras banana. Mas no podemos dizer se elas apontam para a mesma string. Existem dois possveis estados: ** XXX figura 1 ** Em um caso, a e b se referem a duas coisas diferentes que possuem o mesmo valor. No segundo caso, elas se referem mesma coisa. Estas "coisas" possume nomes - elas so chamadas objetos. Um objeto algo ao qual uma varivel pode se referenciar. Todo objeto possui um identificador nico, que podemos obter com a funo id. Exibindo o identificador de a e b, podemos dizer se elas se referem ao mesmo objeto.
>>> id(a)

135044008
>>> id(b)

135044008 De fato, obtivemos o mesmo identificador duas vezes, o que significa que Python criou apenas uma string, e tanto a quanto b se referem a ela. Interessantemente, listas se comportam de forma diferente. Quando criamos duas listas, obtemos dois objetos:
>>> a = [1, 2, 3] >>> b = [1, 2, 3] >>> id(a)

135045528
>>> id(b)

135041704 Ento o diagrama de estado se parece com isto: ** XXX figura 2 ** a e b possuem o mesmo valor mas no se referem ao mesmo objeto.

8.11 Apelidos

Uma vez que variveis se referem a objetos, se atribuimos uma varivel a uma outra, ambas as variveis se referem ao mesmo objeto:
>>> a = [1, 2, 3] >>> b = a

Neste caso, o diagrama de estado se parece com isto: ** XXX figura 3 ** Uma vez que a lista possui dois nomes diferentes, a e b, dizemos que ela est "apelidada" (aliased). Mudanas feitas em um apelido afetam o outro nome:
>>> b[0] = 5 >>> print a

[5, 2, 3] Embora este comportamento possa ser til, ele s vezes inesperado e indesejado. Em geral, mais seguro evitar os apelidos quando voc est trabalhando com objetos mutveis. claro, para objetos imutveis, no h problema. por isto que Python livre para apelidar cadeias de caracteres quando v uma oportunidade de economizar.

8.12 Clonando listas

Se queremos modificar uma lista e tambm manter uma cpia da original,

preciamos ter condies de fazer uma cpia da prpria lista, no apenas uma referncia. Este processo algumas vezes chamado clonagem, para evitar a ambigidade da palavra "cpia". A maneira mas fcil de clonar uma lista utilizar o operador de fatia:
>>> a = [1, 2, 3] >>> b = a[:] >>> print b

[1, 2, 3] Pegar qualquer fatia de a cria uma nova lista. Neste caso acontece da fatia consistir da lista inteira. Agora estamos livres para fazer alteraes a b sem nos preocuparmos com``a``:
>>> b[0] = 5 >>> print a

[1, 2, 3] Como exerccio, desenhe um diagrama de estado para``a`` e ``b`` antes e depois desta mudana.

8.13 Lista como parmetro

Passar uma lista como um argumento passa realmente uma referncia lista, no uma cpia da lista. Por exemplo, a funo cabea pega uma lista como parmetro e devolve o primeiro elemento:
>>> def cabeca(lista):

return lista[0] Aqui est a maneira como ela utilizada:


>>> numeros = [1, 2, 3] >>> cabeca(numeros)

1 O parmetro lista e a varivel numeros so apelidos para o mesmo objeto. O diagrama de estado se parece com isto: ** XXX figura 4 **

Uma vez que o objeto compartilhado pelos dois quadros, o desenhamos entre eles. Se a funo modifica um parmetro da lista, a funo chamadora v a mudana. Por exemplo, removeCabeca remove o primeiro elemento da lista:
>>> def removecabeca(lista):

del lista[0] Aqui est a maneira como ela utilizada:


>>> numeros = [1, 2, 3] >>> removeCabeca(numeros) >>> print numeros

[2, 3] Se uma funo devolve uma lista, ela devolve uma referncia lista. Por exemplo, cauda devolve uma lista que contm todos menos o primeiro elemento de uma determinada lista:
>>> def cauda(lista):

return lista[1:] Aqui est a maneira como ela utilizada:


>>> numeros = [1, 2, 3] >>> resto = cauda(numeros) >>> print resto

[2, 3] Uma vez que o valor de retorno foi criado com o operador de fatia, ele uma nova lista. A criao de resto, e qualquer alterao subseqente a resto, no tem efeito sobre numeros.

8.14 Lista aninhadas

Uma lista aninhada uma lista que aparece como um elemento de uma outra lista. Nesta lista, o terceiro elemento uma lista aninhada:
>>> lista = ["alo", 2.0, 5, [10, 20]]

Se exibimos lista[3], obtemos [10, 20]. Para extrairmos um elemento de uma lista aninhada, podemos agir em duas etapas:
>>> elt = lista[3]

>>> elt[0]

10 Ou podemos combin-las:
>>> lista[3][1]

20 Os operadores colchete avaliam da esquerda para a direita, ento a expresso pega o terceiro elemento de lista e extrai o primeiro elemento dela.

8.15 Matrizes

Listas aninhadas so freqentemente utilizadas para representar matrizes. Por exemplo, a matriz: XXX figura matriz 1 poderia ser representada como:
>>> matriz = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

matriz uma lista com trs elementos, onde cada elemento uma linha da matriz. Podemos selecionar uma linha inteira da matriz da maneira habitual:
>>> matriz[1]

[4, 5, 6] Ou podemos extrair um nico elemento da matriz utilinado a forma de duplo ndice:
>>> matriz[1][1]

5 O primeiro ndice seleciona a linha,e o segundo ndice seleciona a coluna. Embora esta maneira de representar matrizes seja comum, ela no a nica possibilidade. Uma pequena variao utilizar uma lista de colunas ao invs de uma lista de linhas. Mais adiante veremos uma alternativa mais radical utilizando um dicionrio.

8.16 Strings e listas

Duas das mais teis funes no mdulo string envolvem listas de strings. A funo split (separar) quebra uma string em uma lista de palavras. Por padro, qualquer nmero de caracteres espao em branco considerado um limite de uma palavra:
>>> import string >>> poesia = "O orvalho no carvalho..." >>> string.split(poesia)

['O', 'orvalho', 'no', 'carvalho...'] Um argumento opcional chamado um delimitador pode ser utilizado para especificar qual caracter utilizar como limites da palavra. O exemplo a seguir utiliza a string va
>>> string.split(poesia, 'va')

['O or', 'lho no car', 'lho...'] Perceba que o delimitador no aparece na lista. A funo join (juntar) o inverso de split. Ela pega uma lista de strings e concatena os elementos com um espao entre cada par:
>>> lista = ['O', 'orvalho', 'no', 'carvalho...'] >>> string.join(lista)

'O orvalho no carvalho...' Como split, join recebe um delimitador que inserido entre os elementos:
>>> string.join(lista, '_')

'O_orvalho_no_carvalho...' Como um execcio, descreva o relacionamento entre ``string.join(string.split(poesia))`` e ``poesia``. Eles so o mesmo para qualquer *string? Quando eles seriam diferentes?*

8.17 Glossrio

lista (list) Uma coleo denominada de objetos, onde cada objeto identificado por um ndice. ndice (index) Uma varivel inteira ou valor que indica um elemento de uma lista. elemento (element) Um dos valores em uma lista(ou outra seqncia). O operador colchete seleciona elementos de uma lista. seqncia (sequence) Qualquer um dos tipos de dados que consiste de um conjunto ordenado de elementos, com cada elemento identificado por um ndice. lista aninhada (nested list) Uma lista que um elemento de uma outra lista. percurso na lista (list traversal) O acesso seqencial de cada elemento em uma lista. objeto (object) Um coisa a qual uma varivel pode se referir. apelidos (aliases) Mltiplas variveis que contm referncias ao mesmo objeto. clonar (clone) Criar um novo objeto que possui o mesmo valor de um objeto existente. Copiar a referncia a um objeto cria um apelido (alias) mas no clona o objeto. delimitador (delimiter) Um caracter uma string utilizados para indicar onde uma string deveria ser dividida(split).

Outros termos utilizados neste captulo

(XXX esta lista deve ser retirada na verso final) XXX has, have possuir (ter?) XXX there is, there are existir (haver?) XXX use utilizar (usar?) XXX string Utilizei string em itlico, por ser tratar de um termo que no em portugus. XXX enclose envolver??? XXX provide fornecer XXX return devolve XXX denoted denotada ???? XXX disappointing decepcionante (desapontador?) XXX assign atribuir XXX change modificar XXX length comprimento (tamanho?)

XXX print exibir (imprimir?) XXX membership No creio que exista uma palavra que traduza este termo. Pelo menos em ingls no encontrei nenhum sinnimo. Vou tentar traduzir explicando o termo dependendo do contexto. XXX boolean lgico (booleano?) XXX handle tratar XXX proceed agir XXX By default por padro XXX notice perceber (observar?) XXX mirabile dictu Algum tem idia do que significa isto? Meu latim no chegou l. :) XXX traduzir os exemplos? considero melhor fazer a traduzir os exemplos sempre que possvel. S no gostaria de tirar o esprito que levou o autor a utilizar tais exemplos. Podem haver trocadilhos, homenagens e outros sentimentos no autor que no devemos retirar. Desta forma, estou traduzindo todos os termos que consigo entender e encontrar palavras que exprimam a idia. Nos demais, estou mantendo os termos originais para uma discusso futura. System Message: WARNING/2 (<string>, line 10217) Block quote ends without a blank line; unexpected unindent.

Captulo 9: Tuplas
Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos o 3.4 Funes matemticas o 3.5 Composio o 3.6 Adicionando novas funes o 3.7 Definies e uso o 3.8 Fluxo de execuo o 3.9 Parmetros e argumentos o 3.10 Variveis e parmetros so locais o 3.11 Diagramas da pilha o 3.12 Funes com resultados o 3.13 Glossrio Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa

4.6 Condicionais encadeados 4.7 Condicionais aninhados 4.8 A instruo return 4.9 Recursividade 4.10 Diagramas de pilha para funes recursivas 4.11 Recursividade infinita 4.12 Entrada pelo teclado 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas
o o o o o o o o

Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores

9.1 Mutabilidade e tuplas

At agora, voc tem visto dois tipos compostos: strings, que so compostos de caracteres; e listas, que so compostas de elementos de qualquer tipo. Uma das diferenas que notamos que os elementos de uma lista podem ser modificados, mas os caracteres em uma string no. Em outras palavras, strings so imutveis e listas so mutveis. H um outro tipo em Python chamado tupla (tuple) que similar a uma lista exceto por ele ser imutvel. Sintaticamente, uma tupla uma lista de valores separados por vrgulas:
>>> tupla = 'a', 'b', 'c', 'd', 'e'

Embora no seja necessrio, convencional colocar tuplas entre parnteses:


>>> tupla = ('a', 'b', 'c', 'd', 'e')

Para criar uma tupla com um nico elemento, temos que incluir uma vrgula final:
>>> t1 = ('a',) >>> type(t1)

<type 'tuple'> Sem a vrgula, Python entende ('a') como uma string entre parnteses:
>>> t2 = ('a') >>> type(t2)

<type 'string'> Questes de sintaxe de lado, as operaes em tuplas so as mesmas operaes das listas. O operador ndice seleciona um elemento da tupla.
>>> tupla = ('a', 'b', 'c', 'd', 'e') >>> tupla[0]

'a' E o operador slice (fatia) seleciona uma "faixa" (range) de elementos.


>>> tupla[1:3]

('b', 'c') Mas se tentarmos modificar um dos elementos de uma tupla, teremos um erro:
>>> tupla[0] = 'A'

TypeError: object doesn't support item assignment Naturalmente, mesmo que no possamos modificar os elementos de uma tupla, podemos substitu-la por uma tupla diferente:
>>> tupla = ('A',) + tupla[1:] >>> tupla

('A', 'b', 'c', 'd', 'e')

9.2 Atribuies de tupla

De vez em quando, necessrio trocar entre si os valores de duas variveis. Com operaes de atribuio convencionais, temos que utilizar uma varivel temporria. Por exemplo, para fazer a troca entre a e b:
>>> temp = a >>> a = b >>> b = temp

Se voc tiver que fazer isso com frequncia, esta abordagem se torna incmoda. Python fornece uma forma de atribuio de tupla que resolve esse problema elegantemente:
>>> a, b = b, a

O lado esquedo uma tupla de variveis; o lado direito uma tupla de valores. Cada valor atribudo sua respectiva varivel. Todas as expresses do lado direito so avaliadas antes de qualquer das atribuies. Esta caracterstica torna as atribuies de tupla bastante versteis. Naturalmente, o nmero de variveis na esquerda e o nmero de valores na direita deve ser igual:
>>> a, b, c, d = 1, 2, 3

ValueError: unpack tuple of wrong size

9.3 Tuplas como valores de retorno

Funes podem retornar tuplas como valor de retorno. Por Exemplo, ns poderamos escrever uma funo que troca dois parmetros entre si:
def troca(x, y): return y, x

Ento ns poderamos atribuir o valor de retorno para uma tupla com duas variveis:
a, b = troca(a, b)

Neste caso, no existe uma grande vantagem em fazer de troca (swap) uma funo. De fato, existe um perigo em tentar encapsular troca, o qual a tentao de cometer o seguinte erro:
def troca(x, y): x, y = y, x # versao incorreta

Se ns chamarmos esta funo desta forma:


troca(a, b)

ento a e x so apelidos para um mesmo valor. Mudar x dentro da funo troca, faz com que x se referencie a um valor diferente, mas sem efeito sobre a

dentro de __main__. Do mesmo modo, a mudana em y no tem efeito sobre b. Esta funo roda sem produzir uma mensagem de erro, mas ela no faz o que pretendemos. Este um exemplo de um erro semntico. Como exerccio, desenhe um diagrama de estado pra esta funo de modo que voc possa ver porque ela no funciona.

9.4 Nmeros aleatrios

A maioria dos programas de computador fazem a mesma coisa sempre que so executados, ento, podemos dizer que eles so determinsticos. Determinismo em geral uma coisa boa, se ns esperamos que um clculo d sempre o mesmo resultado. Entretanto, para algumas aplicaes queremos que o computador se torne imprevisvel. Jogos so um exemplo bvio, mas existem outros. Fazer um programa realmente no-determinstico se mostra no ser to fcil, mas existem maneiras de faz-lo ao menos parecer no-determinstico. Uma dessas maneiras gerar nmeros aleatrios e us-los para determinar o resultado de um programa. Python tem uma funo nativa que gera nmeros pseudo aleatrios, os quais no so verdadeiramente aleatrios no sentido matemtico, mas para os nossos propsitos eles so. O mdulo random contm uma funo chamada random que retorna um nmero em ponto flutuante (floating-point number) entre 0.0 e 1.0. Cada vez que voc chama random, voc recebe o prximo nmero de uma longa srie. Para ver uma amostra, execute este loop:
import random

for i in range(10): x = random.random() print x

Para gerar um nmero aleatrio ente 0.0 e um limite superior, digamos superior, multiplique x por superior. Como exerccio, gere um nmero aleatrio entre 'inferior' e 'superior'. Como exerccio adicional, gere um nmero inteiro aleatrio entre 'inferior' e 'superior', inclusive os dois extremos.

9.5 Lista de nmeros aleatrios

O primeiro passo gerar uma lista aleatria de valores. listaAleatoria pega um parmetro inteiro e retorna uma lista de nmeros aleatrios com o comprimento dado. Inicia-se com uma lista de n zeros. A cada iterao do loop, ele substitui um dos elementos por um nmero aleatrio. O valor retornado uma referncia para a lista completa:
def listaAleatoria(n): s = [0] * n for i in range(n): s[i] = random.random() return s

Vamos realizar um teste desta funo com uma lista de oito elementos. Para efeitos de depurao, uma boa idia comear com uma lista pequena.
>>> listaAleatoria(8)

0.15156642489 0.498048560109 0.810894847068 0.360371157682 0.275119183077 0.328578797631 0.759199803101 0.800367163582 Os nmeros gerados por random so supostamente uniformemente distribudos, o que significa que cada valor tem uma probabilidade igual de acontecer. Se ns dividirmos a faixa de valores possveis em intervalos do mesmo tamanho, e contarmos o nmero de vezes que um determinado valor aleatrio caiu em seu respectivo intervalo, ns devemos obter o mesmo nmero

aproximado de valores em cada um dos intervalos. Ns podemos testar esta teoria escrevendo um programa que divida a faixa de valores em intervalos e conte o nmero de valores de cada intervalo.

9.6 Contando

Uma boa maneira de abordar problemas como esse dividir o problema em subproblemas, e encontrar um subproblema que se enquadre em um padro de soluo computacional que voc j tenha visto antes. Neste caso, queremos percorrer uma lista de nmeros e contar o nmero de vezes que valor se encaixa em um determinado intervalo. Isso soa familiar. Na Seo 7.8, ns escrevemos um programa que percorria uma string e contava o nmero de vezes que uma determinada letra aparecia. Assim, podemos prosseguir copiando o programa original e adaptando-o para o problema atual. O programa original era:
contador = 0 for letra in fruta: if letra == 'a': contador = contador + 1 print contador

O primeiro passo substituir fruta por lista e letra por numero. Isso no muda o programa, apenas o ajusta para que ele se torne mais fcil de ler e entender. O segundo passo mudar o teste. Ns no estamos interessados em procurar letras. Ns queremos ver se numero est entre inferior e superior.:
contador = 0 for numero in lista if inferior < numero < superior: contador = contador + 1 print contador

O ltimo passo encapsular este cdigo em uma funo chamada noIntervalo. Os parmetros so a lista e os valores inferior e superior:
def noIntervalo(lista, inferior, superior):

contador = 0 for numero in lista: if inferior < numero < superior: contador = contador + 1 return contador

Atravs da cpia e da modificao de um programa existente, estamos aptos a escrever esta funo rapidamente e economizar um bocado de tempo de depurao. Este plano de desenvolvimento chamado de casamento de padres. Se voc se encontrar trabalhando em um problema que voc j solucionou antes, reuse a soluo.

9.7 Vrios intervalos

Conforme o nmero de intervalos aumenta, noIntervalo torna-se intragvel. Com dois intervalos, no to ruim:
inferior = noIntervalo(a, 0.0, 0.5) superior = noIntervalo(a, 0.5, 1)

Mas com quatro intervalos, comea a ficar desconfortvel.:


intervalo1 = noIntervalo(a, 0.0, 0.25) intervalo2 = noIntervalo(a, 0.25, 0.5) intervalo3 = noIntervalo(a, 0.5, 0.75) intervalo4 = noIntervalo(a, 0.75, 1.0)

Existem aqui dois problemas. Um que temos que criar novos nomes de varivel para cada resultado. O outro que temos que calcular os limites de cada intervalo. Vamos resolver o segundo problema primeiro. Se o nmero de intervalos numeroDeIntervalos, ento a largura de cada intervalo 1.0 / numeroDeIntervalos. Vamos usar um lao (loop) para calcular a faixa, ou largura, de cada intervalo. A varivel do loop, i, conta de 0 at numeroDeIntervalos-1:
larguraDoIntervalo = 1.0 / numeroDeIntervalos for i in range(numeroDeIntervalos):

inferior = i * larguraDoIntervalo superior = inferior + larguraDoIntervalo print "do" inferior, "ao", superior

Para calcular o limite inferior (inferior) de cada intervalo, ns multiplicamos a varivel do loop (i) pela largura do intervalo (larguraDoIntervalo). O limite superior (superior) est exatamente uma "largura de intervalo" acima. Com numeroDeIntervalos = 8, o resultado :
0.0 to 0.125 0.125 to 0.25 0.25 to 0.375 0.375 to 0.5 0.5 to 0.625 0.625 to 0.75 0.75 to 0.875 0.875 to 1.0

Voc pode confirmar que cada intervalo tem a mesma largura, que eles no se sobrepe, e que eles cobrem toda a faixa de valores de 0.0 a 1.0. Agora, de volta ao primeiro problema. Ns precisamos de uma maneira de guardar oito inteiros, usando a vriavel do loop para indicar cada um destes inteiros. Voc deve estar pensando, "Lista!" Ns temos que criar a lista de intervalos fora do loop, porque queremos fazer isto apenas uma vez. Dentro do loop, ns vamos chamar noIntervalo repetidamente e atualizar o i-simo elemento da lista:
numeroDeIntervalos = 8 intervalos = [0] * numeroDeIntervalos larguraDoIntervalo = 1.0 / numeroDeIntervalos for i in range(numeroDeIntervalos): inferior = i * larguraDoIntervalo superior = inferior + larguraDoIntervalo intervalos[i] = noIntervalo(lista, inferior, superior) print intervalos

Com uma lista de 1000 valores, este cdigo vai produzir esta lista de quantidades de valores em cada intervalo:
[138, 124, 128, 118, 130, 117, 114, 131]

Esses nmeros esto razoavelmente pximos de 125, o que era o que espervamos. Pelo menos eles esto prximos o bastante para nos fazer acreditar que o gerador de nmero aleatrios est funcionando. Como exerccio, teste esta funo com algumas listas longas, e veja se o nmero de valores em cada um dos intervalos tendem a uma distribuio nivelada.

9.8 Uma soluo em um s passo

Embora este programa funcione, ele no to eficiente quanto poderia ser. Toda vez que ele chama noIntervalo, ele percorre a lista inteira. Conforme o nmero de intervalos aumenta, a lista ser percorrida um bocado de vezes. Seria melhor fazer uma nica passagem pela lista e calcular para cada valor o ndice do intervalo ao qual o valor pertena. Ento podemos incrementar o contador apropriado. Na seo anterior, pegamos um ndice, i, e o multiplicamos pela larguraDoIntervalo para encontrar o limite inferior daquele intervalo. Agora queremos pegar um valor entre 0.0 e 1.0 e encontrar o ndice do intervalo ao qual ele se encaixa. J que este problema o inverso do problema anterior, podemos imaginar que deveramos dividir por larguraDoIntervalo em vez de multiplicar. Esta suposio est correta. J que larguraDoIntervalo = 1.0 / numeroDeIntervalos, dividir por larguraDoIntervalo o mesmo que multiplicar por numeroDeIntervalos. Se multiplicarmos um nmero na faixa entre 0.0 e 1.0 por numeroDeIntervalos, obtemos um nmero na faixa entre 0.0 e numeroDeIntervalos. Se arredondarmos este nmero para baixo, ou seja, para o menor inteiro mais prximo, obtemos exatamente o que estamos procurando - o ndice do intervalo:
numeroDeIntervalos = 8 intervalos = [0] * numeroDeIntervalos for i in lista: indice = int(i * numeroDeIntervalos)

intervalos[indice] = intervalos[indice] + 1

Usamos a funo int para converter um nmero em ponto flutuante (float) para um inteiro. Existe a possibilidade deste clculo produzir um ndice que esteja fora dos limites (seja negativo ou maior que len(intervalos)-1)? Uma lista como intervalos que contm uma contagem do nmero de valores em cada intervalo chamada de histograma. Como exerccio, escreva uma funo chamada ``histograma`` que receba uma lista e um nmero de intervalos como argumentos e retorne um histograma com o nmero de intervalos solicitado.

9.9 Glossrio

tipo imutvel (immutable type) Um tipo de elemento que no pode ser modificado. Atribuies a um elemento ou "fatiamento (slices)" XXX aos tipos imutveis causaro erro. tipo mutvel (mutable type) Tipo de dados onde os elementos podem ser modificados. Todos os tipos mutveis, so tipos compostos. Listas e dicionrios so exemplos de tipos de dados mutveis. String e tuplas no so. tupla (tuple) Tipo sequencial similar as listas com exceo de que ele imutvel. Podem ser usadas Tuplas sempre que um tipo imutvel for necessrio, por exemplo uma "chave (key)" em um dicionrio Atribuio a tupla (tuple assignment) Atribuio a todos os elementos de uma tupla feita num nico comando de atribuo. A atribuio aos elementos ocorre em paralelo, e no em sequncia, tornando esta operao til para swap, ou troca recproca de valores entre variveis (ex: a,b=b,a). determinstico (deterministic) Um programa que realiza a mesma coisa sempre que executado.

pseudo aleatrio (pseudorandom) Uma sequncia de nmeros que parecem ser aleatrios mas so na verdade o resultado de uma computao "determinstica" histograma (histogram) Uma lista de inteiros na qual cada elemento conta o nmero de vezes que algo acontece. casamento de padro XXX (pattern matching) Um programa desenvolvido que envolve identificar um teste padro computacional familiar e copiar a soluo para um problema similar.

Captulo 9: Tuplas
System Message: INFO/1 (<string>, line 10854); backlink Duplicate implicit target name: "captulo 9: tuplas". Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes

3.2 Converso entre tipos 3.3 Coero entre tipos 3.4 Funes matemticas 3.5 Composio 3.6 Adicionando novas funes 3.7 Definies e uso 3.8 Fluxo de execuo 3.9 Parmetros e argumentos 3.10 Variveis e parmetros so locais 3.11 Diagramas da pilha 3.12 Funes com resultados 3.13 Glossrio Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos
o o o o o o o o o o o o

o 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores

9.1 Mutabilidade e tuplas

At agora, voc tem visto dois tipos compostos: strings, que so compostos de caracteres; e listas, que so compostas de elementos de qualquer tipo. Uma das diferenas que notamos que os elementos de uma lista podem ser

modificados, mas os caracteres em uma string no. Em outras palavras, strings so imutveis e listas so mutveis. H um outro tipo em Python chamado tupla (tuple) que similar a uma lista exceto por ele ser imutvel. Sintaticamente, uma tupla uma lista de valores separados por vrgulas:
>>> tupla = 'a', 'b', 'c', 'd', 'e'

Embora no seja necessrio, convencional colocar tuplas entre parnteses:


>>> tupla = ('a', 'b', 'c', 'd', 'e')

Para criar uma tupla com um nico elemento, temos que incluir uma vrgula final:
>>> t1 = ('a',) >>> type(t1)

<type 'tuple'> Sem a vrgula, Python entende ('a') como uma string entre parnteses:
>>> t2 = ('a') >>> type(t2)

<type 'string'> Questes de sintaxe de lado, as operaes em tuplas so as mesmas operaes das listas. O operador ndice seleciona um elemento da tupla.
>>> tupla = ('a', 'b', 'c', 'd', 'e') >>> tupla[0]

'a' E o operador slice (fatia) seleciona uma "faixa" (range) de elementos.


>>> tupla[1:3]

('b', 'c') Mas se tentarmos modificar um dos elementos de uma tupla, teremos um erro:
>>> tupla[0] = 'A'

TypeError: object doesn't support item assignment Naturalmente, mesmo que no possamos modificar os elementos de uma tupla, podemos substitu-la por uma tupla diferente:

>>> tupla = ('A',) + tupla[1:] >>> tupla

('A', 'b', 'c', 'd', 'e')

9.2 Atribuies de tupla

De vez em quando, necessrio trocar entre si os valores de duas variveis. Com operaes de atribuio convencionais, temos que utilizar uma varivel temporria. Por exemplo, para fazer a troca entre a e b:
>>> temp = a >>> a = b >>> b = temp

Se voc tiver que fazer isso com frequncia, esta abordagem se torna incmoda. Python fornece uma forma de atribuio de tupla que resolve esse problema elegantemente:
>>> a, b = b, a

O lado esquedo uma tupla de variveis; o lado direito uma tupla de valores. Cada valor atribudo sua respectiva varivel. Todas as expresses do lado direito so avaliadas antes de qualquer das atribuies. Esta caracterstica torna as atribuies de tupla bastante versteis. Naturalmente, o nmero de variveis na esquerda e o nmero de valores na direita deve ser igual:
>>> a, b, c, d = 1, 2, 3

ValueError: unpack tuple of wrong size

9.3 Tuplas como valores de retorno

Funes podem retornar tuplas como valor de retorno. Por Exemplo, ns poderamos escrever uma funo que troca dois parmetros entre si:
def troca(x, y): return y, x

Ento ns poderamos atribuir o valor de retorno para uma tupla com duas

variveis:
a, b = troca(a, b)

Neste caso, no existe uma grande vantagem em fazer de troca (swap) uma funo. De fato, existe um perigo em tentar encapsular troca, o qual a tentao de cometer o seguinte erro:
def troca(x, y): x, y = y, x # versao incorreta

Se ns chamarmos esta funo desta forma:


troca(a, b)

ento a e x so apelidos para um mesmo valor. Mudar x dentro da funo troca, faz com que x se referencie a um valor diferente, mas sem efeito sobre a dentro de __main__. Do mesmo modo, a mudana em y no tem efeito sobre b. Esta funo roda sem produzir uma mensagem de erro, mas ela no faz o que pretendemos. Este um exemplo de um erro semntico. Como exerccio, desenhe um diagrama de estado pra esta funo de modo que voc possa ver porque ela no funciona.

9.4 Nmeros aleatrios

A maioria dos programas de computador fazem a mesma coisa sempre que so executados, ento, podemos dizer que eles so determinsticos. Determinismo em geral uma coisa boa, se ns esperamos que um clculo d sempre o mesmo resultado. Entretanto, para algumas aplicaes queremos que o computador se torne imprevisvel. Jogos so um exemplo bvio, mas existem outros. Fazer um programa realmente no-determinstico se mostra no ser to fcil, mas existem maneiras de faz-lo ao menos parecer no-determinstico. Uma dessas maneiras gerar nmeros aleatrios e us-los para determinar o resultado de um programa. Python tem uma funo nativa que gera nmeros pseudo aleatrios, os quais no so verdadeiramente aleatrios no sentido matemtico, mas para os nossos propsitos eles so. O mdulo random contm uma funo chamada random que retorna um nmero em ponto flutuante (floating-point number) entre 0.0 e 1.0. Cada vez que voc chama random, voc recebe o prximo nmero de uma longa srie. Para ver uma amostra, execute este loop:

import random

for i in range(10): x = random.random() print x

Para gerar um nmero aleatrio ente 0.0 e um limite superior, digamos superior, multiplique x por superior. Como exerccio, gere um nmero aleatrio entre 'inferior' e 'superior'. Como exerccio adicional, gere um nmero inteiro aleatrio entre 'inferior' e 'superior', inclusive os dois extremos.

9.5 Lista de nmeros aleatrios

O primeiro passo gerar uma lista aleatria de valores. listaAleatoria pega um parmetro inteiro e retorna uma lista de nmeros aleatrios com o comprimento dado. Inicia-se com uma lista de n zeros. A cada iterao do loop, ele substitui um dos elementos por um nmero aleatrio. O valor retornado uma referncia para a lista completa:
def listaAleatoria(n): s = [0] * n for i in range(n): s[i] = random.random() return s

Vamos realizar um teste desta funo com uma lista de oito elementos. Para efeitos de depurao, uma boa idia comear com uma lista pequena.
>>> listaAleatoria(8)

0.15156642489 0.498048560109 0.810894847068 0.360371157682

0.275119183077 0.328578797631 0.759199803101 0.800367163582 Os nmeros gerados por random so supostamente uniformemente distribudos, o que significa que cada valor tem uma probabilidade igual de acontecer. Se ns dividirmos a faixa de valores possveis em intervalos do mesmo tamanho, e contarmos o nmero de vezes que um determinado valor aleatrio caiu em seu respectivo intervalo, ns devemos obter o mesmo nmero aproximado de valores em cada um dos intervalos. Ns podemos testar esta teoria escrevendo um programa que divida a faixa de valores em intervalos e conte o nmero de valores de cada intervalo.

9.6 Contando

Uma boa maneira de abordar problemas como esse dividir o problema em subproblemas, e encontrar um subproblema que se enquadre em um padro de soluo computacional que voc j tenha visto antes. Neste caso, queremos percorrer uma lista de nmeros e contar o nmero de vezes que valor se encaixa em um determinado intervalo. Isso soa familiar. Na Seo 7.8, ns escrevemos um programa que percorria uma string e contava o nmero de vezes que uma determinada letra aparecia. Assim, podemos prosseguir copiando o programa original e adaptando-o para o problema atual. O programa original era:
contador = 0 for letra in fruta: if letra == 'a': contador = contador + 1 print contador

O primeiro passo substituir fruta por lista e letra por numero. Isso no muda o programa, apenas o ajusta para que ele se torne mais fcil de ler e entender.

O segundo passo mudar o teste. Ns no estamos interessados em procurar letras. Ns queremos ver se numero est entre inferior e superior.:
contador = 0 for numero in lista if inferior < numero < superior: contador = contador + 1 print contador

O ltimo passo encapsular este cdigo em uma funo chamada noIntervalo. Os parmetros so a lista e os valores inferior e superior:
def noIntervalo(lista, inferior, superior): contador = 0 for numero in lista: if inferior < numero < superior: contador = contador + 1 return contador

Atravs da cpia e da modificao de um programa existente, estamos aptos a escrever esta funo rapidamente e economizar um bocado de tempo de depurao. Este plano de desenvolvimento chamado de casamento de padres. Se voc se encontrar trabalhando em um problema que voc j solucionou antes, reuse a soluo.

9.7 Vrios intervalos

Conforme o nmero de intervalos aumenta, noIntervalo torna-se intragvel. Com dois intervalos, no to ruim:
inferior = noIntervalo(a, 0.0, 0.5) superior = noIntervalo(a, 0.5, 1)

Mas com quatro intervalos, comea a ficar desconfortvel.:


intervalo1 = noIntervalo(a, 0.0, 0.25) intervalo2 = noIntervalo(a, 0.25, 0.5) intervalo3 = noIntervalo(a, 0.5, 0.75)

intervalo4 = noIntervalo(a, 0.75, 1.0)

Existem aqui dois problemas. Um que temos que criar novos nomes de varivel para cada resultado. O outro que temos que calcular os limites de cada intervalo. Vamos resolver o segundo problema primeiro. Se o nmero de intervalos numeroDeIntervalos, ento a largura de cada intervalo 1.0 / numeroDeIntervalos. Vamos usar um lao (loop) para calcular a faixa, ou largura, de cada intervalo. A varivel do loop, i, conta de 0 at numeroDeIntervalos-1:
larguraDoIntervalo = 1.0 / numeroDeIntervalos for i in range(numeroDeIntervalos): inferior = i * larguraDoIntervalo superior = inferior + larguraDoIntervalo print "do" inferior, "ao", superior

Para calcular o limite inferior (inferior) de cada intervalo, ns multiplicamos a varivel do loop (i) pela largura do intervalo (larguraDoIntervalo). O limite superior (superior) est exatamente uma "largura de intervalo" acima. Com numeroDeIntervalos = 8, o resultado :
0.0 to 0.125 0.125 to 0.25 0.25 to 0.375 0.375 to 0.5 0.5 to 0.625 0.625 to 0.75 0.75 to 0.875 0.875 to 1.0

Voc pode confirmar que cada intervalo tem a mesma largura, que eles no se sobrepe, e que eles cobrem toda a faixa de valores de 0.0 a 1.0. Agora, de volta ao primeiro problema. Ns precisamos de uma maneira de guardar oito inteiros, usando a vriavel do loop para indicar cada um destes inteiros. Voc deve estar pensando, "Lista!" Ns temos que criar a lista de intervalos fora do loop, porque queremos fazer isto apenas uma vez. Dentro do loop, ns vamos chamar noIntervalo

repetidamente e atualizar o i-simo elemento da lista:


numeroDeIntervalos = 8 intervalos = [0] * numeroDeIntervalos larguraDoIntervalo = 1.0 / numeroDeIntervalos for i in range(numeroDeIntervalos): inferior = i * larguraDoIntervalo superior = inferior + larguraDoIntervalo intervalos[i] = noIntervalo(lista, inferior, superior) print intervalos

Com uma lista de 1000 valores, este cdigo vai produzir esta lista de quantidades de valores em cada intervalo:
[138, 124, 128, 118, 130, 117, 114, 131]

Esses nmeros esto razoavelmente pximos de 125, o que era o que espervamos. Pelo menos eles esto prximos o bastante para nos fazer acreditar que o gerador de nmero aleatrios est funcionando. Como exerccio, teste esta funo com algumas listas longas, e veja se o nmero de valores em cada um dos intervalos tendem a uma distribuio nivelada.

9.8 Uma soluo em um s passo

Embora este programa funcione, ele no to eficiente quanto poderia ser. Toda vez que ele chama noIntervalo, ele percorre a lista inteira. Conforme o nmero de intervalos aumenta, a lista ser percorrida um bocado de vezes. Seria melhor fazer uma nica passagem pela lista e calcular para cada valor o ndice do intervalo ao qual o valor pertena. Ento podemos incrementar o contador apropriado. Na seo anterior, pegamos um ndice, i, e o multiplicamos pela larguraDoIntervalo para encontrar o limite inferior daquele intervalo. Agora queremos pegar um valor entre 0.0 e 1.0 e encontrar o ndice do intervalo ao qual ele se encaixa. J que este problema o inverso do problema anterior, podemos imaginar que deveramos dividir por larguraDoIntervalo em vez de multiplicar. Esta

suposio est correta. J que larguraDoIntervalo = 1.0 / numeroDeIntervalos, dividir por larguraDoIntervalo o mesmo que multiplicar por numeroDeIntervalos. Se multiplicarmos um nmero na faixa entre 0.0 e 1.0 por numeroDeIntervalos, obtemos um nmero na faixa entre 0.0 e numeroDeIntervalos. Se arredondarmos este nmero para baixo, ou seja, para o menor inteiro mais prximo, obtemos exatamente o que estamos procurando - o ndice do intervalo:
numeroDeIntervalos = 8 intervalos = [0] * numeroDeIntervalos for i in lista: indice = int(i * numeroDeIntervalos) intervalos[indice] = intervalos[indice] + 1

Usamos a funo int para converter um nmero em ponto flutuante (float) para um inteiro. Existe a possibilidade deste clculo produzir um ndice que esteja fora dos limites (seja negativo ou maior que len(intervalos)-1)? Uma lista como intervalos que contm uma contagem do nmero de valores em cada intervalo chamada de histograma. Como exerccio, escreva uma funo chamada ``histograma`` que receba uma lista e um nmero de intervalos como argumentos e retorne um histograma com o nmero de intervalos solicitado.

9.9 Glossrio

tipo imutvel (immutable type) Um tipo de elemento que no pode ser modificado. Atribuies a um elemento ou "fatiamento (slices)" XXX aos tipos imutveis causaro erro. tipo mutvel (mutable type) Tipo de dados onde os elementos podem ser modificados. Todos os tipos mutveis, so tipos compostos. Listas e dicionrios so exemplos de tipos de dados mutveis. String e tuplas no so. tupla (tuple)

Tipo sequencial similar as listas com exceo de que ele imutvel. Podem ser usadas Tuplas sempre que um tipo imutvel for necessrio, por exemplo uma "chave (key)" em um dicionrio Atribuio a tupla (tuple assignment) Atribuio a todos os elementos de uma tupla feita num nico comando de atribuo. A atribuio aos elementos ocorre em paralelo, e no em sequncia, tornando esta operao til para swap, ou troca recproca de valores entre variveis (ex: a,b=b,a). determinstico (deterministic) Um programa que realiza a mesma coisa sempre que executado. pseudo aleatrio (pseudorandom) Uma sequncia de nmeros que parecem ser aleatrios mas so na verdade o resultado de uma computao "determinstica" histograma (histogram) Uma lista de inteiros na qual cada elemento conta o nmero de vezes que algo acontece. casamento de padro XXX (pattern matching) Um programa desenvolvido que envolve identificar um teste padro computacional familiar e copiar a soluo para um problema similar. System Message: WARNING/2 (<string>, line 11485) Block quote ends without a blank line; unexpected unindent.

Captulo 10: Dicionrios


Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio

o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos o 3.4 Funes matemticas o 3.5 Composio o 3.6 Adicionando novas funes o 3.7 Definies e uso o 3.8 Fluxo de execuo o 3.9 Parmetros e argumentos o 3.10 Variveis e parmetros so locais o 3.11 Diagramas da pilha o 3.12 Funes com resultados o 3.13 Glossrio Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return

4.9 Recursividade 4.10 Diagramas de pilha para funes recursivas 4.11 Recursividade infinita 4.12 Entrada pelo teclado 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas
o o o o o

Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores Os tipos compostos que voce aprendeu - strings, listas e tuplas - utilizam inteiros como indices. Se voce tentar utilizar qualquer outro tipo como indice, voce receber um erro. Dicionrios sao similiares a outros tipos compostos exceto por eles poderem user qualquer tipo imutavel de dados como indice. Como exemplo, nos criaremos um dicionrio para traduzir palavras em Ingls para Espanhol. Para esse dicionrio, os indices sero strings. Uma maneira de criar um dicionario comecando com um dicionrio vazio e depois adiconando elementos. Um dicionrio vazio denotado {}:
>>> eng2sp = {} >>> eng2sp['one'] = 'uno' >>> eng2sp['two'] = 'dos'

A primeira atribuio cria um dicionario chamado eng2sp; as outras atribuies adicionam novos elementos para o dicionrio. Nos podemos imprimir o valor corrente de um dicionario da maneira usual:
>>> print eng2sp

{'one': 'uno', 'two': 'dos'} Os elementos de um dicionrio aparecem em uma lista separada por vrgulas. Cada entrada contm um indice e um valor separado por dois-pontos. Em um dicionrio, os ndices sao chamados de chaves, entao os elementos so chamados de pares chave-valor. Outra maneira de criar dicionrios fornecendo uma lista de pares chavesvalor utilizando a mesma sintaxe da ltima sada.
>>> eng2sp = {'one': 'uno', 'two': 'dos', 'three': 'tres'}

Se nos imprimirmos o valor de eng2sp novamente, nos teremos uma surpresa:


>>> print eng2sp

{'one': 'uno', 'three': 'tres', 'two': 'dos'} Os pares chave-valor no esto em ordem! Felizmente, no a motivos para se preocupar com a ordem, desde que os elementos do dicionrio nunca sejam indexados com indices inteiros. Podemos usar as chaves para buscar os

valores correspondentes:
>>> print eng2sp['two']

'dos' A chave 'two' retornou o valor 'dos' mesmo pensando que retornaria o terceiro par chave-valor.

10.1 Operaes dos Dicionrios

O comando del remove um par chave-valor de um dicionrio. Por exemplo, o dicionrio abaixo contem os nomes de varias frutas e o numero de cada fruta em no estoque:
>>> inventario = {'maas': 430, 'bananas': 312, 'laranjas': 525, 'peras': 217} >>> print inventario

{'laranjas': 525, 'maas': 430, 'peras': 217, 'bananas': 312} Se alguem comprar todas as peras, podemos remover a entrada do dicionrio:
>>> del inventario['peras'] >>> print inventario

{'laranjas': 525, 'maas': 430, 'bananas': 312} Ou se ns esperamos por mais peras em breve, nos podemos simplesmente trocar o valor associoado as peras:
>>> inventario['peras'] = 0 >>> print inventario

{'laranjas': 525, 'maas': 430, 'peras': 0, 'bananas': 312} A funo len tambm funciona com dicionrios; retornando o nmero de pares chave-valor:
>>> len(inventario)

10.2 Mtodos dos Dicionrios

Um mtodo parecido com uma funo - possui parametros e retorna valores - mas a sintaxe diferente. Por exemplo, o metodo keys recebe um dicionrio e retorna uma lista com as chaves, mas em vez de usarmos a sintaxe das funes keys(eng2sp), nos usamos a sintaxe dos mtodos eng2sp.keys().
>>> eng2sp.keys()

['one', 'three', 'two'] Dessa forma o ponto especifica o nome da funo, keys, e o nome do objeto em que deve ser aplicada a funo, eng2sp. Os parenteses indicam que esse mtodo no possui parameteros. Ao invs de chamarmos um mtodo, dizemos que ele invocado, nesse caso, ns podemos dizer que ns estamos invocando keys do objeto eng2sp. O mtodo values parecido; retorna a lista de valores de um dicionrio:
>>> eng2sp.values()

['uno', 'tres', 'dos'] O mtodo items retorna os dois, na forma de uma lista de tuplas - cada tupla com um par chave-valor:
>>> eng2sp.items()

[('one','uno'), ('three','tres'), ('two','dos')] A sintaxe fornece uma informao util. Os colchetes indicam que isso uma lista. Os parentses indicam que os elementos da lista so tuplas. Se o mtodo recebe de algum parmetro, se utiliza a mesma sintaxe das funes. Por exemplo, o mtodo has_key recebe uma chave e retorna verdadeiro (1) se a chave existe no dicionrio:
>>> eng2sp.has_key('one')

1
>>> eng2sp.has_key('deux')

0 Se voce tentar chamar um mtodo sem especificar em qual objeto, voce obter um erro. Nesse caso, a mensagem de erro no muito til:
>>> has_key('one')

NameError: has_key

10.3 Aliasing (XXX) e Copiar

Uma vez que os dicionrios so mutveis, voce precisa saber sobre Aliasing. Sempre que duas variveis referenciarem o mesmo objeto, quando uma alterada, afeta a outra. Se voc quer modificar um dicionrio e continuar com uma copia original, utilize o mtodo copy. Por exemplo, opposites um dicionrio que contm pares de antnimos.
>>> opposites = {'up': 'down', 'right': 'wrong', 'true': 'false'} >>> alias = opposities >>> copy = opposities.copy()

alias e opossites se referem ao mesmo objeto; copy se refere a um novo objeto igual ao dicionrio opossites. Se voc modificar o alias, opossites tambm ser alterado.
>>> alias['right'] = 'left' >>> opossites['right']

'left' Se modificarmos copy, opossites no ser modificado:


>>> copy['right'] = 'privilege' >>> opposites['right']

'left'

10.4 Matrizes Esparsas

Na seo 8.14, ns usamos uma lista de listas para representar uma matriz. Essa uma boa escolha se a matriz for principalmente de valores diferentes de zero, mas considerando uma matriz esparsa como essa: LINK DA MATRIZ Uma representao usando uma lista contem muitos zeros:

>>> matriz = [ [0,0,0,1,0],

[0,0,0,0,0], [0,2,0,0,0], [0,0,0,0,0], [0,0,0,3,0] ] Uma alternativa usarmos um dicionrio. Para as chaves, ns podemos usar tuplas que contm os nmeros da linha e a coluna. Abaixo uma representao em um dicinario da mesma matriz:
>>> matriz = {(0,3): 1, (2, 1): 2, (4, 3): 3}

Ns precisamos apenas de trs pares chave-valor, cada um sendo um elemento diferente de zero da matriz. Cada chave uma tupla, e cada valor um nmero inteiro. Para acessarmos um elemento da matriz, nos utilizamos o operador []:
>>> matriz[0,3]

1 Note que a sintaxe da representao de um dicionrio no a mesma que a sintaxe usada pela representao pelas listas. Em vez de usarmos dois ndices inteiros, ns usamos apenas um ndice, que uma tupla de inteiros. Mas existe um problema. Se tentarmos buscar um elemento zero, obteremos um erro, pois no existe uma entrada no dicionrio para a chave especificada:
>>> matriz[1,3]

KeyError: (1,3) O mtodo get resolve esse problema:


>>> matriz.get((0,3), 0)

1 O primeiro parmetro a chave; o segundo o valor que get retornar caso no existe a chave no dicionrio:
>>> matriz.get((1,3), 0)

0 get definitivamente melhora a semntica e a sintaxe do acesso a matrizes

esparsas.

10.5 Hint

Se voc brincou com a funo fibonacci da seo 5.7, provvel que voc notou que quanto maior o nmero passado para a funo, mais tempo a funo demora para executar. Alm disso, o tempo da execuo aumenta rapidamente. Em uma das nossas mquinas, fibonacci(20) executa instantaneamente, fibonacci(30) demora cerca de um segundo, e fibonacci(40) demora uma eternidade. Para entender o porque, considere o grfico de chamadas para fibonacci com n=4: LINK PARA A FIGURA O grfico mostra a estrutura da funo, com linhas conectando cada execuo com a execuo que a chamou. No topo do grfico, fibonacci tem n=4, que chama fibonacci com n=3 e n=2. Em seguida, fibonacci com n=3 chama fibonacci com n=2 e n=1. E assim por diante. Conte quantas vezes fibonacci(0) e fibonacci(1) so chamadas. Essa uma soluo ineficiente para o problema, e torna-se pior quando o parmetro recebido um nmero maior. Uma boa soluo guardar os valores que ja foram calculados armazenandoos em um dicionrio. Um valor prviamente calculado que guardado para ser utilizado mais tarde chamado de hint. Abaixo uma implementao de fibonacci usando hints:
>>> previous = {0:1, 1:1} >>> def fibonacci(n):

if previous.has_key(n): return previous[n] else: newValue = fibonacci(n-1) + fibonacci(n-2) previous[n] = newValue return newValue O dicionrio chamado previous guarda os nmeros de Fibonacci que ns ja

conhecemos. Ele comea com apenas dois pares: 0 possui 1; e 1 possui 1. Sempre que fibonacci chamada, ela verifica o dicionrio para determinar se ele j possui o resultado. Se o resultado estiver ali, a funo pode retornar imediatamente sempre precisar fazer mais chamadas recursivas. Se o resultado no estiver ali, ele calculado no newValue. O valor de newValue adicionado no dicionrio antes da funo retornar. Usando essa verso de fibonacci, nossa mquina consegue calcular fibonacci(40) em um piscar de olhos. Mas quando tentamos calcular fibonacci(50), ns veremos um problema diferente:
>>> fibonacci(50)

OverflowError: integer addition A resposta, que voc ver em um minuto, 20.365.011.074. O problema que esse nmero muito grande para guardarmos como um inteiro do Python. Isso overflow. Felizmente, esse problema tem uma soluo simples.

10.6 Inteiros Longos

Python possui um tipo chamado long int que permite trabalharmos com qualquer tamanho de inteiros. Existem duas maneiras de criarmos um valor long int. A primeira escrever um inteiro seguido de um L no final:
>>> type(1L)

<type 'long int'> A outra maneira usarmos a funo long que converte um valor para um long int. long pode receber qualquer valor nmerico e at mesmo uma string de digitos:
>>> long(1)

1L
>>> long(3.9)

3L
>>> long('57')

57L

Todas as operaes matemticas funcionam com long int s, ento no precisamos modificar muito para adaptar fibonacci:
>>> previous = {0: 1L, 1:1L} >>> fibonacci(50)

20365011074L Somente trocando os valores iniciais de previous, conseguimos mudar o comportamento da fibonacci. Os dois primeiros numeros da sequncia so long ints, ento todos os nmeros subsequentes da sequncia tambm sero. Como exerccio, converta factorial para produzir um long int como resultado.

10.7 Contando Letras

No captulo 7, escrevemos uma funo que contava o nmero de ocorrncias de uma letra em uma string. A verso mais comum desse problema fazer um histograma das letras da string, ou seja, quantas vezes cada letra aparece na string. Um histograma pode ser util para comprimir um arquivo de texto. Pois diferentes letras aparecem com diferentes frequncias, podemos comprimir um arquivo usando pequenos cdigos para letras comuns e longos cdigos para letras que aparecem em menor frequncia. Dicionrios fornecem uma maneira elegante de gerar um histograma:
>>> letterCounts = {} >>> for letter in "Mississippi":

... letterCounts[letter] = letterCounts.get(letter,0) + 1 ...


>>> letterCounts

{'M': 1, 's': 4, 'p': 2, 'i': 4} Comeamos com um dicionrio vazio. Para cada letra da string, achamos o contador (possivelmente zero) e o incrementamos. No final, o dicionrio contem pares de letras e as suas frequncias. mais atraente mostrarmos o histograma na ordem alfabtica. Podemos fazer isso com os mtodos items e sort:
>>> letterItems = letterCounts.items() >>> letterItems.sort()

>>> print letterItems

[('M', 1), ('i', 4), ('p', 2), ('s', 4)] Voc ja tinha visto o mtodo items antes, mas sort o primeiro mtodo que voc se depara para aplicar em listas. Existem muitos outros mtodos de listas, incluindo append, extend, e reverse. Consulte a documentao do Python para maiores detalhes.

10.8 Glossrio

dicionrio (dictionary) Uma coleo de pares de chaves-valores que so mapeados pelas chaves, para se obter os valores. As chaves podem ser qualquer tipo de dados imutavel, e os valores podem ser de qualquer tipo. chave (key) Um valor que usado para buscar uma entrada em um dicionrio. par chave-valor (key-value pair) Um dos itens de um dicionrio. mtodo (method) Um tipo de funo que chamada com uma sintaxe diferente e invocada no contexto de um objeto. invocar (invoke) Chamar um mtodo. hint O armazenamento temporrio de um valor pr-computado para evitar a computao redundante. overflow Um resultado numrico que muito grande para ser representado no formato numrico.

Captulo 10: Dicionrios

System Message: INFO/1 (<string>, line 12067); backlink Duplicate implicit target name: "captulo 10: dicionrios". Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos o 3.4 Funes matemticas o 3.5 Composio o 3.6 Adicionando novas funes o 3.7 Definies e uso o 3.8 Fluxo de execuo o 3.9 Parmetros e argumentos o 3.10 Variveis e parmetros so locais o 3.11 Diagramas da pilha o 3.12 Funes com resultados o 3.13 Glossrio Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional

4.5 Execuo alternativa 4.6 Condicionais encadeados 4.7 Condicionais aninhados 4.8 A instruo return 4.9 Recursividade 4.10 Diagramas de pilha para funes recursivas 4.11 Recursividade infinita 4.12 Entrada pelo teclado 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas
o o o o o o o o o

Captulo 9: Tuplas Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores Os tipos compostos que voce aprendeu - strings, listas e tuplas - utilizam inteiros como indices. Se voce tentar utilizar qualquer outro tipo como indice, voce receber um erro. Dicionrios sao similiares a outros tipos compostos exceto por eles poderem user qualquer tipo imutavel de dados como indice. Como exemplo, nos criaremos um dicionrio para traduzir palavras em Ingls para Espanhol. Para esse dicionrio, os indices sero strings. Uma maneira de criar um dicionario comecando com um dicionrio vazio e depois adiconando elementos. Um dicionrio vazio denotado {}:
>>> eng2sp = {} >>> eng2sp['one'] = 'uno' >>> eng2sp['two'] = 'dos'

A primeira atribuio cria um dicionario chamado eng2sp; as outras atribuies adicionam novos elementos para o dicionrio. Nos podemos imprimir o valor corrente de um dicionario da maneira usual:
>>> print eng2sp

{'one': 'uno', 'two': 'dos'} Os elementos de um dicionrio aparecem em uma lista separada por vrgulas.

Cada entrada contm um indice e um valor separado por dois-pontos. Em um dicionrio, os ndices sao chamados de chaves, entao os elementos so chamados de pares chave-valor. Outra maneira de criar dicionrios fornecendo uma lista de pares chavesvalor utilizando a mesma sintaxe da ltima sada.
>>> eng2sp = {'one': 'uno', 'two': 'dos', 'three': 'tres'}

Se nos imprimirmos o valor de eng2sp novamente, nos teremos uma surpresa:


>>> print eng2sp

{'one': 'uno', 'three': 'tres', 'two': 'dos'} Os pares chave-valor no esto em ordem! Felizmente, no a motivos para se preocupar com a ordem, desde que os elementos do dicionrio nunca sejam indexados com indices inteiros. Podemos usar as chaves para buscar os valores correspondentes:
>>> print eng2sp['two']

'dos' A chave 'two' retornou o valor 'dos' mesmo pensando que retornaria o terceiro par chave-valor.

10.1 Operaes dos Dicionrios

O comando del remove um par chave-valor de um dicionrio. Por exemplo, o dicionrio abaixo contem os nomes de varias frutas e o numero de cada fruta em no estoque:
>>> inventario = {'maas': 430, 'bananas': 312, 'laranjas': 525, 'peras': 217} >>> print inventario

{'laranjas': 525, 'maas': 430, 'peras': 217, 'bananas': 312} Se alguem comprar todas as peras, podemos remover a entrada do dicionrio:
>>> del inventario['peras'] >>> print inventario

{'laranjas': 525, 'maas': 430, 'bananas': 312} Ou se ns esperamos por mais peras em breve, nos podemos simplesmente

trocar o valor associoado as peras:


>>> inventario['peras'] = 0 >>> print inventario

{'laranjas': 525, 'maas': 430, 'peras': 0, 'bananas': 312} A funo len tambm funciona com dicionrios; retornando o nmero de pares chave-valor:
>>> len(inventario)

10.2 Mtodos dos Dicionrios

Um mtodo parecido com uma funo - possui parametros e retorna valores - mas a sintaxe diferente. Por exemplo, o metodo keys recebe um dicionrio e retorna uma lista com as chaves, mas em vez de usarmos a sintaxe das funes keys(eng2sp), nos usamos a sintaxe dos mtodos eng2sp.keys().
>>> eng2sp.keys()

['one', 'three', 'two'] Dessa forma o ponto especifica o nome da funo, keys, e o nome do objeto em que deve ser aplicada a funo, eng2sp. Os parenteses indicam que esse mtodo no possui parameteros. Ao invs de chamarmos um mtodo, dizemos que ele invocado, nesse caso, ns podemos dizer que ns estamos invocando keys do objeto eng2sp. O mtodo values parecido; retorna a lista de valores de um dicionrio:
>>> eng2sp.values()

['uno', 'tres', 'dos'] O mtodo items retorna os dois, na forma de uma lista de tuplas - cada tupla com um par chave-valor:
>>> eng2sp.items()

[('one','uno'), ('three','tres'), ('two','dos')] A sintaxe fornece uma informao util. Os colchetes indicam que isso uma

lista. Os parentses indicam que os elementos da lista so tuplas. Se o mtodo recebe de algum parmetro, se utiliza a mesma sintaxe das funes. Por exemplo, o mtodo has_key recebe uma chave e retorna verdadeiro (1) se a chave existe no dicionrio:
>>> eng2sp.has_key('one')

1
>>> eng2sp.has_key('deux')

0 Se voce tentar chamar um mtodo sem especificar em qual objeto, voce obter um erro. Nesse caso, a mensagem de erro no muito til:
>>> has_key('one')

NameError: has_key

10.3 Aliasing (XXX) e Copiar

Uma vez que os dicionrios so mutveis, voce precisa saber sobre Aliasing. Sempre que duas variveis referenciarem o mesmo objeto, quando uma alterada, afeta a outra. Se voc quer modificar um dicionrio e continuar com uma copia original, utilize o mtodo copy. Por exemplo, opposites um dicionrio que contm pares de antnimos.
>>> opposites = {'up': 'down', 'right': 'wrong', 'true': 'false'} >>> alias = opposities >>> copy = opposities.copy()

alias e opossites se referem ao mesmo objeto; copy se refere a um novo objeto igual ao dicionrio opossites. Se voc modificar o alias, opossites tambm ser alterado.
>>> alias['right'] = 'left' >>> opossites['right']

'left' Se modificarmos copy, opossites no ser modificado:


>>> copy['right'] = 'privilege'

>>> opposites['right']

'left'

10.4 Matrizes Esparsas

Na seo 8.14, ns usamos uma lista de listas para representar uma matriz. Essa uma boa escolha se a matriz for principalmente de valores diferentes de zero, mas considerando uma matriz esparsa como essa: LINK DA MATRIZ Uma representao usando uma lista contem muitos zeros:
>>> matriz = [ [0,0,0,1,0],

[0,0,0,0,0], [0,2,0,0,0], [0,0,0,0,0], [0,0,0,3,0] ] Uma alternativa usarmos um dicionrio. Para as chaves, ns podemos usar tuplas que contm os nmeros da linha e a coluna. Abaixo uma representao em um dicinario da mesma matriz:
>>> matriz = {(0,3): 1, (2, 1): 2, (4, 3): 3}

Ns precisamos apenas de trs pares chave-valor, cada um sendo um elemento diferente de zero da matriz. Cada chave uma tupla, e cada valor um nmero inteiro. Para acessarmos um elemento da matriz, nos utilizamos o operador []:
>>> matriz[0,3]

1 Note que a sintaxe da representao de um dicionrio no a mesma que a sintaxe usada pela representao pelas listas. Em vez de usarmos dois ndices inteiros, ns usamos apenas um ndice, que uma tupla de inteiros. Mas existe um problema. Se tentarmos buscar um elemento zero, obteremos

um erro, pois no existe uma entrada no dicionrio para a chave especificada:


>>> matriz[1,3]

KeyError: (1,3) O mtodo get resolve esse problema:


>>> matriz.get((0,3), 0)

1 O primeiro parmetro a chave; o segundo o valor que get retornar caso no existe a chave no dicionrio:
>>> matriz.get((1,3), 0)

0 get definitivamente melhora a semntica e a sintaxe do acesso a matrizes esparsas.

10.5 Hint

Se voc brincou com a funo fibonacci da seo 5.7, provvel que voc notou que quanto maior o nmero passado para a funo, mais tempo a funo demora para executar. Alm disso, o tempo da execuo aumenta rapidamente. Em uma das nossas mquinas, fibonacci(20) executa instantaneamente, fibonacci(30) demora cerca de um segundo, e fibonacci(40) demora uma eternidade. Para entender o porque, considere o grfico de chamadas para fibonacci com n=4: LINK PARA A FIGURA O grfico mostra a estrutura da funo, com linhas conectando cada execuo com a execuo que a chamou. No topo do grfico, fibonacci tem n=4, que chama fibonacci com n=3 e n=2. Em seguida, fibonacci com n=3 chama fibonacci com n=2 e n=1. E assim por diante. Conte quantas vezes fibonacci(0) e fibonacci(1) so chamadas. Essa uma soluo ineficiente para o problema, e torna-se pior quando o parmetro recebido um nmero maior. Uma boa soluo guardar os valores que ja foram calculados armazenando-

os em um dicionrio. Um valor prviamente calculado que guardado para ser utilizado mais tarde chamado de hint. Abaixo uma implementao de fibonacci usando hints:
>>> previous = {0:1, 1:1} >>> def fibonacci(n):

if previous.has_key(n): return previous[n] else: newValue = fibonacci(n-1) + fibonacci(n-2) previous[n] = newValue return newValue O dicionrio chamado previous guarda os nmeros de Fibonacci que ns ja conhecemos. Ele comea com apenas dois pares: 0 possui 1; e 1 possui 1. Sempre que fibonacci chamada, ela verifica o dicionrio para determinar se ele j possui o resultado. Se o resultado estiver ali, a funo pode retornar imediatamente sempre precisar fazer mais chamadas recursivas. Se o resultado no estiver ali, ele calculado no newValue. O valor de newValue adicionado no dicionrio antes da funo retornar. Usando essa verso de fibonacci, nossa mquina consegue calcular fibonacci(40) em um piscar de olhos. Mas quando tentamos calcular fibonacci(50), ns veremos um problema diferente:
>>> fibonacci(50)

OverflowError: integer addition A resposta, que voc ver em um minuto, 20.365.011.074. O problema que esse nmero muito grande para guardarmos como um inteiro do Python. Isso overflow. Felizmente, esse problema tem uma soluo simples.

10.6 Inteiros Longos

Python possui um tipo chamado long int que permite trabalharmos com qualquer tamanho de inteiros. Existem duas maneiras de criarmos um valor long int. A primeira escrever um inteiro seguido de um L no final:

>>> type(1L)

<type 'long int'> A outra maneira usarmos a funo long que converte um valor para um long int. long pode receber qualquer valor nmerico e at mesmo uma string de digitos:
>>> long(1)

1L
>>> long(3.9)

3L
>>> long('57')

57L Todas as operaes matemticas funcionam com long int s, ento no precisamos modificar muito para adaptar fibonacci:
>>> previous = {0: 1L, 1:1L} >>> fibonacci(50)

20365011074L Somente trocando os valores iniciais de previous, conseguimos mudar o comportamento da fibonacci. Os dois primeiros numeros da sequncia so long ints, ento todos os nmeros subsequentes da sequncia tambm sero. Como exerccio, converta factorial para produzir um long int como resultado.

10.7 Contando Letras

No captulo 7, escrevemos uma funo que contava o nmero de ocorrncias de uma letra em uma string. A verso mais comum desse problema fazer um histograma das letras da string, ou seja, quantas vezes cada letra aparece na string. Um histograma pode ser util para comprimir um arquivo de texto. Pois diferentes letras aparecem com diferentes frequncias, podemos comprimir um arquivo usando pequenos cdigos para letras comuns e longos cdigos para letras que aparecem em menor frequncia. Dicionrios fornecem uma maneira elegante de gerar um histograma:

>>> letterCounts = {} >>> for letter in "Mississippi":

... letterCounts[letter] = letterCounts.get(letter,0) + 1 ...


>>> letterCounts

{'M': 1, 's': 4, 'p': 2, 'i': 4} Comeamos com um dicionrio vazio. Para cada letra da string, achamos o contador (possivelmente zero) e o incrementamos. No final, o dicionrio contem pares de letras e as suas frequncias. mais atraente mostrarmos o histograma na ordem alfabtica. Podemos fazer isso com os mtodos items e sort:
>>> letterItems = letterCounts.items() >>> letterItems.sort() >>> print letterItems

[('M', 1), ('i', 4), ('p', 2), ('s', 4)] Voc ja tinha visto o mtodo items antes, mas sort o primeiro mtodo que voc se depara para aplicar em listas. Existem muitos outros mtodos de listas, incluindo append, extend, e reverse. Consulte a documentao do Python para maiores detalhes.

10.8 Glossrio

dicionrio (dictionary) Uma coleo de pares de chaves-valores que so mapeados pelas chaves, para se obter os valores. As chaves podem ser qualquer tipo de dados imutavel, e os valores podem ser de qualquer tipo. chave (key) Um valor que usado para buscar uma entrada em um dicionrio. par chave-valor (key-value pair) Um dos itens de um dicionrio. mtodo (method)

Um tipo de funo que chamada com uma sintaxe diferente e invocada no contexto de um objeto. invocar (invoke) Chamar um mtodo. hint (hint) O armazenamento temporrio de um valor pr-computado para evitar a computao redundante. overflow (overflow) Um resultado numrico que muito grande para ser representado no formato numrico. System Message: WARNING/2 (<string>, line 12644) Block quote ends without a blank line; unexpected unindent.

Captulo 11: Arquivos e excees


Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 3: Funes

3.1 Chamadas de funes 3.2 Converso entre tipos 3.3 Coero entre tipos 3.4 Funes matemticas 3.5 Composio 3.6 Adicionando novas funes 3.7 Definies e uso 3.8 Fluxo de execuo 3.9 Parmetros e argumentos 3.10 Variveis e parmetros so locais 3.11 Diagramas da pilha 3.12 Funes com resultados 3.13 Glossrio Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo
o o o o o o o o o o o o o

5.8 Checagem de tipos 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores
o o

Arquivos e excees

Durante a execuo de um programa, seus dados ficam na memria. Quando o programa termina, ou o computador desligado, os dados na memria

desaparecem. Para armazenar os dados permanentemente, voc tem que coloc-los em um arquivo. Arquivos usualmente so guardados em um disco rgido (HD), num disquete ou em um CD-ROM. Quando existe um nmero muito grande de arquivos, eles muitas vezes so organizados dentro de diretrios (tambm chamados de ?pastas? ou ainda ?*folders*?). Cada arquivo identificado por um nome nico, ou uma combinao de um nome de arquivo com um nome de diretrio. Lendo e escrevendo em arquivos, os programas podem trocar informaes uns com os outros e gerar formatos imprimveis como PDF. Trabalhar com arquivos muito parecido com trabalhar com livros. Para utilizar um livro, voc tem que abr-lo. Quando voc termina, voc tem que fech-lo. Enquanto o livro estiver aberto, voc pode tanto l-lo quanto escrever nele. Em qualquer caso, voc sabe onde voc est situado no livro. Na maioria das vezes, voc l o livro inteiro em sua ordem natural, mas voc tambm pode saltar atravs de alguns trechos (skip around). Tudo isso se aplica do mesmo modo a arquivos. Para abrir um arquivo, voc especifica o nome dele e indica o que voc quer, seja ler ou escrever (gravar). Abrir um arquivo cria um objeto arquivo. Neste exemplo, a varivel f se referencia ao novo objeto arquivo.
>>> f = open("teste.dat", "w") >>> print f <open file "teste.dat", mode "w" at fe820>

A funo open recebe dois argumentos. O primeiro o nome do arquivo, e o segundo o modo. Modo ?w? significa que estamos abrindo o arquivo para gravao (?*write*?, escrever). Se no existir nenhum arquivo de nome teste.dat, ele ser criado. Se j existir um, ele ser substitudo pelo arquivo que estamos gravando (ou escrevendo). Quando executamos um comando print sobre o objeto arquivo, visualizamos o nome do arquivo, o modo e a localizao do objeto na memria. Para colocar dados dentro do arquivo, invocamos o mtodo write do objeto arquivo:
>>> f.write("Agora hora") >>> f.write("de fechar o arquivo")

Fechar o arquivo diz ao sistema que terminamos de escrever (gravar) e que o arquivo est livre para ser lido:

>>> f.close()

Agora podemos abrir o arquivo de novo, desta vez para leitura, e ler o seu contedo para uma string. Desta vez, o argumento modo ?r? para leitura (?reading?):
>>> f = open("teste.dat", "r")

Se tentarmos abrir um arquivo que no existe, temos um erro:


>>> f = open("teste.cat", "r") IOError: [Errno 2] No such file or directory: 'teste.cat'

Sem nenhuma surpresa, o mtodo read l dados do arquivo. Sem argumentos, ele l todo o contedo do arquivo:
>>> texto = f.read() >>> print texto Agora horade fechar o arquivo

No existe espao entre ?hora? e ?de? porque ns no gravamos um espao entre as strings. read tambm pode receber um argumento que indica quantos caracteres ler:
>>> f = open("teste.dat", "r") >>> print f.read(9) Agora h

Se no houver caracteres suficientes no arquivo, read retorna os caracteres restantes. Quando chegamos ao final do arquivo, read retorna a string vazia:
>>> print f.read(1000006) orade fechar o arquivo >>> print f.read()

>>>

A funo seguinte, copia um arquivo, lendo e gravando at cinqenta caracteres de uma vez. O primeiro argumento o nome do arquivo original; o segundo o nome do novo arquivo:
def copiaArquivo(velhoArquivo, novoArquivo): f1 = open(velhoArquivo, "r")

f2 = open(novoArquivo, "w") while 1: texto = f1.read(50) if texto == "": break f2.write(texto) f1.close() f2.close() return

A comando break novo. O que ele faz saltar a execuo para fora do loop; o fluxo de execuo passa para o primeiro comando depois do loop. Neste exemplo, o loop while infinito porque o valor 1 sempre verdadeiro. O nico modo de sair do loop executando o break, o que ocorre quando texto a string vazia, o que ocorre quando alcanamos o fim do arquivo.

11.1 Arquivos texto

Um arquivo texto um arquivo que contm caracteres imprimveis e espaos, organizados dentro de linhas separadas por caracteres de nova linha. J que Pyhton especialmente projetado para processar arquivos texto, ele oferece mtodos que tornam esta tarefa mais fcil. Para demonstrar, vamos criar um arquivo texto com trs linhas de texto separadas por caracteres de nova linha:
>>> f = open("teste.dat", "w") >>> f.write("linha um\nlinha dois\nlinha trs\n") >>> f.close()

O mtodo readline l todos os caracteres at, e incluindo, o prximo caractere de nova linha:
>>> f = open("teste.dat", "r") >>> print f.readline() linha um

>>>

readlines retorna todas as linhas restantes como uma lista de strings:


>>> print f.readlines() ['linha dois\012', 'linha trs\012']

Neste caso, a sada est em formado de lista, o que significa que as strings aparecem entre aspas e o caractere de nova linha aparece como a seqncia de escape 012. No fim do arquivo, readline retorna a string vazia e readlines retorna a lista vazia:
>>> print f.readline()

>>> print f.readlines() []

A seguir temos um exemplo de um programa de processamento de linhas. filtraArquivo faz uma cpia de velhoArquivo, omitindo quaisquer linhas que comecem por #:
def filtraArquivo(velhoArquivo, novoArquivo): f1 = open(velhoArquivo, "r") f2 = open(novoArquivo, "w") while 1: texto = f1.readline() if texto == "": break if texto[0] == '#': continue f2.write(texto) f1.close() f2.close() return

O comando continue termina a iterao corrente do loop, mas continua

iterando o loop. O fluxo de execuo passa para o topo do loop, checa a condio e prossegue conforme o caso. Assim, se texto for a string vazia, o loop termina. Se o primeiro caractere de texto for o jogo da velha (? # ?), o fluxo de execuo passa para o topo do loop. Somente se ambas as condies falharem que texto ser copiado para dentro do novo arquivo.

11.2 Gravando variveis

O argumento de write tem que ser uma string, assim se quisermos colocar outros valores em um arquivo, temos de convert-los para strings primeiro. A maneira mais fcil de fazer isso com a funo str:
>>> x = 52 >>> f.write(str(x))

Uma alternativa usar o operador de formatao %. Quando aplicado a inteiros, % o operador mdulo. Mas quando o primeiro operador uma string, % o operador de formatao. O primeiro operando a string de formatao, e o segundo operando uma tupla de expresses. O resultado uma string que contm os valores das expresses, formatadas de acordo com a string de formatao. Num exemplo simples, a seqncia de formatao "??%d??" significa que a primeira expresso na tupla deve ser formatada como um inteiro. Aqui a letra d representa ?decimal?.
>>> carros = 52 >>> "%d" % carros '52'

O resultado a string ?52?, que no deve ser confundida com o valor inteiro 52. Uma seqncia de formatao pode aparecer em qualquer lugar na string de formatao, assim, podemos embutir um valor em uma seqncia:
>>> carros = 52 >>> "Em julho vendemos %d carros." % carros 'Em julho vendemos 52 carros.'

A seqncia de formatao "%f" formata o prximo item da tupla como um nmero em ponto flutuante, e "%s" formata o prximo como uma string:
>>> "Em %d dias fizemos %f milhes %s." % (34,6.1,'reais') 'Em 34 dias fizemos 6.100000 milhes de reais.'

Por padro, o formato de ponto flutuante exibe seis casas decimais. O nmero de expresses na tupla tem que ser igual ao nmero de seqncias de formatao na string. Alm disso, os tipos das expresses tm que iguais aos da seqncia de formatao:
>>> "%d %d %d" % (1,2) TypeError: not enough arguments for format string >>> "%d" % 'reais' TypeError: illegal argument type for built-in operation

No primeiro exemplo, no existem expresses suficientes; no segundo, a expresso do tipo errado. Para um controle maior na formatao de nmeros, podemos especificar o nmero de dgitos como parte da seqncia de formatao:
>>> "%6d" % 62 ' 62'

>>> "%12f" % 6.1 ' 6,100000'

O nmero depois do sinal de porcentagem o nmero mnimo de espaos que o valor ocupar. Se o valor fornecido tiver um nmero menor de dgitos, espaos em branco sero adicionados antes para preencher o restante. Se o nmero de espaos for negativo, os espaos sero adicionados depois:
>>> "%-6d" % 62 '62 '

Para nmeros em ponto-flutuante, tambm podemos especificar o nmero de dgitos depois da vrgula:
>>> "%12.2f" % 6.1 ' 6.10'

Neste exemplo, o resultado reserva 12 espaos e inclui dois dgitos depois da vrgula. Esta formatao til para exibir valores monetrios com os centavos

alinhados. Por exemplo, imagine um dicionrio que contm nomes de estudantes como chaves e salrios-hora como valores. Aqui est uma funo que imprime o contedo do dicionrio como um relatrio formatado:
def relatorio(salarios): estudantes = salarios.keys() estudantes.sort() for estudante in estudantes: print "%-20s %12.02f" % (estudante, salarios[estudante])

Para testar esta funo, criaremos um pequeno dicionrio e imprimiremos o contedo:


>>> salarios = {'maria': 6.23, 'joo': 5.45, 'josu': 4.25} >>> relatorio(salarios) joo josu maria 5.45 4.25 6.23

Controlando a largura de cada valor, podemos garantir que as colunas ficaro alinhadas, desde que os nomes contenham menos que vinte e um caracteres e os salrios sejam menores do que um bilho de reais por hora.

11.3 Diretrios

Quando voc cria um novo arquivo abrindo-o e escrevendo nele, o novo arquivo fica no diretrio corrente (seja l onde for que voc esteja quando rodar o programa). Do mesmo modo, quando voc abre um arquivo para leitura, Python procura por ele no diretrio corrente. Se voc quiser abrir um arquivo que esteja em algum outro lugar, voc tem que especificar o caminho (path) para o arquivo, o qual o nome do diretrio (ou folder) onde o arquivo est localizado:
>>> f = open("/usr/share/dict/words", "r") >>> print f.readline() Aarhus

Este exemplo abre um arquivo chamado words que reside em um diretrio de nome dict, o qual reside em share, o qual reside em usr, o qual reside no diretrio de mais alto nvel do sistema, chamado /. Voc no pode usar / como parte do nome de um arquivo; ela um caractere reservado como um delimitador entre nomes de diretrios e nomes de arquivos. O arquivo /usr/share/dict/words contm uma lista de palavras em ordem alfabtica, na qual a primeira palavra o nome de uma universidade Dinamarquesa.

11.4 Pickling

Para colocar valores em um arquivo, voc tem que convert-los para strings. Voc j viu como fazer isto com str:
>>> f.write (str(12.3)) >>> f.write (str([1,2,3]))

O problema que quando voc l de volta o valor, voc tem uma string. O Tipo original da informao foi perdido. De fato, voc no pode sequer dizer onde comea um valor e termina outro:
>>> f.readline() ?12.3[1, 2, 3]?

A soluo o pickling, assim chamado porque ?preserva? estruturas de dados. O mdulo pickel contm os comandos necessrios. Para us-lo, importe pickle e ento abra o arquivo da maneira usual:
>>> import pickle >>> f = open(?test.pck?, ?w?)

Para armazenar uma estrutura de dados, use o mtodo dump e ento feche o arquivo do modo usual:
>>> pickle.dump(12.3, f) >>> pickle.dump([1,2,3], f) >>> f.close()

Ento, podemos abrir o arquivo para leitura e carregar as estruturas de dados

que foram descarregadas (dumped):


>>> f = open(?test.pck?, ?r?) >>> x = pickle.load(f) >>> x 12,3 >>> type(x) <type ?float?> >>> y = pickle.load(f) >>> y [1, 2, 3] >>> type(y) <type ?list?>

Cada vez que invocamos load, obtemos um nico valor do arquivo, completo com seu tipo original.

11.5 Excees

Whenever que um erro em tempo de execuo acontece, ele gera uma exceo. Usualmente, o programa pra e Python exibe uma mensagem de erro. Por exemplo, dividir por zero gera uma exceo:
>>> print 55/0 ZeroDivisionError: integer division or modulo

Do mesmo modo, acessar um item de lista inexistente:


>>> a = [] >>> print a[5] IndexError: list index out of range

Ou acessar uma chave que no est em um dicionrio:


>>> b = {}

>>> print b[?what?] KeyError: what

Em cada caso, a mensagem de erro tem duas partes: o tipo do erro antes dos dois pontos, e especificidades do erro depois dos dois pontos. Normalmente Python tambm exibe um ?*traceback*? de onde estava a execuo do programa, mas ns temos omitido esta parte nos exemplos. s vezes queremos executar uma operao que pode causar uma exceo, mas no queremos que o programa pare. Ns podemos tratar a exceo usando as instrues try e except. Por exemplo, podemos pedir ao usurio um nome de arquivo e ento tentar abr-lo. Se o arquivo no existe, no queremos que o programa trave; queremos tratar a exceo:
nomedoarquivo = raw_input(?Entre com o nome do arquivo: ?) try: f = open (nomedoarquivo, ?r?) except: print ?No existe arquivo chamado?, nomedoarquivo

A instruo try executa os comandos do primeiro bloco. Se no ocorrerem excees, ele ignora a instruo except. Se qualquer exceo acontece, ele executa os comandos do ramo except e continua. Podemos encapsular esta habilidade numa funo: existe toma um nome de arquivo e retorna verdadeiro se o arquivo existe e falso se no existe:
def existe(nomedoarquivo) try: f = open(nomedoarquivo) f.close() return 1 except: return 0

Voc pode usar mltiplos blocos except para tratar diferentes tipos de excees. O Manual de Referncia de Python (Python Reference Manual) tem os detalhes. Se o seu programa detecta uma condio de erro, voc pode faz-lo lanar uma exceo. Aqui est um exemplo que toma uma entrada do usurio e testa

se o valor 17. Supondo que 17 no seja uma entrada vlida por uma razo qualquer, ns lanamos uma exceo.
def entraNumero(): x = input (?Escolha um nmero: ?) if x == 17: raise ?ErroNumeroRuim?, ?17 um nmero ruim? return x

O comando raise toma dois argumentos: o tipo da exceo e informaes especficas sobre o erro. ErroNumeroRuim um novo tipo de exceo que ns inventamos para esta aplicao. Se a funo que chamou entraNumero trata o erro, ento o programa pode continuar; de outro modo, Pyhton exibe uma mensagem de erro e sai:
>>> entraNumero() Escolha um nmero: 17 ErroNumeroRuim: 17 um nmero ruim

A mensagem de erro inclui o tipo da exceo e a informao adicional que voc forneceu. Como um exerccio, escreva uma funo que use entraNumero para pegar um nmero do teclado e que trate a exceo ErroNumeroRuim.

11.6 Glossrio

arquivo (file) Uma entidade nomeada, usualmente armazenada em um disco rgido (HD), disquete ou CD-ROM, que contm uma seqncia de caracteres. diretrio (directory) Uma coleo nomeada de arquivos, tambm chamado de pasta ou folder. caminho (path) Uma seqncia de nomes de diretrios que especifica a exata localizao de um arquivo.

arquivo texto (text file) Um arquivo que contm caracteres organizados em linhas separadas por caracteres de nova linha. comando break (break statement) Um comando que fora a atual iterao de um loop a terminar. O fluxo de execuo vai para o topo do loop, testa a condio e prossegue conforme o caso.

Captulo 11: Arquivos e excees


System Message: INFO/1 (<string>, line 13395); backlink Duplicate implicit target name: "captulo 11: arquivos e excees". Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos o 3.4 Funes matemticas o 3.5 Composio

3.6 Adicionando novas funes 3.7 Definies e uso 3.8 Fluxo de execuo 3.9 Parmetros e argumentos 3.10 Variveis e parmetros so locais 3.11 Diagramas da pilha 3.12 Funes com resultados 3.13 Glossrio Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas
o o o o o o o o

5.3 Composio 5.4 Funes booleanas 5.5 Mais recursividade 5.6 Voto de confiana (Leap of faith) 5.7 Mais um exemplo 5.8 Checagem de tipos 5.9 Glossrio Captulo 6: Iterao Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores
o o o o o o o

Arquivos e excees

Durante a execuo de um programa, seus dados ficam na memria. Quando o programa termina, ou o computador desligado, os dados na memria desaparecem. Para armazenar os dados permanentemente, voc tem que coloc-los em um arquivo. Arquivos usualmente so guardados em um disco rgido (HD), num disquete ou em um CD-ROM. Quando existe um nmero muito grande de arquivos, eles muitas vezes so

organizados dentro de diretrios (tambm chamados de ?pastas? ou ainda ?*folders*?). Cada arquivo identificado por um nome nico, ou uma combinao de um nome de arquivo com um nome de diretrio. Lendo e escrevendo em arquivos, os programas podem trocar informaes uns com os outros e gerar formatos imprimveis como PDF. Trabalhar com arquivos muito parecido com trabalhar com livros. Para utilizar um livro, voc tem que abr-lo. Quando voc termina, voc tem que fech-lo. Enquanto o livro estiver aberto, voc pode tanto l-lo quanto escrever nele. Em qualquer caso, voc sabe onde voc est situado no livro. Na maioria das vezes, voc l o livro inteiro em sua ordem natural, mas voc tambm pode saltar atravs de alguns trechos (skip around). Tudo isso se aplica do mesmo modo a arquivos. Para abrir um arquivo, voc especifica o nome dele e indica o que voc quer, seja ler ou escrever (gravar). Abrir um arquivo cria um objeto arquivo. Neste exemplo, a varivel f se referencia ao novo objeto arquivo.
>>> f = open("teste.dat", "w") >>> print f <open file "teste.dat", mode "w" at fe820>

A funo open recebe dois argumentos. O primeiro o nome do arquivo, e o segundo o modo. Modo ?w? significa que estamos abrindo o arquivo para gravao (?*write*?, escrever). Se no existir nenhum arquivo de nome teste.dat, ele ser criado. Se j existir um, ele ser substitudo pelo arquivo que estamos gravando (ou escrevendo). Quando executamos um comando print sobre o objeto arquivo, visualizamos o nome do arquivo, o modo e a localizao do objeto na memria. Para colocar dados dentro do arquivo, invocamos o mtodo write do objeto arquivo:
>>> f.write("Agora hora") >>> f.write("de fechar o arquivo")

Fechar o arquivo diz ao sistema que terminamos de escrever (gravar) e que o arquivo est livre para ser lido:
>>> f.close()

Agora podemos abrir o arquivo de novo, desta vez para leitura, e ler o seu contedo para uma string. Desta vez, o argumento modo ?r? para leitura

(?reading?):
>>> f = open("teste.dat", "r")

Se tentarmos abrir um arquivo que no existe, temos um erro:


>>> f = open("teste.cat", "r") IOError: [Errno 2] No such file or directory: 'teste.cat'

Sem nenhuma surpresa, o mtodo read l dados do arquivo. Sem argumentos, ele l todo o contedo do arquivo:
>>> texto = f.read() >>> print texto Agora horade fechar o arquivo

No existe espao entre ?hora? e ?de? porque ns no gravamos um espao entre as strings. read tambm pode receber um argumento que indica quantos caracteres ler:
>>> f = open("teste.dat", "r") >>> print f.read(9) Agora h

Se no houver caracteres suficientes no arquivo, read retorna os caracteres restantes. Quando chegamos ao final do arquivo, read retorna a string vazia:
>>> print f.read(1000006) orade fechar o arquivo >>> print f.read()

>>>

A funo seguinte, copia um arquivo, lendo e gravando at cinqenta caracteres de uma vez. O primeiro argumento o nome do arquivo original; o segundo o nome do novo arquivo:
def copiaArquivo(velhoArquivo, novoArquivo): f1 = open(velhoArquivo, "r") f2 = open(novoArquivo, "w") while 1:

texto = f1.read(50) if texto == "": break f2.write(texto) f1.close() f2.close() return

A comando break novo. O que ele faz saltar a execuo para fora do loop; o fluxo de execuo passa para o primeiro comando depois do loop. Neste exemplo, o loop while infinito porque o valor 1 sempre verdadeiro. O nico modo de sair do loop executando o break, o que ocorre quando texto a string vazia, o que ocorre quando alcanamos o fim do arquivo.

11.1 Arquivos texto

Um arquivo texto um arquivo que contm caracteres imprimveis e espaos, organizados dentro de linhas separadas por caracteres de nova linha. J que Pyhton especialmente projetado para processar arquivos texto, ele oferece mtodos que tornam esta tarefa mais fcil. Para demonstrar, vamos criar um arquivo texto com trs linhas de texto separadas por caracteres de nova linha:
>>> f = open("teste.dat", "w") >>> f.write("linha um\nlinha dois\nlinha trs\n") >>> f.close()

O mtodo readline l todos os caracteres at, e incluindo, o prximo caractere de nova linha:
>>> f = open("teste.dat", "r") >>> print f.readline() linha um

>>>

readlines retorna todas as linhas restantes como uma lista de strings:


>>> print f.readlines() ['linha dois\012', 'linha trs\012']

Neste caso, a sada est em formado de lista, o que significa que as strings aparecem entre aspas e o caractere de nova linha aparece como a seqncia de escape 012. No fim do arquivo, readline retorna a string vazia e readlines retorna a lista vazia:
>>> print f.readline()

>>> print f.readlines() []

A seguir temos um exemplo de um programa de processamento de linhas. filtraArquivo faz uma cpia de velhoArquivo, omitindo quaisquer linhas que comecem por #:
def filtraArquivo(velhoArquivo, novoArquivo): f1 = open(velhoArquivo, "r") f2 = open(novoArquivo, "w") while 1: texto = f1.readline() if texto == "": break if texto[0] == '#': continue f2.write(texto) f1.close() f2.close() return

O comando continue termina a iterao corrente do loop, mas continua iterando o loop. O fluxo de execuo passa para o topo do loop, checa a condio e prossegue conforme o caso.

Assim, se texto for a string vazia, o loop termina. Se o primeiro caractere de texto for o jogo da velha (? # ?), o fluxo de execuo passa para o topo do loop. Somente se ambas as condies falharem que texto ser copiado para dentro do novo arquivo.

11.2 Gravando variveis

O argumento de write tem que ser uma string, assim se quisermos colocar outros valores em um arquivo, temos de convert-los para strings primeiro. A maneira mais fcil de fazer isso com a funo str:
>>> x = 52 >>> f.write(str(x))

Uma alternativa usar o operador de formatao %. Quando aplicado a inteiros, % o operador mdulo. Mas quando o primeiro operador uma string, % o operador de formatao. O primeiro operando a string de formatao, e o segundo operando uma tupla de expresses. O resultado uma string que contm os valores das expresses, formatadas de acordo com a string de formatao. Num exemplo simples, a seqncia de formatao "??%d??" significa que a primeira expresso na tupla deve ser formatada como um inteiro. Aqui a letra d representa ?decimal?.
>>> carros = 52 >>> "%d" % carros '52'

O resultado a string ?52?, que no deve ser confundida com o valor inteiro 52. Uma seqncia de formatao pode aparecer em qualquer lugar na string de formatao, assim, podemos embutir um valor em uma seqncia:
>>> carros = 52 >>> "Em julho vendemos %d carros." % carros 'Em julho vendemos 52 carros.'

A seqncia de formatao "%f" formata o prximo item da tupla como um nmero em ponto flutuante, e "%s" formata o prximo como uma string:

>>> "Em %d dias fizemos %f milhes %s." % (34,6.1,'reais') 'Em 34 dias fizemos 6.100000 milhes de reais.'

Por padro, o formato de ponto flutuante exibe seis casas decimais. O nmero de expresses na tupla tem que ser igual ao nmero de seqncias de formatao na string. Alm disso, os tipos das expresses tm que iguais aos da seqncia de formatao:
>>> "%d %d %d" % (1,2) TypeError: not enough arguments for format string >>> "%d" % 'reais' TypeError: illegal argument type for built-in operation

No primeiro exemplo, no existem expresses suficientes; no segundo, a expresso do tipo errado. Para um controle maior na formatao de nmeros, podemos especificar o nmero de dgitos como parte da seqncia de formatao:
>>> "%6d" % 62 ' 62'

>>> "%12f" % 6.1 ' 6,100000'

O nmero depois do sinal de porcentagem o nmero mnimo de espaos que o valor ocupar. Se o valor fornecido tiver um nmero menor de dgitos, espaos em branco sero adicionados antes para preencher o restante. Se o nmero de espaos for negativo, os espaos sero adicionados depois:
>>> "%-6d" % 62 '62 '

Para nmeros em ponto-flutuante, tambm podemos especificar o nmero de dgitos depois da vrgula:
>>> "%12.2f" % 6.1 ' 6.10'

Neste exemplo, o resultado reserva 12 espaos e inclui dois dgitos depois da vrgula. Esta formatao til para exibir valores monetrios com os centavos alinhados. Por exemplo, imagine um dicionrio que contm nomes de estudantes como chaves e salrios-hora como valores. Aqui est uma funo que imprime o

contedo do dicionrio como um relatrio formatado:


def relatorio(salarios): estudantes = salarios.keys() estudantes.sort() for estudante in estudantes: print "%-20s %12.02f" % (estudante, salarios[estudante])

Para testar esta funo, criaremos um pequeno dicionrio e imprimiremos o contedo:


>>> salarios = {'maria': 6.23, 'joo': 5.45, 'josu': 4.25} >>> relatorio(salarios) joo josu maria 5.45 4.25 6.23

Controlando a largura de cada valor, podemos garantir que as colunas ficaro alinhadas, desde que os nomes contenham menos que vinte e um caracteres e os salrios sejam menores do que um bilho de reais por hora.

11.3 Diretrios

Quando voc cria um novo arquivo abrindo-o e escrevendo nele, o novo arquivo fica no diretrio corrente (seja l onde for que voc esteja quando rodar o programa). Do mesmo modo, quando voc abre um arquivo para leitura, Python procura por ele no diretrio corrente. Se voc quiser abrir um arquivo que esteja em algum outro lugar, voc tem que especificar o caminho (path) para o arquivo, o qual o nome do diretrio (ou folder) onde o arquivo est localizado:
>>> f = open("/usr/share/dict/words", "r") >>> print f.readline() Aarhus

Este exemplo abre um arquivo chamado words que reside em um diretrio de nome dict, o qual reside em share, o qual reside em usr, o qual reside no diretrio de mais alto nvel do sistema, chamado /.

Voc no pode usar / como parte do nome de um arquivo; ela um caractere reservado como um delimitador entre nomes de diretrios e nomes de arquivos. O arquivo /usr/share/dict/words contm uma lista de palavras em ordem alfabtica, na qual a primeira palavra o nome de uma universidade Dinamarquesa.

11.4 Pickling

Para colocar valores em um arquivo, voc tem que convert-los para strings. Voc j viu como fazer isto com str:
>>> f.write (str(12.3)) >>> f.write (str([1,2,3]))

O problema que quando voc l de volta o valor, voc tem uma string. O Tipo original da informao foi perdido. De fato, voc no pode sequer dizer onde comea um valor e termina outro:
>>> f.readline() ?12.3[1, 2, 3]?

A soluo o pickling, assim chamado porque ?preserva? estruturas de dados. O mdulo pickel contm os comandos necessrios. Para us-lo, importe pickle e ento abra o arquivo da maneira usual:
>>> import pickle >>> f = open(?test.pck?, ?w?)

Para armazenar uma estrutura de dados, use o mtodo dump e ento feche o arquivo do modo usual:
>>> pickle.dump(12.3, f) >>> pickle.dump([1,2,3], f) >>> f.close()

Ento, podemos abrir o arquivo para leitura e carregar as estruturas de dados que foram descarregadas (dumped):
>>> f = open(?test.pck?, ?r?) >>> x = pickle.load(f)

>>> x 12,3 >>> type(x) <type ?float?> >>> y = pickle.load(f) >>> y [1, 2, 3] >>> type(y) <type ?list?>

Cada vez que invocamos load, obtemos um nico valor do arquivo, completo com seu tipo original.

11.5 Excees

Whenever que um erro em tempo de execuo acontece, ele gera uma exceo. Usualmente, o programa pra e Python exibe uma mensagem de erro. Por exemplo, dividir por zero gera uma exceo:
>>> print 55/0 ZeroDivisionError: integer division or modulo

Do mesmo modo, acessar um item de lista inexistente:


>>> a = [] >>> print a[5] IndexError: list index out of range

Ou acessar uma chave que no est em um dicionrio:


>>> b = {} >>> print b[?what?] KeyError: what

Em cada caso, a mensagem de erro tem duas partes: o tipo do erro antes dos dois pontos, e especificidades do erro depois dos dois pontos. Normalmente

Python tambm exibe um ?*traceback*? de onde estava a execuo do programa, mas ns temos omitido esta parte nos exemplos. s vezes queremos executar uma operao que pode causar uma exceo, mas no queremos que o programa pare. Ns podemos tratar a exceo usando as instrues try e except. Por exemplo, podemos pedir ao usurio um nome de arquivo e ento tentar abr-lo. Se o arquivo no existe, no queremos que o programa trave; queremos tratar a exceo:
nomedoarquivo = raw_input(?Entre com o nome do arquivo: ?) try: f = open (nomedoarquivo, ?r?) except: print ?No existe arquivo chamado?, nomedoarquivo

A instruo try executa os comandos do primeiro bloco. Se no ocorrerem excees, ele ignora a instruo except. Se qualquer exceo acontece, ele executa os comandos do ramo except e continua. Podemos encapsular esta habilidade numa funo: existe toma um nome de arquivo e retorna verdadeiro se o arquivo existe e falso se no existe:
def existe(nomedoarquivo) try: f = open(nomedoarquivo) f.close() return 1 except: return 0

Voc pode usar mltiplos blocos except para tratar diferentes tipos de excees. O Manual de Referncia de Python (Python Reference Manual) tem os detalhes. Se o seu programa detecta uma condio de erro, voc pode faz-lo lanar uma exceo. Aqui est um exemplo que toma uma entrada do usurio e testa se o valor 17. Supondo que 17 no seja uma entrada vlida por uma razo qualquer, ns lanamos uma exceo.
def entraNumero(): x = input (?Escolha um nmero: ?)

if x == 17: raise ?ErroNumeroRuim?, ?17 um nmero ruim? return x

O comando raise toma dois argumentos: o tipo da exceo e informaes especficas sobre o erro. ErroNumeroRuim um novo tipo de exceo que ns inventamos para esta aplicao. Se a funo que chamou entraNumero trata o erro, ento o programa pode continuar; de outro modo, Pyhton exibe uma mensagem de erro e sai:
>>> entraNumero() Escolha um nmero: 17 ErroNumeroRuim: 17 um nmero ruim

A mensagem de erro inclui o tipo da exceo e a informao adicional que voc forneceu. Como um exerccio, escreva uma funo que use entraNumero para pegar um nmero do teclado e que trate a exceo ErroNumeroRuim.

11.6 Glossrio

arquivo (file) Uma entidade nomeada, usualmente armazenada em um disco rgido (HD), disquete ou CD-ROM, que contm uma seqncia de caracteres. diretrio (directory) Uma coleo nomeada de arquivos, tambm chamado de pasta ou folder. caminho (path) Uma seqncia de nomes de diretrios que especifica a exata localizao de um arquivo. arquivo texto (text file) Um arquivo que contm caracteres organizados em linhas separadas por caracteres de nova linha. comando break (break statement)

Um comando que fora a atual iterao de um loop a terminar. O fluxo de execuo vai para o topo do loop, testa a condio e prossegue conforme o caso. System Message: WARNING/2 (<string>, line 14140) Block quote ends without a blank line; unexpected unindent.

Captulo 12: Classes e objetos


Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos o 3.4 Funes matemticas o 3.5 Composio o 3.6 Adicionando novas funes o 3.7 Definies e uso o 3.8 Fluxo de execuo o 3.9 Parmetros e argumentos o 3.10 Variveis e parmetros so locais o 3.11 Diagramas da pilha o 3.12 Funes com resultados o 3.13 Glossrio

Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao

Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores

12.1 Tipos compostos definidos pelo usurio

Depois de usarmos alguns tipos nativos do Python, estamos prontos para criar tipo de dados: O ponto. Considere o conceito de um ponto matemtico. Em duas dimenses, um ponto tem dois nmeros (coordenadas) que so tratadas coletivamente como um objeto simples. Na notao matemtica, pontos so freqentemente escritos entre parnteses com vrgula separando as coordenadas. Por exemplo, (0, 0) representam a origem, e (x, y) representam as unidades do ponto x a direita, e y representam as unidades do ponto x acima da origem. Uma maneira natural para representar um ponto em Python, com dois valores ponto flutuantes. A questo, ento, como agrupar estes dois valores em um objeto composto. A maneira rpida e 'suja' usar uma lista ou uma tupla, e para algumas aplicaes, isto pode ser a melhor escolha.

Uma alternativa definir um novo tipo composto, tambm chamado uma 'classe'. Esta abordagem envolve um pouco mais de esforo, mas ela tem vantagens que sero percebidas rapidamente. Uma definio de classe se parece como algo:
class Point: pass

Definies de Classe podem aparecer (ou figurar) em qualquer parte de um programa, mas elas esto usualmente prximas ao comeo do programa (aps os comandos de 'import'). As regras de sintaxe para a definio de Classes so as mesmas de outros comandos compostos (veja Seo 4.4). Esta definio cria uma nova classe chamada Point. O comando 'pass' no tem nenhum efeito aqui; ele somente necessrio porque um comando composto precisa ter algo no seu corpo. Quando criamos a classe Point, criamos um novo tipo tambm chamado Point. Os membros deste novo tipo so chamados 'instncias' deste tipo ou 'objetos'. Quando criamos uma nova instncia, estamos instanciando. Para instanciar o objeto Point, ns chamamos uma funo chamada (voc vai adivinhar) Point:
blank = Point()

A varivel 'blank' uma referncia a um novo objeto Point. A funo chamada Point (chamada no comando) que cria novos objetos Point, chamada 'construtor'. Clique aqui para feedback

12.2 Atributos

Ns podemos adicionar novos dados em uma instncia usando a notao 'ponto':


>>> blank.x = 3.0 >>> blank.y = 4.0

Esta sintaxe similar sintaxe de selecionar uma varivel de um mdulo, como math.pi ou string.uppercase. Neste caso, da mesma forma, ns estamos selecionando um item de dado de uma instncia. Estes itens so chamados atributos.

O seguinte diagrama de estado mostra o resultado destas atribuies: A varivel 'blank' refere a um objeto Point, que contm dois atributos. Cada atributo faz referncia a um nmero ponto-flutuante. Ns podemos ler o valor de um atributo usando a mesma sintaxe:
>>> print blank.y 4.0 >>> x = blank.x >>> print x 3.0

A expresso blank.x significa, "V ao objeto blank e pegue o valor de x". Neste caso, ns atribumos este valor a uma varivel cujo nome 'x'. No h conflito entre a varivel 'x' e o atributo 'x'. O propsito da notao '.' identificar a qual varivel voc est fazendo referncia de forma que no ambguo. distanceSquared = blank.x * blank.x + blank.y * blank.y Voc pode usar a notao '.' como parte de qualquer expresso; assim os seguintes comandos so corretos:
print '(' + str(blank.x) + ', ' + str(blank.y) + ')' distanceSquared = blank.x * blank.x + blank.y * blank.y

A primeira linha imprime (3.0, 4.0); a segunda linha calcula o valor 25.0. Voc pode ser tentado a imprimir o valor do objeto 'blank':
>>> print blank <__main__.Point instance at 80f8e70>

O resultado indica que 'blank' uma instncia da classe Point e foi definida na __main__. 80f8e70 o identificador nico deste objeto, escrito em hexadecimal (base 16). Est no provavelmente a forma mais 'informativa' para mostrar o objeto Point. Voc ir ver como mudar isto em breve. Como um exerccio, crie e imprima um objeto Point, e ento use id para imprimir o identificador nico do objeto. Traduza a forma hexadecimal para a forma decimal e confirme se so compatveis.

12.3 Instncias como parmetros

Voc pode passar uma instncia como um parmetro da forma usual. Por exemplo:
def printPoint(p): print '(' + str(p.x) + ', ' + str(p.y) + ')'

printPoint pega o ponto (p) como um argumento e mostra-o no formato padro. Se voc chamar printPoint(blank), a sada ser (3.0, 4.0). Como um exerccio, re-escreva a funo distancia da Seo 5.2 sendo que ela pega dois Points como parmetros, ao invs de quatro nmeros.

12.4 Semelhana

O significado da palavra 'mesmo' (ou semelhante) parece perfeitamente claro ate que voc lhe de algum sentido, e ento voc percebe que h mais nesta palavra do que voc esperava. Por exemplo, se voc diz "Chris e eu temos o mesmo carro", voc est dizendo que o carro de Chris e o seu so do mesmo fabricante e modelo, mas so dois carros diferentes. Se voc disser "Chris e eu temos a mesma me", voc est dizendo que a me de Chris e a sua, so a mesma pessoa. *Nota. Portanto a idia de 'semelhana' diferente dependendo do contexto. System Message: WARNING/2 (<string>, line 14324); backlink Inline emphasis start-string without end-string. Quando voc fala sobre objetos, h uma ambigidade similar. Por exemplo, se dois Pontos forem os mesmos, os dois contm os mesmos dados (coordenadas) ou so realmente o 'mesmo' objeto? Para verificar se duas referncias se referem ao 'mesmo' objeto, use o operador '=='. Por exemplo:
>>> p1 = Point() >>> p1.x = 3 >>> p1.y = 4 >>> p2 = Point() >>> p2.x = 3

>>> p2.y = 4 >>> p1 == p2 0

Mesmo que p1 e p2 contenham as mesmas coordenadas, os dois no representam o mesmo objeto. Se ns atribuirmos p1 a p2, ento as duas variveis so pseudnimos do mesmo objeto.
>>> p2 = p1 >>> p1 == p2 1

Este tipo de igualdade chamado de igualdade rasa porque ela compara somente as referncias e no o contedo dos objetos. Para comparar o contedo dos objetos - igualdade profunda - ns podemos escrever uma funo chamada samePoint:
def samePoint(p1, p2) : return (p1.x == p2.x) and (p1.y == p2.y)

Agora se ns criarmos dois diferentes objetos que contm os mesmos dados, ns podemos usar samePoint para verificar se eles representam o mesmo ponto.
>>> p1 = Point() >>> p1.x = 3 >>> p1.y = 4 >>> p2 = Point() >>> p2.x = 3 >>> p2.y = 4 >>> samePoint(p1, p2) 1

claro, se as duas variveis referirem ao mesmo objeto, elas tm igualdade rasa e igualdade profunda.

12.5 Retngulos

Digamos que desejemos uma classe para representar um retngulo. A questo , qual informao temos de prover para especificar um retngulo? Para manter as coisas simples, assuma que o retngulo orientado verticalmente ou horizontalmente, nunca em um ngulo. H algumas possibilidades: ns poderamos especificar o centro do retngulo (duas coordenadas) e seu tamanho (largura e altura); ou ns poderamos especificar um dos lados e o tamanho; ou ns poderamos especificar dois lados opostos. A escolha convencional especificar o canto superior esquerdo do retngulo e o tamanho. Novamente, ns vamos definir uma nova classe:
class Rectangle: pass

E instanci-la:
box = Rectangle() box.width = 100.0 box.height = 200.0

Este cdigo cria um novo objeto Retngulo com dois atributos ponto-flutuante. Para especificar o canto superior esquerdo, ns podemos embutir um objeto dentro de um objeto!
box.corner = Point() box.corner.x = 0.0; box.corner.y = 0.0;

A expresso box.corner.x significa, "v ao objeto referenciado por 'box' e selecione o atributo 'corner'; ento v ao objeto 'corner' e deste, selecione o atributo de nome 'x'". A figura mostra o estado deste objeto: Clique aqui para feedback

12.6 Instancias como valores retornados

Funes podem retornar instncias. Por exemplo, findCenter pega um Retngulo como um argumento e retorna um Ponto que contem as

coordenadas do centro do retngulo:


def findCenter(box): p = Point() p.x = box.corner.x + box.width/2.0 p.y = box.corner.y + box.height/2.0

Para chamar esta funo, passe 'box' como um argumento e coloque o resultado em uma varivel.
>>> center = findCenter(box) >>> print printPoint(center) (50.0, 100.0)

Clique aqui para feedback

12.7 Objetos so mutveis

Ns podemos mudar o estado de um objeto fazendo uma atribuio a um dos seus atributos. Por exemplo, para mudar o tamanho de um retngulo sem mudar sua posio, ns podemos modificar os valores de sua largura e altura. Veja:
box.width = box.width + 50 box.height = box.height + 100

Ns poderamos encapsular este cdigo em um mtodo e generaliza-lo para aumentar o tamanho deste retngulo em qualquer medida:
def growRect(box, dwidth, dheight) : box.width = box.width + dwidth box.height = box.height + dheight

As variveis dwidth e dheight indicam em quanto vamos aumentar o tamanho do retngulo em cada direo. Chamando este mtodo, teramos o mesmo efeito. Por exemplo, nspoderamos criar um novo Retngulo com o nome de 'bob' e passar este nome para o mtodo growRect:
>>> bob = Rectangle()

>>> bob.width = 100.00 >>> bob.height = 200.00 >>> bob.corner.x = 0.0; >>> bob.corner.y = 0.0; >>> growRect(bob, 50, 100)

Enquanto growRect est sendo executado, o parmetro 'box' um alias (apelido) para 'bob'. Qualquer mudana feita em 'box', tambm ir afetar 'bob'. Como exerccio, escreva uma function (mtodo) com o nome de moveRect que pega um Rectangle e dois parmetros com o nome de 'dx' e 'dy'. Esta funo dever mudar a localizao do retngulo atravs da adio de 'dx' coordenada 'x' e da adio de 'dy' coordenada 'y'. Clique aqui para feedback

12.8 Copiando

Ao usar 'alias' - como fizemos na seo anterior - ns podemos tornar o programa um pouco difcil de ler ou entender, pois as mudanas feitas em um local, podem afetar inesperadamente um outro objeto. E pode se tornar difcil de encontrar todas as variveis que podem afetar um dado objeto. Copiar um objeto freqentemente uma alternativa ao 'alias'. O modulo 'copy' contm uma funo chamada 'copy' que duplica um qualquer objeto. Veja:
>>> import copy >>> p1 = Point() >>> p1.x = 3 >>> p1.y = 4 >>> p2 = copy.copy(p1) >>> p1 == p2 0 >>> samePoint(p1, p2) 1

Uma vez que importamos o modulo 'copy', podemos usar o mtodo 'copy' para

criar um outro 'Point'. p1 e p2 no representam o mesmo ponto, mas eles contem os mesmo dados. Para copiar um simples objeto como um 'Point', que no contem nenhum objeto embutido, 'copy' suficiente. Isto eh chamado 'shallow' copia. Mas para um objeto como um 'Rectangle', que contem uma referencia para um 'Point', o mtodo 'copy' no ir executar corretamente a copia. Ele ir copiar a referencia para o objeto 'Point', portanto o que acontece aqui que os dois Rectangle (o novo e o antigo) iro fazer referencia a um simples 'Point'. Em outras palavras, se criarmos um 'box', b1, utilizando a forma usual, e depois fazer uma copia, b2, usando o mtodo 'copy', o resultado no ser o que esperamos. Neste caso, invocando 'growRect' em um dos retngulos (b1), isto no ir afetar o outro retngulo (b2, neste exemplo). Mas se usarmos o mtodo 'moveRect' em qualquer um deles, isto ir inevitavelmente afetar o outro. Este comportamento confuso e propenso a erros! Mas felizmente o modulo 'copy' contem um mtodo chamado 'deepcopy' que copia no somente o objeto, mas tambm copia todo e qualquer objeto 'embutido' neste objeto. Por isto, voc no ficar surpreso porque este mtodo chama-se 'deepcopy' (copia profunda) no ? Veja como funciona:
>>> b2 = copy.deepcopy(b1)

Agora, b1 e b2 so objetos completamente separados. Ns podemos usar 'deepcopy' para re-escrever 'growRect' sendo que ao invs de modificar um Rectangle existente, ele cria um novo que tem a mesma localizao do outro, mas com novas dimenses:
def growRect(box, dwidth, dheight): import copy newBox = copy.deepcopy(box) newBox.width = newBox.width + dwidth newBox.height = newBox.height + dheight return newBox

Como exerccio, re-escreva o mtodo 'moveRect' para ele criar e retornar um novo Rectangle ao invs de apenas modificar o antigo.

12.9 Glossrio

classe (class) Um tipo composto (XXX compound type) definido pelo usurio. Uma classe tambm pode ser visualizada como um molde que define a forma dos objetos que sero suas instncias. instanciar (instantiate) Criar uma instncia de uma classe. instncia (instance) Um objeto que pertence a uma classe. objeto (object) Um tipo de dado composto comumente utilizado para representar uma coisa ou um conceito do mundo real. construtor (constructor) Um mtodo utilizado para criar novos objetos. atributo (attribute) Um dos itens de dados nomeados que compem uma instncia. igualdade rasa (shallow equality) Igualdade de referncias; ocorre quando duas referncias apontam para o mesmo objeto. igualdade profunda (deep equality) Igualdade de valores; ocorre quando duas referncias apontam para objetos que tm o mesmo valor. cpia rasa (shallow copy) Ato de copiar o contedo de um objeto, incluindo as referncias a objetos embutidos (XXX embedded); implementada pela funo copy do mdulo copy. cpia profunda (deep copy) Ato de copiar o contedo de um objeto, bem como dos objetos embutidos (XXX embedded), e dos objetos embutidos nestes, e assim por diante; implementada pela funo deepcopy do mdulo copy.

Captulo 12: Classes e objetos


System Message: INFO/1 (<string>, line 14741); backlink Duplicate implicit target name: "captulo 12: classes e objetos". Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos o 3.4 Funes matemticas o 3.5 Composio o 3.6 Adicionando novas funes o 3.7 Definies e uso o 3.8 Fluxo de execuo o 3.9 Parmetros e argumentos o 3.10 Variveis e parmetros so locais o 3.11 Diagramas da pilha o 3.12 Funes com resultados o 3.13 Glossrio Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo

4.2 Expresses booleanas 4.3 Operadores lgicos 4.4 Execuo condicional 4.5 Execuo alternativa 4.6 Condicionais encadeados 4.7 Condicionais aninhados 4.8 A instruo return 4.9 Recursividade 4.10 Diagramas de pilha para funes recursivas 4.11 Recursividade infinita 4.12 Entrada pelo teclado 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings
o o o o o o o o o o o o

Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores

12.1 Tipos compostos definidos pelo usurio

Depois de usarmos alguns tipos nativos do Python, estamos prontos para criar tipo de dados: O ponto. Considere o conceito de um ponto matemtico. Em duas dimenses, um ponto tem dois nmeros (coordenadas) que so tratadas coletivamente como um objeto simples. Na notao matemtica, pontos so freqentemente escritos entre parnteses com vrgula separando as coordenadas. Por exemplo, (0, 0) representam a origem, e (x, y) representam as unidades do ponto x a direita, e y representam as unidades do ponto x acima da origem. Uma maneira natural para representar um ponto em Python, com dois valores ponto flutuantes. A questo, ento, como agrupar estes dois valores em um objeto composto. A maneira rpida e 'suja' usar uma lista ou uma tupla, e para algumas aplicaes, isto pode ser a melhor escolha. Uma alternativa definir um novo tipo composto, tambm chamado uma 'classe'. Esta abordagem envolve um pouco mais de esforo, mas ela tem

vantagens que sero percebidas rapidamente. Uma definio de classe se parece como algo:
class Point: pass

Definies de Classe podem aparecer (ou figurar) em qualquer parte de um programa, mas elas esto usualmente prximas ao comeo do programa (aps os comandos de 'import'). As regras de sintaxe para a definio de Classes so as mesmas de outros comandos compostos (veja Seo 4.4). Esta definio cria uma nova classe chamada Point. O comando 'pass' no tem nenhum efeito aqui; ele somente necessrio porque um comando composto precisa ter algo no seu corpo. Quando criamos a classe Point, criamos um novo tipo tambm chamado Point. Os membros deste novo tipo so chamados 'instncias' deste tipo ou 'objetos'. Quando criamos uma nova instncia, estamos instanciando. Para instanciar o objeto Point, ns chamamos uma funo chamada (voc vai adivinhar) Point:
blank = Point()

A varivel 'blank' uma referncia a um novo objeto Point. A funo chamada Point (chamada no comando) que cria novos objetos Point, chamada 'construtor'. Clique aqui para feedback

12.2 Atributos

Ns podemos adicionar novos dados em uma instncia usando a notao 'ponto':


>>> blank.x = 3.0 >>> blank.y = 4.0

Esta sintaxe similar sintaxe de selecionar uma varivel de um mdulo, como math.pi ou string.uppercase. Neste caso, da mesma forma, ns estamos selecionando um item de dado de uma instncia. Estes itens so chamados atributos. O seguinte diagrama de estado mostra o resultado destas atribuies: A varivel 'blank' refere a um objeto Point, que contm dois atributos. Cada

atributo faz referncia a um nmero ponto-flutuante. Ns podemos ler o valor de um atributo usando a mesma sintaxe:
>>> print blank.y 4.0 >>> x = blank.x >>> print x 3.0

A expresso blank.x significa, "V ao objeto blank e pegue o valor de x". Neste caso, ns atribumos este valor a uma varivel cujo nome 'x'. No h conflito entre a varivel 'x' e o atributo 'x'. O propsito da notao '.' identificar a qual varivel voc est fazendo referncia de forma que no ambguo. distanceSquared = blank.x * blank.x + blank.y * blank.y Voc pode usar a notao '.' como parte de qualquer expresso; assim os seguintes comandos so corretos:
print '(' + str(blank.x) + ', ' + str(blank.y) + ')' distanceSquared = blank.x * blank.x + blank.y * blank.y

A primeira linha imprime (3.0, 4.0); a segunda linha calcula o valor 25.0. Voc pode ser tentado a imprimir o valor do objeto 'blank':
>>> print blank <__main__.Point instance at 80f8e70>

O resultado indica que 'blank' uma instncia da classe Point e foi definida na __main__. 80f8e70 o identificador nico deste objeto, escrito em hexadecimal (base 16). Est no provavelmente a forma mais 'informativa' para mostrar o objeto Point. Voc ir ver como mudar isto em breve. Como um exerccio, crie e imprima um objeto Point, e ento use id para imprimir o identificador nico do objeto. Traduza a forma hexadecimal para a forma decimal e confirme se so compatveis.

12.3 Instncias como parmetros

Voc pode passar uma instncia como um parmetro da forma usual. Por

exemplo:
def printPoint(p): print '(' + str(p.x) + ', ' + str(p.y) + ')'

printPoint pega o ponto (p) como um argumento e mostra-o no formato padro. Se voc chamar printPoint(blank), a sada ser (3.0, 4.0). Como um exerccio, re-escreva a funo distancia da Seo 5.2 sendo que ela pega dois Points como parmetros, ao invs de quatro nmeros.

12.4 Semelhana

O significado da palavra 'mesmo' (ou semelhante) parece perfeitamente claro ate que voc lhe de algum sentido, e ento voc percebe que h mais nesta palavra do que voc esperava. Por exemplo, se voc diz "Chris e eu temos o mesmo carro", voc est dizendo que o carro de Chris e o seu so do mesmo fabricante e modelo, mas so dois carros diferentes. Se voc disser "Chris e eu temos a mesma me", voc est dizendo que a me de Chris e a sua, so a mesma pessoa. *Nota. Portanto a idia de 'semelhana' diferente dependendo do contexto. System Message: WARNING/2 (<string>, line 14923); backlink Inline emphasis start-string without end-string. Quando voc fala sobre objetos, h uma ambigidade similar. Por exemplo, se dois Pontos forem os mesmos, os dois contm os mesmos dados (coordenadas) ou so realmente o 'mesmo' objeto? Para verificar se duas referncias se referem ao 'mesmo' objeto, use o operador '=='. Por exemplo:
>>> p1 = Point() >>> p1.x = 3 >>> p1.y = 4 >>> p2 = Point() >>> p2.x = 3 >>> p2.y = 4 >>> p1 == p2

Mesmo que p1 e p2 contenham as mesmas coordenadas, os dois no representam o mesmo objeto. Se ns atribuirmos p1 a p2, ento as duas variveis so pseudnimos do mesmo objeto.
>>> p2 = p1 >>> p1 == p2 1

Este tipo de igualdade chamado de igualdade rasa porque ela compara somente as referncias e no o contedo dos objetos. Para comparar o contedo dos objetos - igualdade profunda - ns podemos escrever uma funo chamada samePoint:
def samePoint(p1, p2) : return (p1.x == p2.x) and (p1.y == p2.y)

Agora se ns criarmos dois diferentes objetos que contm os mesmos dados, ns podemos usar samePoint para verificar se eles representam o mesmo ponto.
>>> p1 = Point() >>> p1.x = 3 >>> p1.y = 4 >>> p2 = Point() >>> p2.x = 3 >>> p2.y = 4 >>> samePoint(p1, p2) 1

claro, se as duas variveis referirem ao mesmo objeto, elas tm igualdade rasa e igualdade profunda.

12.5 Retngulos

Digamos que desejemos uma classe para representar um retngulo. A questo , qual informao temos de prover para especificar um retngulo? Para manter as coisas simples, assuma que o retngulo orientado

verticalmente ou horizontalmente, nunca em um ngulo. H algumas possibilidades: ns poderamos especificar o centro do retngulo (duas coordenadas) e seu tamanho (largura e altura); ou ns poderamos especificar um dos lados e o tamanho; ou ns poderamos especificar dois lados opostos. A escolha convencional especificar o canto superior esquerdo do retngulo e o tamanho. Novamente, ns vamos definir uma nova classe:
class Rectangle: pass

E instanci-la:
box = Rectangle() box.width = 100.0 box.height = 200.0

Este cdigo cria um novo objeto Retngulo com dois atributos ponto-flutuante. Para especificar o canto superior esquerdo, ns podemos embutir um objeto dentro de um objeto!
box.corner = Point() box.corner.x = 0.0; box.corner.y = 0.0;

A expresso box.corner.x significa, "v ao objeto referenciado por 'box' e selecione o atributo 'corner'; ento v ao objeto 'corner' e deste, selecione o atributo de nome 'x'". A figura mostra o estado deste objeto: Clique aqui para feedback

12.6 Instancias como valores retornados

Funes podem retornar instncias. Por exemplo, findCenter pega um Retngulo como um argumento e retorna um Ponto que contem as coordenadas do centro do retngulo:
def findCenter(box):

p = Point() p.x = box.corner.x + box.width/2.0 p.y = box.corner.y + box.height/2.0

Para chamar esta funo, passe 'box' como um argumento e coloque o resultado em uma varivel.
>>> center = findCenter(box) >>> print printPoint(center) (50.0, 100.0)

Clique aqui para feedback

12.7 Objetos so mutveis

Ns podemos mudar o estado de um objeto fazendo uma atribuio a um dos seus atributos. Por exemplo, para mudar o tamanho de um retngulo sem mudar sua posio, ns podemos modificar os valores de sua largura e altura. Veja:
box.width = box.width + 50 box.height = box.height + 100

Ns poderamos encapsular este cdigo em um mtodo e generaliza-lo para aumentar o tamanho deste retngulo em qualquer medida:
def growRect(box, dwidth, dheight) : box.width = box.width + dwidth box.height = box.height + dheight

As variveis dwidth e dheight indicam em quanto vamos aumentar o tamanho do retngulo em cada direo. Chamando este mtodo, teramos o mesmo efeito. Por exemplo, nspoderamos criar um novo Retngulo com o nome de 'bob' e passar este nome para o mtodo growRect:
>>> bob = Rectangle() >>> bob.width = 100.00 >>> bob.height = 200.00

>>> bob.corner.x = 0.0; >>> bob.corner.y = 0.0; >>> growRect(bob, 50, 100)

Enquanto growRect est sendo executado, o parmetro 'box' um alias (apelido) para 'bob'. Qualquer mudana feita em 'box', tambm ir afetar 'bob'. Como exerccio, escreva uma function (mtodo) com o nome de moveRect que pega um Rectangle e dois parmetros com o nome de 'dx' e 'dy'. Esta funo dever mudar a localizao do retngulo atravs da adio de 'dx' coordenada 'x' e da adio de 'dy' coordenada 'y'. Clique aqui para feedback

12.8 Copiando

Ao usar 'alias' - como fizemos na seo anterior - ns podemos tornar o programa um pouco difcil de ler ou entender, pois as mudanas feitas em um local, podem afetar inesperadamente um outro objeto. E pode se tornar difcil de encontrar todas as variveis que podem afetar um dado objeto. Copiar um objeto freqentemente uma alternativa ao 'alias'. O modulo 'copy' contm uma funo chamada 'copy' que duplica um qualquer objeto. Veja:
>>> import copy >>> p1 = Point() >>> p1.x = 3 >>> p1.y = 4 >>> p2 = copy.copy(p1) >>> p1 == p2 0 >>> samePoint(p1, p2) 1

Uma vez que importamos o modulo 'copy', podemos usar o mtodo 'copy' para criar um outro 'Point'. p1 e p2 no representam o mesmo ponto, mas eles contem os mesmo dados. Para copiar um simples objeto como um 'Point', que no contem nenhum

objeto embutido, 'copy' suficiente. Isto eh chamado 'shallow' copia. Mas para um objeto como um 'Rectangle', que contem uma referencia para um 'Point', o mtodo 'copy' no ir executar corretamente a copia. Ele ir copiar a referencia para o objeto 'Point', portanto o que acontece aqui que os dois Rectangle (o novo e o antigo) iro fazer referencia a um simples 'Point'. Em outras palavras, se criarmos um 'box', b1, utilizando a forma usual, e depois fazer uma copia, b2, usando o mtodo 'copy', o resultado no ser o que esperamos. Neste caso, invocando 'growRect' em um dos retngulos (b1), isto no ir afetar o outro retngulo (b2, neste exemplo). Mas se usarmos o mtodo 'moveRect' em qualquer um deles, isto ir inevitavelmente afetar o outro. Este comportamento confuso e propenso a erros! Mas felizmente o modulo 'copy' contem um mtodo chamado 'deepcopy' que copia no somente o objeto, mas tambm copia todo e qualquer objeto 'embutido' neste objeto. Por isto, voc no ficar surpreso porque este mtodo chama-se 'deepcopy' (copia profunda) no ? Veja como funciona:
>>> b2 = copy.deepcopy(b1)

Agora, b1 e b2 so objetos completamente separados. Ns podemos usar 'deepcopy' para re-escrever 'growRect' sendo que ao invs de modificar um Rectangle existente, ele cria um novo que tem a mesma localizao do outro, mas com novas dimenses:
def growRect(box, dwidth, dheight): import copy newBox = copy.deepcopy(box) newBox.width = newBox.width + dwidth newBox.height = newBox.height + dheight return newBox

Como exerccio, re-escreva o mtodo 'moveRect' para ele criar e retornar um novo Rectangle ao invs de apenas modificar o antigo.

12.9 Glossrio

classe (class) Um tipo composto (XXX compound type) definido pelo usurio. Uma classe tambm pode ser visualizada como um molde que define a forma dos objetos

que sero suas instncias. instanciar (instantiate) Criar uma instncia de uma classe. instncia (instance) Um objeto que pertence a uma classe. objeto (object) Um tipo de dado composto comumente utilizado para representar uma coisa ou um conceito do mundo real. construtor (constructor) Um mtodo utilizado para criar novos objetos. atributo (attribute) Um dos itens de dados nomeados que compem uma instncia. igualdade rasa (shallow equality) Igualdade de referncias; ocorre quando duas referncias apontam para o mesmo objeto. igualdade profunda (deep equality) Igualdade de valores; ocorre quando duas referncias apontam para objetos que tm o mesmo valor. cpia rasa (shallow copy) Ato de copiar o contedo de um objeto, incluindo as referncias a objetos embutidos (XXX embedded); implementada pela funo copy do mdulo copy. cpia profunda (deep copy) Ato de copiar o contedo de um objeto, bem como dos objetos embutidos (XXX embedded), e dos objetos embutidos nestes, e assim por diante; implementada pela funo deepcopy do mdulo copy. System Message: WARNING/2 (<string>, line 15336) Block quote ends without a blank line; unexpected unindent.

Captulo 13: Classes e funes


Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos o 3.4 Funes matemticas o 3.5 Composio o 3.6 Adicionando novas funes o 3.7 Definies e uso o 3.8 Fluxo de execuo o 3.9 Parmetros e argumentos o 3.10 Variveis e parmetros so locais o 3.11 Diagramas da pilha o 3.12 Funes com resultados o 3.13 Glossrio Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa

4.6 Condicionais encadeados 4.7 Condicionais aninhados 4.8 A instruo return 4.9 Recursividade 4.10 Diagramas de pilha para funes recursivas 4.11 Recursividade infinita 4.12 Entrada pelo teclado 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas
o o o o o o o o

Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores

13.1 Horario

Como exemplo de outro tipo definido pelo usurio, ns vamos definir uma classe chamada Horario que grava os registros de horrio do dia. A definio da classe se parece com isso:
class Horario: pass

Ns podemos criar um novo objeto Horario e determinar atributos para horas, minutos e segundos:
horario = Horario() horario.horas = 11 horario.minutos = 59 horario.segundos = 30

O diagrama de estado para o objeto Horario parece com isso: ** TEM UMA FIGURA AQUI **

Como exerccio, escreva uma funo 'imprimirHorario' que tenha como argumento um objeto Horario e imprima-o na forma horas:minutos:segundos. Como um segundo exerccio, escreva uma funo booleana que tenha como argumento dois objetos Horario, h1 e h2, e retorne verdadeiro (1) se h1 vem depois de h2 cronologicamente, do contrrio, retorne falso (0).

13.2 Funes Puras

Nas prximas sesses, ns vamos escrever duas verses de uma funo chamada adicionaHorario, que calcula a soma de dois horrios. Elas vo demonstrar 2 tipos de funes: funes puras e funes modificadoras. Segue uma verso tosca de somaHorario:
def somaHorario(h1, h2): soma = Horario() soma.horas = h1.horas + h2.horas soma.minutos = h1.minutos + h2.minutos soma.segundos = h1.segundos + h2.segundos return soma

A funo cria um novo objeto Horario, inicializa os seus atributos, e retorna uma referncia para o novo objeto. Isso chamado de funo pura pois ela no modifica nenhum dos objetos que so passados como parmetros e no tem nenhum efeito colateral, como imprimir um valor ou pegar entrada do usurio. Aqui est um exemplo de como usar esta funo. Ns vamos criar dois objetos Horario: horarioAtual, que contm o horrio atual; e horarioDoPao, que contm a quantidade de tempo que a mquina de fazer po gasta para fazer po. Ento ns vamos usar somaHorario para tentar saber quando o po estar pronto. Se voc no tiver terminado de escrever imprimirHorario ainda, de uma olhada na seo 14.2 antes de voc continuar isso:
>>> horarioAtual = Horario() >>> horarioAtual.horas = 9 >>> horarioAtual.minutos = 14 >>> horarioAtual.segundos = 30 >>> horarioDoPao = Horario() >>> horarioDoPao.horas = 3 >>> horarioDoPao.minutos = 35 >>> horarioDoPao.segundos = 0 >>> horarioTermino = somaHorario(horarioAtual, horarioDoPao)

>>> imprimirHorario(horarioTermino)

A sada deste programa 12:49:30, o que correto. Por outro lado, existem casos onde o resultado no correto. Voc pode pensar em algum ? O problema que esta funo no lida com casos onde o nmero de segundos ou minutos acrescentado em mais de sessenta. Quando isso acontece, ns temos de "transportar" os segundos extras para a coluna dos minutos ou os minutos extras na coluna das horas. Aqui est a segunda verso corrigida da funo:
def somaHorario(t1, t2): soma = Horario() soma.horas = t1.horas + t2.horas soma.minutos = t1.minutos + t2.minutos soma.segundos = t1.segundos + t2.segundos

if soma.segundos >= 60: soma.segundos = soma.segundos - 60 soma.minutos = soma.minutos + 1

if soma.minutos >= 60: soma.minutos = soma.minutos - 60 soma.horas = soma.horas + 1

return soma

Apesar desta funo estar correta, ela est comeando a ficar grande. Depois ns vamos sugerir uma aproximao alternativa que rende um cdigo menor. Clique aqui para feedback

13.3 Modificadores

Existem momentos quando til para uma funo modificar um ou mais dos objetos que ela recebe como parmetro. Usualmente, quem est chamando a funo mantm uma referncia para os objetos que ele passa, de forma que

quaisquer mudanas que a funo faz so visveis para quem est chamando. Funes que trabalham desta forma so chamadas modificadores. incrementar, que adiciona um nmero dado de segundos para um objeto Horario, que poderia ser escrito quase naturalmente como um modificador. Um rascunho tosco da funo seria algo parecido com isso:
def incrementar(horario, segundos): horario.segundos = horario.segundos + segundos

if horario.segundos >= 60: horario.segundos = horario.segundos - 60 horario.minutos = horario.minutos + 1

if horario.minutos >= 60: horario.minutos = horario.minutos - 60 horario.horas = horario.horas + 1

A primeira linha executa a operao bsica; o resto lida com os caso especiais que vimos antes. Esta funo esta correta ? O que aconteceria se o parametro segundos for muito maior que sessenta ? Nesse caso, no suficiente transportar apenas uma vez; ns teramos de continuar fazendo isso at que segundos seja menor que sessenta. Uma soluo seria substituir os comando if por comandos while:
def incrementar(horario, segundos): horario.segundos = horario.segundos + segundos

while horario.segundos >= 60: horario.segundos = horario.segundos - 60 horario.minutos = horario.minutos + 1

while horario.minutos >= 60: horario.minutos = horario.minutos - 60 horario.horas = horario.horas + 1

Esta funo agora esta correta, mas no a soluo mais eficiente. Como um exerccio, reescreva esta funo de maneira que ela no contenha nenhum loop. Como um segundo exerccio, reescreva incrementar como uma funo pura, e escreva chamadas de funes para as duas funes. Clique aqui para feedback

13.4 O que melhor ?

Qualquer coisa que pode ser feita com modificadores tambm podem ser feitas com funes puras. De fato, algumas linguagens de programao permitem apenas funes puras. Existe alguma evidncia que programas que usam funes puras so desenvolvidos mais rapidamente e so menos propensos a erros que programas que usam modificadores. No entanto, modificadores as vezes so convenientes, e em alguns casos, programao funcional menos eficiente. Em geral, ns recomendamos que voc escreva funes puras sempre que for necessrio e recorrer para modificadores somente se existir uma grande vantagem. Esta aproximao poderia ser chamada de um estilo de programao funcional. Clique aqui para feedback

13.5 Desenvolvimento Prototipado versus Desenvolvimento Planejamento

Neste captulo, ns demonstramos uma aproximao para o desenvolvimento de programas que ns chamamos de desenvolvimento prototipado. Em cada caso, ns escrevemos um rascunho tosco (ou prototipo) que executou os clculos bsicos e ento, o testamos em uns poucos casos, corrigindo ento, as falhas que fomos encontrando. Embora esta aproximao possa ser eficaz, ela pode conduzir para cdigo que desnecessariamente complicado desde que trata de muitos casos especiais e unreliable desde que difcil saber se voc encontrou todos os erros. An alternative is planned development, in which high-level insight into the problem can make the programming much easier. In this case, the insight is that a Time object is really a three-digit number in base 60! The second component is the "ones column," the minute component is the "sixties column," and the hourcomponent is the "thirty-six hundreds column." When we wrote addTime and increment, we were effectively doing addition in

base 60, which is why we had to carry from one column to the next. This observation suggests another approach to the whole problem we can convert a Time object into a single number and take advantage of the fact that the computer knows how to do arithmetic with numbers. The following function converts a Timeobject into an integer:
def converterParaSegundos(t): minutos = t.horas * 60 + t.minutos segundos = minutos * 60 + t.segundos return segundos

Agora, tudo que ns precisamos uma maneira de converter de um inteiro para um objeto Horario:
def criarHorario(segundos): horario = Time() horario.horas = segundos/3600 segundos = segundos - horario.horas * 3600 horario.minutos = segundos/60 segundos = segundos - horario.minutos * 60 horario.segundos = segundos return horario

Voc deve ter que pensar um pouco para se convencer que esta tcnica de converter de uma base para outra correta. Assumindo que voc est convencido, voc pode usar essas funes para reescrever somaHorario:
def somaHorario(t1, t2): segundos = converterParaSegundos(t1) + converterParaSegundos(t2) return criarHorario(segundos)

Esta verso muito mais curta que a original, e muito mais fcil para demonstrar que est correta (assumindo, como sempre, que as funes que so chamadas esto corretas). Como um exerccio, reescreva incrementar da mesma forma. Clique aqui para feedback 13.6 Generalizao

Algumas vezes, converter de base 60 para base 10 e voltar mais difcil do que simplesmente lidar com horrios. Converso de base mais abstrata; nossa intuio para lidar com horrios melhor. Mas se ns But if we have the insight to treat times as base 60 numbers and make the investment of writing the conversion functions (converterParaSeguntos e criarHorario), ns conseguimos um programa que menor, fcil de ler e depurar, e mais confivel. tambm fcil para adicionar funcionalidades depois. Por exemplo, imagine subtrair dois Horarios para encontrar a durao entre eles. Uma aproximao ingnua seria implementar subtrao com emprstimo (?? borrowing - Isso mesmo ??). Usando as funes de converso ser mais fcil e provavelmente estar correto. Ironicamente, algumas vezes fazer um problema mais difcil (ou mais genrico) o torna mais simples (porque existem alguns poucos casos especiais e poucas oportunidades para errar). Clique aqui para feedback 13.7 Algoritmos Quando voc escreve uma soluo genrica para uma classe de problemas, ao contrrio de uma soluo especfica para um nico problema, voc escreveu um algortmo. Ns mencionamos isso antes mas no definimos cuidadosamente. Isso no fcil para definir, ento ns vamos tentar //a couple of approaches//. Primeiramente, considere alguma coisa que no seja um algortmo. Quando voc aprendeu a multiplicar nmeros de um dgito, voc provavelmente memorizou a tabela de multiplicao. Como resultado, voc memorizou 100 solues especficas. Esse tipo de conhecimento no algortmo. Mas se voc "preguioso", voc provavelmente trapaceou por ter aprendido alguns truques. Por exemplo, para encontrar o produto de n e 9, voc pode escrever n-1 como o primeiro dgito e 10-n como o segundo dgito. Este truque um soluo genrica para multiplicar qualquer nmero de um dgito por 9. Isso um algoritmo! De modo parecido, as tcnicas que voc aprendeu para adicionar //com transporte//, //subtraction with borrowing//, e diviso longa so todas algortmos. Uma das caractersticas dos algortmos que eles no requerem nenhuma inteligncia para serem executados ( carry out ). Eles so processos mecnicos no qual cada passo segue o ltimo de acordo com um conjunto simples de regras. Na nossa opinio, preocupante que humanos gastem tanto tempo na escola aprendendo a executar algoritmos que, literalmente, no requerem inteligncia. Por outro lado, o processo de projetar algoritmos interessante,

intelectualmente desafiante, e uma parte central daquilo que chamamos programao. Algumas das coisas que as pessoas fazem naturalmente, sem dificuldade ou conscincia, so as mais difceis de se expressar atravs de algoritmos. Entender a linguagem natural um bom exemplo. Todos ns fazemos isso, mas at hoje ningum conseguiu explicar como fazemos isso, pelo menos no na forma de algoritmo. Clique aqui para feedback.

13.8 Glossrio

funo pura (pure function) Uma funo que no modifica nenhum dos objetos que ela recebe como parmetro. A maioria das funes puras frutfera. modificador (modifier) Uma funo que muda um ou mais dos objetos que ela recebe como parmetros. A maioria dos modificadores nula. estilo de programao funcional (functional programming style) Um estilo de programao onde a maioria das funes so puras. desenvolvimento prototipado (prototype development) Uma maneira de desenvolver programas comeando com um prottipo e gradualmente melhorando-o. desenvolvimento planejado (planned development) Uma maneira de desenvolver programas que envolvem uma percepo de alto nvel do problema e mais planejamento do que desenvolvimento incremental ou desenvolvimento prototipado. algoritmo (algorithm) Um conjunto de instrues para resolver uma classe de problemas usando um processo mecnico, no inteligente.

Captulo 13: Classes e funes

System Message: INFO/1 (<string>, line 15805); backlink Duplicate implicit target name: "captulo 13: classes e funes". Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos o 3.4 Funes matemticas o 3.5 Composio o 3.6 Adicionando novas funes o 3.7 Definies e uso o 3.8 Fluxo de execuo o 3.9 Parmetros e argumentos o 3.10 Variveis e parmetros so locais o 3.11 Diagramas da pilha o 3.12 Funes com resultados o 3.13 Glossrio Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional

4.5 Execuo alternativa 4.6 Condicionais encadeados 4.7 Condicionais aninhados 4.8 A instruo return 4.9 Recursividade 4.10 Diagramas de pilha para funes recursivas 4.11 Recursividade infinita 4.12 Entrada pelo teclado 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas
o o o o o o o o o

Captulo 9: Tuplas Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores

13.1 Horario

Como exemplo de outro tipo definido pelo usurio, ns vamos definir uma classe chamada Horario que grava os registros de horrio do dia. A definio da classe se parece com isso:
class Horario: pass

Ns podemos criar um novo objeto Horario e determinar atributos para horas, minutos e segundos:
horario = Horario() horario.horas = 11 horario.minutos = 59 horario.segundos = 30

O diagrama de estado para o objeto Horario parece com isso:

** TEM UMA FIGURA AQUI ** Como exerccio, escreva uma funo 'imprimirHorario' que tenha como argumento um objeto Horario e imprima-o na forma horas:minutos:segundos. Como um segundo exerccio, escreva uma funo booleana que tenha como argumento dois objetos Horario, h1 e h2, e retorne verdadeiro (1) se h1 vem depois de h2 cronologicamente, do contrrio, retorne falso (0).

13.2 Funes Puras

Nas prximas sesses, ns vamos escrever duas verses de uma funo chamada adicionaHorario, que calcula a soma de dois horrios. Elas vo demonstrar 2 tipos de funes: funes puras e funes modificadoras. Segue uma verso tosca de somaHorario:
def somaHorario(h1, h2): soma = Horario() soma.horas = h1.horas + h2.horas soma.minutos = h1.minutos + h2.minutos soma.segundos = h1.segundos + h2.segundos return soma

A funo cria um novo objeto Horario, inicializa os seus atributos, e retorna uma referncia para o novo objeto. Isso chamado de funo pura pois ela no modifica nenhum dos objetos que so passados como parmetros e no tem nenhum efeito colateral, como imprimir um valor ou pegar entrada do usurio. Aqui est um exemplo de como usar esta funo. Ns vamos criar dois objetos Horario: horarioAtual, que contm o horrio atual; e horarioDoPao, que contm a quantidade de tempo que a mquina de fazer po gasta para fazer po. Ento ns vamos usar somaHorario para tentar saber quando o po estar pronto. Se voc no tiver terminado de escrever imprimirHorario ainda, de uma olhada na seo 14.2 antes de voc continuar isso:
>>> horarioAtual = Horario() >>> horarioAtual.horas = 9 >>> horarioAtual.minutos = 14 >>> horarioAtual.segundos = 30 >>> horarioDoPao = Horario() >>> horarioDoPao.horas = 3 >>> horarioDoPao.minutos = 35

>>> horarioDoPao.segundos = 0 >>> horarioTermino = somaHorario(horarioAtual, horarioDoPao) >>> imprimirHorario(horarioTermino)

A sada deste programa 12:49:30, o que correto. Por outro lado, existem casos onde o resultado no correto. Voc pode pensar em algum ? O problema que esta funo no lida com casos onde o nmero de segundos ou minutos acrescentado em mais de sessenta. Quando isso acontece, ns temos de "transportar" os segundos extras para a coluna dos minutos ou os minutos extras na coluna das horas. Aqui est a segunda verso corrigida da funo:
def somaHorario(t1, t2): soma = Horario() soma.horas = t1.horas + t2.horas soma.minutos = t1.minutos + t2.minutos soma.segundos = t1.segundos + t2.segundos

if soma.segundos >= 60: soma.segundos = soma.segundos - 60 soma.minutos = soma.minutos + 1

if soma.minutos >= 60: soma.minutos = soma.minutos - 60 soma.horas = soma.horas + 1

return soma

Apesar desta funo estar correta, ela est comeando a ficar grande. Depois ns vamos sugerir uma aproximao alternativa que rende um cdigo menor. Clique aqui para feedback

13.3 Modificadores

Existem momentos quando til para uma funo modificar um ou mais dos

objetos que ela recebe como parmetro. Usualmente, quem est chamando a funo mantm uma referncia para os objetos que ele passa, de forma que quaisquer mudanas que a funo faz so visveis para quem est chamando. Funes que trabalham desta forma so chamadas modificadores. incrementar, que adiciona um nmero dado de segundos para um objeto Horario, que poderia ser escrito quase naturalmente como um modificador. Um rascunho tosco da funo seria algo parecido com isso:
def incrementar(horario, segundos): horario.segundos = horario.segundos + segundos

if horario.segundos >= 60: horario.segundos = horario.segundos - 60 horario.minutos = horario.minutos + 1

if horario.minutos >= 60: horario.minutos = horario.minutos - 60 horario.horas = horario.horas + 1

A primeira linha executa a operao bsica; o resto lida com os caso especiais que vimos antes. Esta funo esta correta ? O que aconteceria se o parametro segundos for muito maior que sessenta ? Nesse caso, no suficiente transportar apenas uma vez; ns teramos de continuar fazendo isso at que segundos seja menor que sessenta. Uma soluo seria substituir os comando if por comandos while:
def incrementar(horario, segundos): horario.segundos = horario.segundos + segundos

while horario.segundos >= 60: horario.segundos = horario.segundos - 60 horario.minutos = horario.minutos + 1

while horario.minutos >= 60: horario.minutos = horario.minutos - 60

horario.horas = horario.horas + 1

Esta funo agora esta correta, mas no a soluo mais eficiente. Como um exerccio, reescreva esta funo de maneira que ela no contenha nenhum loop. Como um segundo exerccio, reescreva incrementar como uma funo pura, e escreva chamadas de funes para as duas funes. Clique aqui para feedback

13.4 O que melhor ?

Qualquer coisa que pode ser feita com modificadores tambm podem ser feitas com funes puras. De fato, algumas linguagens de programao permitem apenas funes puras. Existe alguma evidncia que programas que usam funes puras so desenvolvidos mais rapidamente e so menos propensos a erros que programas que usam modificadores. No entanto, modificadores as vezes so convenientes, e em alguns casos, programao funcional menos eficiente. Em geral, ns recomendamos que voc escreva funes puras sempre que for necessrio e recorrer para modificadores somente se existir uma grande vantagem. Esta aproximao poderia ser chamada de um estilo de programao funcional. Clique aqui para feedback

13.5 Desenvolvimento Prototipado versus Desenvolvimento Planejamento

Neste captulo, ns demonstramos uma aproximao para o desenvolvimento de programas que ns chamamos de desenvolvimento prototipado. Em cada caso, ns escrevemos um rascunho tosco (ou prototipo) que executou os clculos bsicos e ento, o testamos em uns poucos casos, corrigindo ento, as falhas que fomos encontrando. Embora esta aproximao possa ser eficaz, ela pode conduzir para cdigo que desnecessariamente complicado desde que trata de muitos casos especiais e unreliable desde que difcil saber se voc encontrou todos os erros. An alternative is planned development, in which high-level insight into the problem can make the programming much easier. In this case, the insight is that a Time object is really a three-digit number in base 60! The second component is the "ones column," the minute component is the "sixties column," and the hourcomponent is the "thirty-six hundreds column."

When we wrote addTime and increment, we were effectively doing addition in base 60, which is why we had to carry from one column to the next. This observation suggests another approach to the whole problem we can convert a Time object into a single number and take advantage of the fact that the computer knows how to do arithmetic with numbers. The following function converts a Timeobject into an integer:
def converterParaSegundos(t): minutos = t.horas * 60 + t.minutos segundos = minutos * 60 + t.segundos return segundos

Agora, tudo que ns precisamos uma maneira de converter de um inteiro para um objeto Horario:
def criarHorario(segundos): horario = Time() horario.horas = segundos/3600 segundos = segundos - horario.horas * 3600 horario.minutos = segundos/60 segundos = segundos - horario.minutos * 60 horario.segundos = segundos return horario

Voc deve ter que pensar um pouco para se convencer que esta tcnica de converter de uma base para outra correta. Assumindo que voc est convencido, voc pode usar essas funes para reescrever somaHorario:
def somaHorario(t1, t2): segundos = converterParaSegundos(t1) + converterParaSegundos(t2) return criarHorario(segundos)

Esta verso muito mais curta que a original, e muito mais fcil para demonstrar que est correta (assumindo, como sempre, que as funes que so chamadas esto corretas). Como um exerccio, reescreva incrementar da mesma forma. Clique aqui para feedback

13.6 Generalizao Algumas vezes, converter de base 60 para base 10 e voltar mais difcil do que simplesmente lidar com horrios. Converso de base mais abstrata; nossa intuio para lidar com horrios melhor. Mas se ns But if we have the insight to treat times as base 60 numbers and make the investment of writing the conversion functions (converterParaSeguntos e criarHorario), ns conseguimos um programa que menor, fcil de ler e depurar, e mais confivel. tambm fcil para adicionar funcionalidades depois. Por exemplo, imagine subtrair dois Horarios para encontrar a durao entre eles. Uma aproximao ingnua seria implementar subtrao com emprstimo (?? borrowing - Isso mesmo ??). Usando as funes de converso ser mais fcil e provavelmente estar correto. Ironicamente, algumas vezes fazer um problema mais difcil (ou mais genrico) o torna mais simples (porque existem alguns poucos casos especiais e poucas oportunidades para errar). Clique aqui para feedback 13.7 Algoritmos Quando voc escreve uma soluo genrica para uma classe de problemas, ao contrrio de uma soluo especfica para um nico problema, voc escreveu um algortmo. Ns mencionamos isso antes mas no definimos cuidadosamente. Isso no fcil para definir, ento ns vamos tentar //a couple of approaches//. Primeiramente, considere alguma coisa que no seja um algortmo. Quando voc aprendeu a multiplicar nmeros de um dgito, voc provavelmente memorizou a tabela de multiplicao. Como resultado, voc memorizou 100 solues especficas. Esse tipo de conhecimento no algortmo. Mas se voc "preguioso", voc provavelmente trapaceou por ter aprendido alguns truques. Por exemplo, para encontrar o produto de n e 9, voc pode escrever n-1 como o primeiro dgito e 10-n como o segundo dgito. Este truque um soluo genrica para multiplicar qualquer nmero de um dgito por 9. Isso um algoritmo! De modo parecido, as tcnicas que voc aprendeu para adicionar //com transporte//, //subtraction with borrowing//, e diviso longa so todas algortmos. Uma das caractersticas dos algortmos que eles no requerem nenhuma inteligncia para serem executados ( carry out ). Eles so processos mecnicos no qual cada passo segue o ltimo de acordo com um conjunto simples de regras. Na nossa opinio, preocupante que humanos gastem tanto tempo na escola aprendendo a executar algoritmos que, literalmente, no requerem

inteligncia. Por outro lado, o processo de projetar algoritmos interessante, intelectualmente desafiante, e uma parte central daquilo que chamamos programao. Algumas das coisas que as pessoas fazem naturalmente, sem dificuldade ou conscincia, so as mais difceis de se expressar atravs de algoritmos. Entender a linguagem natural um bom exemplo. Todos ns fazemos isso, mas at hoje ningum conseguiu explicar como fazemos isso, pelo menos no na forma de algoritmo. Clique aqui para feedback.

13.8 Glossrio

funo pura (pure function) Uma funo que no modifica nenhum dos objetos que ela recebe como parmetro. A maioria das funes puras fruitful (proveitosa ???). modificador (modifier) Uma funo que muda um ou mais dos objetos que ela recebe como parmetros. A maioria dos modificadores nula. estilo de programao funcional (functional programming style) Um estilo de programao onde a maioria das funes so puras. desenvolvimento prototipado (prototype development) Uma maneira de desenvolver programas comeando com um prottipo e gradualmente melhorando-o. desenvolvimento planejado (planned development) Uma maneira de desenvolver programas que envolvem uma percepo de alto nvel do problema e mais planejamento do que desenvolvimento incremental ou desenvolvimento prototipado. algoritmo (algorithm)

Um conjunto de instrues para resolver uma classe de problemas usando um processo mecnico, no inteligente. System Message: WARNING/2 (<string>, line 16276) Block quote ends without a blank line; unexpected unindent.

Captulo 14: Classes e mtodos


Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos o 3.4 Funes matemticas o 3.5 Composio o 3.6 Adicionando novas funes o 3.7 Definies e uso o 3.8 Fluxo de execuo o 3.9 Parmetros e argumentos o 3.10 Variveis e parmetros so locais o 3.11 Diagramas da pilha o 3.12 Funes com resultados o 3.13 Glossrio

Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao

Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores ATENO As referncias cruzadas a nomes em cdigos de outros captulos (especialmente 13) ainda no foram unificadas... 14.1 Caractersticas da orientao a objetos

Python uma linguagem de programao orientada a objetos, o que significa que ela tem caractersticas que suportam a programao orientada a objetos. No fcil definir programao orientada a objetos, mas temos visto already algumas de suas caractersticas: Programas so construdos sobre definies de objetos e definies de funes, e a maioria das computaes expressa em termos de operaes sobre objetos. Cada definio de objeto corresponde a algum objeto ou conceito do mundo real, e as funes que operam com aqueles objetos correspondem maneira como os objetos do mundo real interagem.

Por exemplo, a classe Tempo, definida no captulo 13 corresponde maneira como as pessoas registram as horas do dia, e as funes que definimos correspondem aos tipos de coisas que as pessoas fazem com times. Do mesmo modo, as classes Ponto e Retngulo correspondem aos conceitos matemticos de um ponto e de um retngulo. At aqui, no tiramos vantagem das caractersticas fornecidas por Python que suportam a programao orientada a objetos. Estritamente falando, estas caractersticas no so necessrias. Na maior parte das vezes, elas fornecem uma sintaxe alternativa para as coisas que j fizemos, mas em muitos casos, a alternativa mais concisa e convm mais acuradamente estrutura do programa. Por exemplo, no programa Time, no existe uma conexo bvia entre a definio da classe e a definio da funo que segue. Com alguma investigao, fica aparente que toda funo toma pelo menos um objeto Time como um parmetro. Esta observao a motivao por trs dos mtodos. J temos visto alguns mtodos, tais como keys (chaves) e values (valores), os quais foram invocados em dicionrios. Cada mtodo associado com uma classe e intended para ser invocado em instncias daquela classe. Mtodos so simplesmente como funes, com duas diferenas: Mtodos so definidos dentro da definio de uma classe para tornar explcita a relao entre a classe e o mtodo. A sintaxe para a chamada do mtodo diferente da sintaxe para a chamada de uma funo. Nas prximas sees, vamos pegar as funes dos dois captulos anteriores e transform-las em mtodos. Esta transformao puramente mecnica: voc pode consegu-la simplesmente seguindo uma seqncia de passos. Se voc se sentir confortvel convertendo de uma forma para a outra, voc estar apto para escolher a melhor forma para seja o l o que for que voc estiver fazendo. 14.2 exibeHora (printTime)

No captulo 13, definimos uma classe chamada Horrio (Time) e voc escreveu uma funo chamada exibeHora (printTime), que deve ter ficado mais ou menos assim:
class Horario: pass

def exibeHora(time) print str(time.horas) + ?:? + \ str(time.minutos) + ?:? + \ str(time.segundos)

Para chamar esta funo, passamos um objeto Time como um parmetro:


>>> horaCorrente = Hora() >>> horaCorrente.horas = 9 >>> horaCorrente.minutos = 14 >>> horaCorrente.segundos = 30 >>> exibeHora(horaCorrente)

Para fazer de exibeHora um mtodo, tudo o que temos a fazer mover a definio da funo para dentro da definio da classe. Note a mudana na endentao:
class Horario: def exibeHora(time): print str(time.horas) + ?:? + \ str(time.minutos) + ?:? + \ str(time.segundos)

Agora podemos chamar exibeHora usando a natao de ponto:


>>> horaCorrente.exibeHora()

Como usual, o objeto no qual o mtodo invocado aparece antes do ponto e o nome do mtodo aparece depois do ponto. O objeto no qual o mtodo invocado atribudo ao primeiro parmetro, ento, neste caso, horaCorrente atribudo ao parmetro time. Por conveno, o primeiro parmetro de um mtodo chamado self. A razo para isto um pouco convoluted, mas baseada numa metfora til. A sintaxe para uma chamada de funo, exibeHora(horaCorrente), sugere que a funo um agente ativo. Diz algo como, ?Ei, exibeHora! Aqui est um objeto para voc exibir.? Na programao orientada a objetos, os objetos so agentes ativos. Uma chamado do tipo horaCorrente.exibeHora() diz ?Ei, horaCorrente! Por favor exiba-se a si mesmo!? Esta mudana de perspectiva pode ser mais polida, mas no fica bvio que seja til. Nos exemplos que temos visto at aqui, pode ser que no seja. Mas

s vezes, deslocar a responsabilidade das funes para cima dos objetos torna possvel escrever funes mais versteis, e torna mais fcil manter e reutilizar o cdigo. 14.3 Um outro exemplo

Vamos converter incremento (da Seo 13.3) em um mtodo. Para poupar espao, deixaremos de fora mtodos definidos previamente(anteriormente?), mas voc deve mant-los em sua verso:
class Time: #previous method definitions here...

def increment(self, segundos): self.seconds = seconds + self.seconds

while self.segundos >= 60: self.seconds = self.segundos - 60 self.minutes = self.minutos + 1

while self.minutes >= 60: self.minutes = self.minutos - 60 self.hours = self.horas + 1

A transformao puramente mecnica ? movemos a definio do mtodo para dentro da definio da classe e mudamos o nome do primeiro parmetro. Agora podemos chamar incremento como um mtodo:
horaCorrente.incremento(500)

De novo, o objeto no qual o mtodo chamado gets atribui ao primeiro parmetro, self. O segundo parmetro, segundo toma(gets) o valor 500. Como um exerccio, converta ?converteParaSegundos? (da Seo 13.5) para um mtodo na classe ?Time?. 14.4 Um exemplo mais complicado

... 14.10 Glossrio

linguagem orientada a objetos Uma linguagem que prov caractersticas tais como classes definidas pelo usurio e herana, que facilitam a programao orientada a objetos. programao orientada a objetos Um estilo de programao na qual os dados e as operaes que os manipulam esto organizados em classes e mtodos. mtodo Uma funo que definida dentro de uma definio de classe e chamada em instncias desta classe. override (sem traducao; termo consagrado) Substituir uma definio j pronta. Exemplos incluem substituir um parmetro padro por um argumento particular e substituir um mtodo padro, fornecendo um novo mtodo com o mesmo nome. mtodo de inicializao (tambem chamado de construtor) Um mtodo especial que invocado automaticamente quando um novo objeto criado e que inicializa os atributos deste objeto. sobrecarga de operador Estender a funcionalidade dos operadores nativos (+, -, *, >, <, etc.) de forma que eles funcionem tambm com tipos definidos pelo usurio. produto escalar Operao definida na lgebra linear que multiplica dois pontos (com coordenadas (x,y,z)) e retorna um valor numrico. multiplicao por escalar Operao definida na lgebra linear que multiplica cada uma das coordenadas de um ponto por um valor numrico. polimrfica

Uma funo que pode operar com mais de um tipo. Se todas as operaes de uma funo pode ser aplicadas a um certo tipo, ento a funo pode ser aplicada a este tipo.

Captulo 14: Classes e mtodos


System Message: INFO/1 (<string>, line 16561); backlink Duplicate implicit target name: "captulo 14: classes e mtodos". Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos o 3.4 Funes matemticas o 3.5 Composio o 3.6 Adicionando novas funes o 3.7 Definies e uso o 3.8 Fluxo de execuo o 3.9 Parmetros e argumentos o 3.10 Variveis e parmetros so locais o 3.11 Diagramas da pilha o 3.12 Funes com resultados o 3.13 Glossrio

Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao

Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores ATENO As referncias cruzadas a nomes em cdigos de outros captulos (especialmente 13) ainda no foram unificadas... 14.1 Caractersticas da orientao a objetos

Python uma linguagem de programao orientada a objetos, o que significa que ela tem caractersticas que suportam a programao orientada a objetos. No fcil definir programao orientada a objetos, mas temos visto already algumas de suas caractersticas: Programas so construdos sobre definies de objetos e definies de funes, e a maioria das computaes expressa em termos de operaes sobre objetos. Cada definio de objeto corresponde a algum objeto ou conceito do mundo real, e as funes que operam com aqueles objetos correspondem maneira como os objetos do mundo real interagem.

Por exemplo, a classe Tempo, definida no captulo 13 corresponde maneira como as pessoas registram as horas do dia, e as funes que definimos correspondem aos tipos de coisas que as pessoas fazem com times. Do mesmo modo, as classes Ponto e Retngulo correspondem aos conceitos matemticos de um ponto e de um retngulo. At aqui, no tiramos vantagem das caractersticas fornecidas por Python que suportam a programao orientada a objetos. Estritamente falando, estas caractersticas no so necessrias. Na maior parte das vezes, elas fornecem uma sintaxe alternativa para as coisas que j fizemos, mas em muitos casos, a alternativa mais concisa e convm mais acuradamente estrutura do programa. Por exemplo, no programa Time, no existe uma conexo bvia entre a definio da classe e a definio da funo que segue. Com alguma investigao, fica aparente que toda funo toma pelo menos um objeto Time como um parmetro. Esta observao a motivao por trs dos mtodos. J temos visto alguns mtodos, tais como keys (chaves) e values (valores), os quais foram invocados em dicionrios. Cada mtodo associado com uma classe e intended para ser invocado em instncias daquela classe. Mtodos so simplesmente como funes, com duas diferenas: Mtodos so definidos dentro da definio de uma classe para tornar explcita a relao entre a classe e o mtodo. A sintaxe para a chamada do mtodo diferente da sintaxe para a chamada de uma funo. Nas prximas sees, vamos pegar as funes dos dois captulos anteriores e transform-las em mtodos. Esta transformao puramente mecnica: voc pode consegu-la simplesmente seguindo uma seqncia de passos. Se voc se sentir confortvel convertendo de uma forma para a outra, voc estar apto para escolher a melhor forma para seja o l o que for que voc estiver fazendo. 14.2 exibeHora (printTime)

No captulo 13, definimos uma classe chamada Horrio (Time) e voc escreveu uma funo chamada exibeHora (printTime), que deve ter ficado mais ou menos assim:
class Horario: pass

def exibeHora(time) print str(time.horas) + ?:? + \ str(time.minutos) + ?:? + \ str(time.segundos)

Para chamar esta funo, passamos um objeto Time como um parmetro:


>>> horaCorrente = Hora() >>> horaCorrente.horas = 9 >>> horaCorrente.minutos = 14 >>> horaCorrente.segundos = 30 >>> exibeHora(horaCorrente)

Para fazer de exibeHora um mtodo, tudo o que temos a fazer mover a definio da funo para dentro da definio da classe. Note a mudana na endentao:
class Horario: def exibeHora(time): print str(time.horas) + ?:? + \ str(time.minutos) + ?:? + \ str(time.segundos)

Agora podemos chamar exibeHora usando a natao de ponto:


>>> horaCorrente.exibeHora()

Como usual, o objeto no qual o mtodo invocado aparece antes do ponto e o nome do mtodo aparece depois do ponto. O objeto no qual o mtodo invocado atribudo ao primeiro parmetro, ento, neste caso, horaCorrente atribudo ao parmetro time. Por conveno, o primeiro parmetro de um mtodo chamado self. A razo para isto um pouco convoluted, mas baseada numa metfora til. A sintaxe para uma chamada de funo, exibeHora(horaCorrente), sugere que a funo um agente ativo. Diz algo como, ?Ei, exibeHora! Aqui est um objeto para voc exibir.? Na programao orientada a objetos, os objetos so agentes ativos. Uma chamado do tipo horaCorrente.exibeHora() diz ?Ei, horaCorrente! Por favor exiba-se a si mesmo!? Esta mudana de perspectiva pode ser mais polida, mas no fica bvio que seja til. Nos exemplos que temos visto at aqui, pode ser que no seja. Mas

s vezes, deslocar a responsabilidade das funes para cima dos objetos torna possvel escrever funes mais versteis, e torna mais fcil manter e reutilizar o cdigo. 14.3 Um outro exemplo

Vamos converter incremento (da Seo 13.3) em um mtodo. Para poupar espao, deixaremos de fora mtodos definidos previamente(anteriormente?), mas voc deve mant-los em sua verso:
class Time: #previous method definitions here...

def increment(self, segundos): self.seconds = seconds + self.seconds

while self.segundos >= 60: self.seconds = self.segundos - 60 self.minutes = self.minutos + 1

while self.minutes >= 60: self.minutes = self.minutos - 60 self.hours = self.horas + 1

A transformao puramente mecnica ? movemos a definio do mtodo para dentro da definio da classe e mudamos o nome do primeiro parmetro. Agora podemos chamar incremento como um mtodo:
horaCorrente.incremento(500)

De novo, o objeto no qual o mtodo chamado gets atribui ao primeiro parmetro, self. O segundo parmetro, segundo toma(gets) o valor 500. Como um exerccio, converta ?converteParaSegundos? (da Seo 13.5) para um mtodo na classe ?Time?. 14.4 Um exemplo mais complicado

... 14.10 Glossrio

linguagem orientada a objetos Uma linguagem que prov caractersticas tais como classes definidas pelo usurio e herana, que facilitam a programao orientada a objetos. programao orientada a objetos Um estilo de programao na qual os dados e as operaes que os manipulam esto organizados em classes e mtodos. mtodo Uma funo que definida dentro de uma definio de classe e chamada em instncias desta classe. override (sem traducao; termo consagrado) Substituir uma definio j pronta. Exemplos incluem substituir um parmetro padro por um argumento particular e substituir um mtodo padro, fornecendo um novo mtodo com o mesmo nome. mtodo de inicializao (tambem chamado de construtor) Um mtodo especial que invocado automaticamente quando um novo objeto criado e que inicializa os atributos deste objeto. sobrecarga de operador Estender a funcionalidade dos operadores nativos (+, -, *, >, <, etc.) de forma que eles funcionem tambm com tipos definidos pelo usurio. produto escalar Operao definida na lgebra linear que multiplica dois pontos (com coordenadas (x,y,z)) e retorna um valor numrico. multiplicao por escalar Operao definida na lgebra linear que multiplica cada uma das coordenadas de um ponto por um valor numrico. polimrfica

Uma funo que pode operar com mais de um tipo. Se todas as operaes de uma funo pode ser aplicadas a um certo tipo, ento a funo pode ser aplicada a este tipo.

Captulo 15: Conjuntos de objetos


Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos o 3.4 Funes matemticas o 3.5 Composio o 3.6 Adicionando novas funes o 3.7 Definies e uso o 3.8 Fluxo de execuo o 3.9 Parmetros e argumentos o 3.10 Variveis e parmetros so locais o 3.11 Diagramas da pilha o 3.12 Funes com resultados o 3.13 Glossrio Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas

4.3 Operadores lgicos 4.4 Execuo condicional 4.5 Execuo alternativa 4.6 Condicionais encadeados 4.7 Condicionais aninhados 4.8 A instruo return 4.9 Recursividade 4.10 Diagramas de pilha para funes recursivas 4.11 Recursividade infinita 4.12 Entrada pelo teclado 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas
o o o o o o o o o o o

Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores

15.1 Composio

At agora, voc vio diversos exemplos de composio. Um dos primeiros exemplos foi o uso de uma invocao de mtodo como parte de uma expresso. Outro exemplo a estrutura aninhada dos comandos: voc pode pr um comando if dentro de um lao while, dentro de outro comando if, e assim por diante. Tendo visto este padro, e tendo aprendido a respeito de listas e objetos, voc no deveria ficar surpreso em aprender que voc pode criar listas de objetos. Voc tambm pode criar obejtos que contm listas (como atritos); voc pode criar listas que contm listas; voc pode criar objetos que contm objetos; e assim por diante. Neste captulo e no prximo, voc ir ver alguns exemplos destas combinaes, usando objetos Carta como exemplo.

15.2 Objetos Carta

Se voc no estiver familiarizado com jogos de cartas, agora um bom momento para conseguir um baralho, ou ento esse captulo pode no fazer muito sentido. H 52 cartas em um baralho, cada uma das quais pertence a um dos quatro naipes e a uma das treze posies. Os naipes so Espadas, Copas, Ouros e Paus (em ordem descendente no bridge). As posies so s, 2, 3, 4, 5, 6, 7, 8, 9, 10, Valete, Rainha e Rei. Dependendo do jogo, a posio do s pode ser maior do que a do Rei ou menor do que a do 2. Se quisermos definir um novo objeto para representar uma carta, bvio que os atributos devem ser posicao e naipe. No to bvio so os tipos aos quais devem pertencer os atributos. Uma possibilidade usar strings contendo palavras como "Espada" para naipes e "Rainha" para posies. Um problema com esta implementao que no seria fcil comparar cartas para ver qual possui o maior naipe ou posio. Uma alternativa usar inteiros para codificar as posies e naipes. "Codificar", neste caso, no significa o mesmo que as pessoas normalmente pensam, que criptografar ou traduzir para um cdigo secreto. O que um cientista da computao quer dizer com "codificar" "definir um mapeamento entre uma seqncia de nmeros e os itens que eu quero representar". Por exemplo: Espadas -> 3 Copas -> 2 Ouros -> 1 Paus -> 0 Uma caracterstica bvia deste mapeamento que os naipes so mapeados para inteiros na ordem, de modo que ns podemos comparar naipes pela comparao de inteiros. O mapeamento de posies bastante bvio. Cada uma das posies numricas mapeia para o inteiro correspondente e, as cartas com figura so mapeadas conforme abaixo: Valete -> 11 Rainha -> 12 Rei -> 13 O motivo pelo qual ns estamos usando notao matemtica para estes mapeamentos que eles no so parte do programa Python. Eles so parte do projeto do programa, mas eles nunca aparecem explicitamente no cdigo. A definio de classe para o tipo Carta fica parecida com esta:
class Carta: def __init__(self, naipe=0, posicao=0): self.naipe = naipe self.posicao = posicao

Como sempre, ns fornecemos um mtodo de inicializao que recebe um parmetro opcional para cada atributo. Para criar um objeto que representa o 3 de Paus, usa-se este comando:
tresDePaus = Carta(0, 3)

O primeiro argumento, 0, representa o naipe de Paus.

15.3 Atributos de classe e o mtodo __str__

Para imprimir objetos Carta de uma maneira que as pessoas possam facilmente ler, ns gostaramos de mapear os cdigos inteiros para palavras. Uma forma natural de fazer isso usar listas de strings. Ns atribumos estas listas para atributos de classe no topo da definio de classe:
class Carta: listaDeNaipes = ["Paus", "Ouros", "Copas", "Espadas"] listaDePosicoes = ["narf", "s", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Valete", "Rainha", "Rei"]

# mtodo init omitido

def __str__(self): return (self.listaDePosicoes[self.posicao] + " de " + self.ListaDeNaipes[self.naipe])

Um atributo de classe definido fora de qualquer mtodo, e ele pode ser acessado por quaisquer mtodos da classe. Dentro de __str__, ns podemos usar listaDeNaipes e listaDePosicoes para mapear os valores numricos de naipe e posicao para strings. Por exemplo, a expresso self.listaDeNaipes[self.naipe] significa "use o atributo naipe do objeto self como um ndice para o atributo de classe chamado listaDeNaipes, e selecione a string apropriada". O motivo para o "narf" no primeiro elemento em listaDePosicoes preencher o lugar do 0-simo elemento da lista, que nunca ser usado. As nicas posies vlidas so de 1 a 13. Este item desperdiado no inteiramente necessrio.

Ns poderamos ter iniciado com 0, como normal. Porm, menos confuso codificar 2 como 2, 3 como 3, e assim por diante. Com os mtodos que ns temos at agora, ns podemos criar e imprimir cartas:
>>> carta1 = Carta(1, 11) >>> print carta1 Valete de Ouros

Atributos de classe como listaDeNaipes so compartilhados por todos os objetos Carta. A vantagem disso que ns podemos usar qualquer objeto Carta para acessar os atributos de classe:
>>> carta2 = Carta(1, 3) >>> print carta2 3 de Ouros >>> print carta2.listaDeNaipes[1] Ouros

A desvantagem que se ns modificarmos um atributo de classe, isso afetar cada instncia da classe. Por exemplo, se ns decidirmos que "Valete de Ouros" deveria realmente se chamar "Valete de Baleias Rodopiantes", ns poderamos fazer isso:
>>> carta1.listaDeNaipes = "Baleias Rodopiantes" >>> print carta1 3 de Baleias Rodopiantes

O problema que todos os Ouros se tornam Baleias Rodopiantes:


>>> print carta2 3 de Baleias Rodopiantes

Normalmente, no uma boa idia modificar atributos de classe.

15.4 Comparando cartas

Para tipos primitivos, existem operadores condicionais (<, >, ==, etc.) que comparam valores e determinam quando um maior que, menor que ou igual

a outro. Para tipos definidos pelo usurio, ns podemos sobrescrever o comportamento dos operadores pr-definidos fornecendo um mtodo __cmp__. Por conveno, __cmp__ recebe dois parmetros, self e other, e retorna 1 se o primeiro objeto for maior, -1 se o segundo objeto for maior, e 0 se eles forem iguais. Alguns tipos so totalmente ordenados, o que significa que ns podemos comparar quaisquer dois elementos e dizer qual o maior. Por exemplo, os inteiros e os nmeros de ponto flutuante so totalmente ordenados. Alguns conjuntos so no-ordenados, o que significa que no existe maneira significativa de dizer que um elemento maior que o outro. Por exemplo, as frutas so no-ordenadas, e por isso que no podemos comparar mas e laranjas. O conjunto de cartas de jogo parcialmente ordenado, o que significa que s vezes voc pode comparar cartas, e s vezes no. Por exemplo, voc sabe que o 3 de Paus maior do que o 2 de Paus, e que o 3 de Ouros maior do que o 3 de Paus. Mas qual o melhor, o 3 de Paus ou o 2 de Ouros? Um tem uma posio maior, mas o outro tem um naipe maior. Para tornar as cartas comparveis, voc tem que decidir o que mais importante: posio ou naipe. Para ser honesto, a escolha arbitrria. Por questo de escolha, ns iremos dizer que naipe mais importante, porque um baralho de cartas novo vem ordenado com todas as cartas de Paus juntas, seguidas pelas de Ouros, e assim por diante. Com essa deciso, ns podemos escrever __cmp__:
def __cmp__(self, other): # verificar os naipes if self.naipe > other.naipe: return 1 if self.naipe < other.naipe: return -1 # as cartas tm o mesmo naipe... verificar as posies if self.posicao > other.posicao: return 1 if self.posicao < other.posicao> return -1 # as posies so iguais... um empate return 0

Nesta ordenao, Ases so menores do que 2. Como um exerccio, modifique ``__cmp__``, de modo que os Ases sejam maiores do que os Reis.

15.5 Baralhos

Agora que ns temos objetos para representar Cartas, o prximo passo lgico definir uma classe para representar um Baralho. claro que um baralho formado por cartas; portanto, cada objeto Baralho ir conter uma lista de cartas como um atributo. A seguir, damos uma definio para a classe Baralho. O mtodo de inicializao cria o atributo cartas e gera o conjunto padro de 52 cartas:
classe Baralho def __init__(self): self.cartas = [] for naipe in range(4): for posicao in range(1, 14): self.cartas.append(Carta(naipe, posicao))

A maneira mais fcil de popular o baralho com um lao aninhado. O lao externo enumera os naipes de 0 at 3. O lao interno enumera as posies de 1 at 13. Como o lao externo repete quatro vezes e o lao interno 13 vezes, o nmero total de vezes que o corpo executado 52 (13 vezes quatro). Cada iterao cria uma nova instncia de Carta com o naipe e posio atuais e a inclui na lista cartas. O mtodo append trabalha sobre listas mas no, obviamente, sobre tuplas.

15.6 Imprimindo o baralho

Como sempre, quando ns definimos um novo tipo de objeto, ns gostaramos de ter um mtodo para imprimir o contedo de um objeto. Para imprimir um Baralho, ns percorremos a lista e imprimimos cada Carta:
class Baralho: ... def imprimirBaralho(self): for carta in self.cartas: print carta

Aqui, e a partir daqui, as reticncias (...) indicam que ns omitimos os outros mtodos da classe. Como uma alternativa a imprimirBaralho, ns poderamos escrever um mtodo __str__ para a classe Baralho. A vantagem de __str__ que ela mais flexvel. Em vez de apenas imprimir o contedo de um objeto, ela gera uma representao em string que outras partes do programa podem manipular antes de imprimir ou armazenar para uso posterior. Abaixo, uma verso de __str__ que devolve uma representao em string de um Baralho. Para adicionar um pouco de estilo, ela distribui as cartas em uma cascata, na qual cada carta indentada um espao a mais do que a carta anterior:
class Baralho: ... def __str__(self): s = "" for i in range(len(self.cartas)): s = s + " "*i + str(self.cartas[i]) + "\n" return s

Este exemplo demonstra diversas caractersticas. Primeiro, em vez de percorrer self.cartas e atribuir cada carta a uma varivel, ns estamos usando i como uma varivel de lao e um ndice para a lista de cartas. Segundo, ns estamos usando o operador de multiplicao de strings para indentar cada carta com um espao adicional com relao anterior. A expresso " "*i produz um nmero de espaos igual ao valor atual de i. Terceiro, em vez de usar o comando print para imprimir as cartas, ns usamos a funo str. Passar um objeto como um argumento para str equivale a invocar o mtodo __str__ sobre o objeto. Finalmente, ns estamos usando a varivel s como um acumulador. Inicialmente, s a string vazia. A cada repetio do lao, uma nova string gerada e concatenada com o valor antigo de s para obter um novo valor. Quando o lao termina, s contm a representao em string completa do Baralho, que se parece com:
>>> baralho = Baralho() >>> print Baralho s de Paus

2 de Paus 3 de Paus 4 de Paus 5 de Paus 6 de Paus 7 de Paus 8 de Paus 9 de Paus 10 de Paus Valete de Paus Rainha de Paus Rei de Paus s de Ouros

E assim por diante. Mesmo que o resultado aparea em 52 linhas, uma string longa que contm newlines.

15.7 Embaralhando

Se um baralho estiver perfeitamente embaralhado, ento cada carta tem a mesma probabilidade de aparecer em qualquer lugar no baralho, e qualquer localizao no baralho tem a mesma probabilidade de conter qualquer carta. Para embaralhar as cartas, ns usaremos a funo randrange do mdulo random. Com dois argumentos inteiros, a e b, randrange escolhe um inteiro aleatrio no intervalo a <= x < b. Como o limite superior estritamente menor que b, ns podemos usar o comprimento de uma lista como o segundo parmetro, e ns garantimos que o ndice sempre ser vlido. Por exemplo, esta expresso escolhe o ndice de uma carta aleatria em um baralho:
random.randrange(0, len(self.cartas))

Uma maneira fcil de embaralhar as cartas percorrer a lista e trocar cada carta por outra escolhida aleatoriamente. possvel que a carta seja trocada por ela mesma, mas isso no problema. Na verdade, se ns exclussemos essa possibilidade, a ordem das cartas no seria totalmente aleatria:
class Baralho:

... def embaralhar(self): import random nCartas = len(self.cartas) for i in range(nCartas): j = random.randrange(i, nCartas) self.cartas[i], self.cartas[j] = self.cartas[j], self.cartas[i]

Em vez de assumir que existem 52 cartas no baralho, ns obtivemos o comprimento real da lista e o guardamos na varivel nCartas. Para cada carta no baralho, ns escolhemos uma carta aleatria dentre as cartas que ainda no foram embaralhadas. Ento, ns trocamos a carta atual (i) pela carta selecionada (j). Para trocar as cartas, ns usamos uma atribuio de tupla, como visto na Seo 9.2:
self.cartas[i], self.cartas[j] = self.cartas[j], self.cartas[i]

Como exerccio, reescreva esta linha de cdigo sem usar uma atribuio de seqncia.

15.8 Removendo e distribuindo cartas

Outro mtodo que pode ser til para a classe Baralho removerCarta. Ele recebe uma carta como parmetro, remove-a do baralho e retorna verdadeiro (1), se a carta estava no baralho e falso (0), caso contrrio:
class Baralho: ... def removerCarta(self, carta): if carta in self.cartas: self.cartas.remove(carta) return 1 else return 0

O operador in retorna verdadeiro se o primeiro operando estiver contido no

segundo, que deve ser uma lista ou uma tupla. Se o primeiro operando for um objeto, Python usa o mtodo __cmp__ do objeto para determinar igualdade com os itens da lista. Como o mtodo __cmp__ da classe Carta verifica por igualdade profunda, o mtodo removerCarta tambm testa por igualdade profunda. Para distribuir as cartas, ns iremos remover e devolver a carta do topo. O mtodo de lista pop fornece uma maneira conveniente de fazer isso:
class Baralho: ... def distribuirCarta(self): return self.cards.pop()

Na verdade, pop remove a ltima carta da lista. Portanto, ns estamos realmente distribuindo as cartas do fim para o incio do baralho. Uma ltima operao que ns poderamos querer a funo booleana estahVazio, que retorna verdadeiro se o baralho no contm cartas:
class Baralho: ... def estahVazio(self): return (len(self.cartas) == 0)

15.9 Glossrio

codificar (encode) Representar um conjunto de valores usando outro conjunto de valores, construindo um mapeamento entre eles. atributo de classe (class atribute) Uma varivel que definida dentro de uma definio de classe, mas fora de qualquer mtodo. Atributos de classe podem ser acessados a partir de qualquer mtodo da classe e so compartilhados por todas as instncias da classe. acumulador (accumulator) Uma varivel usada em um lao para acumular uma srie de valores, para, por exemplo, concaten-los em uma string ou som-los a uma soma em

andamento.

Captulo 15: Conjuntos de objetos


System Message: INFO/1 (<string>, line 17404); backlink Duplicate implicit target name: "captulo 15: conjuntos de objetos". Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos o 3.4 Funes matemticas o 3.5 Composio o 3.6 Adicionando novas funes o 3.7 Definies e uso o 3.8 Fluxo de execuo o 3.9 Parmetros e argumentos o 3.10 Variveis e parmetros so locais o 3.11 Diagramas da pilha o 3.12 Funes com resultados o 3.13 Glossrio Captulo 3: Funes Captulo 4: Condicionais e recurso

4.1 O operador mdulo 4.2 Expresses booleanas 4.3 Operadores lgicos 4.4 Execuo condicional 4.5 Execuo alternativa 4.6 Condicionais encadeados 4.7 Condicionais aninhados 4.8 A instruo return 4.9 Recursividade 4.10 Diagramas de pilha para funes recursivas 4.11 Recursividade infinita 4.12 Entrada pelo teclado 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao Captulo 6: Iterao Captulo 7: Strings
o o o o o o o o o o o o o

Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores

15.1 Composio

At agora, voc vio diversos exemplos de composio. Um dos primeiros exemplos foi o uso de uma invocao de mtodo como parte de uma expresso. Outro exemplo a estrutura aninhada dos comandos: voc pode pr um comando if dentro de um lao while, dentro de outro comando if, e assim por diante. Tendo visto este padro, e tendo aprendido a respeito de listas e objetos, voc no deveria ficar surpreso em aprender que voc pode criar listas de objetos. Voc tambm pode criar obejtos que contm listas (como atritos); voc pode criar listas que contm listas; voc pode criar objetos que contm objetos; e assim por diante. Neste captulo e no prximo, voc ir ver alguns exemplos destas combinaes, usando objetos Carta como exemplo.

15.2 Objetos Carta

Se voc no estiver familiarizado com jogos de cartas, agora um bom momento para conseguir um baralho, ou ento esse captulo pode no fazer muito sentido. H 52 cartas em um baralho, cada uma das quais pertence a um dos quatro naipes e a uma das treze posies. Os naipes so Espadas, Copas, Ouros e Paus (em ordem descendente no bridge). As posies so s, 2, 3, 4, 5, 6, 7, 8, 9, 10, Valete, Rainha e Rei. Dependendo do jogo, a posio do s pode ser maior do que a do Rei ou menor do que a do 2. Se quisermos definir um novo objeto para representar uma carta, bvio que os atributos devem ser posicao e naipe. No to bvio so os tipos aos quais devem pertencer os atributos. Uma possibilidade usar strings contendo palavras como "Espada" para naipes e "Rainha" para posies. Um problema com esta implementao que no seria fcil comparar cartas para ver qual possui o maior naipe ou posio. Uma alternativa usar inteiros para codificar as posies e naipes. "Codificar", neste caso, no significa o mesmo que as pessoas normalmente pensam, que criptografar ou traduzir para um cdigo secreto. O que um cientista da computao quer dizer com "codificar" "definir um mapeamento entre uma seqncia de nmeros e os itens que eu quero representar". Por exemplo: Espadas -> 3 Copas -> 2 Ouros -> 1 Paus -> 0 Uma caracterstica bvia deste mapeamento que os naipes so mapeados para inteiros na ordem, de modo que ns podemos comparar naipes pela comparao de inteiros. O mapeamento de posies bastante bvio. Cada uma das posies numricas mapeia para o inteiro correspondente e, as cartas com figura so mapeadas conforme abaixo: Valete -> 11 Rainha -> 12 Rei -> 13 O motivo pelo qual ns estamos usando notao matemtica para estes mapeamentos que eles no so parte do programa Python. Eles so parte do projeto do programa, mas eles nunca aparecem explicitamente no cdigo. A definio de classe para o tipo Carta fica parecida com esta:
class Carta: def __init__(self, naipe=0, posicao=0):

self.naipe = naipe self.posicao = posicao

Como sempre, ns fornecemos um mtodo de inicializao que recebe um parmetro opcional para cada atributo. Para criar um objeto que representa o 3 de Paus, usa-se este comando:
tresDePaus = Carta(0, 3)

O primeiro argumento, 0, representa o naipe de Paus.

15.3 Atributos de classe e o mtodo __str__

Para imprimir objetos Carta de uma maneira que as pessoas possam facilmente ler, ns gostaramos de mapear os cdigos inteiros para palavras. Uma forma natural de fazer isso usar listas de strings. Ns atribumos estas listas para atributos de classe no topo da definio de classe:
class Carta: listaDeNaipes = ["Paus", "Ouros", "Copas", "Espadas"] listaDePosicoes = ["narf", "s", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Valete", "Rainha", "Rei"]

# mtodo init omitido

def __str__(self): return (self.listaDePosicoes[self.posicao] + " de " + self.ListaDeNaipes[self.naipe])

Um atributo de classe definido fora de qualquer mtodo, e ele pode ser acessado por quaisquer mtodos da classe. Dentro de __str__, ns podemos usar listaDeNaipes e listaDePosicoes para mapear os valores numricos de naipe e posicao para strings. Por exemplo, a expresso self.listaDeNaipes[self.naipe] significa "use o atributo naipe do objeto self como um ndice para o atributo de classe chamado listaDeNaipes, e selecione a string apropriada".

O motivo para o "narf" no primeiro elemento em listaDePosicoes preencher o lugar do 0-simo elemento da lista, que nunca ser usado. As nicas posies vlidas so de 1 a 13. Este item desperdiado no inteiramente necessrio. Ns poderamos ter iniciado com 0, como normal. Porm, menos confuso codificar 2 como 2, 3 como 3, e assim por diante. Com os mtodos que ns temos at agora, ns podemos criar e imprimir cartas:
>>> carta1 = Carta(1, 11) >>> print carta1 Valete de Ouros

Atributos de classe como listaDeNaipes so compartilhados por todos os objetos Carta. A vantagem disso que ns podemos usar qualquer objeto Carta para acessar os atributos de classe:
>>> carta2 = Carta(1, 3) >>> print carta2 3 de Ouros >>> print carta2.listaDeNaipes[1] Ouros

A desvantagem que se ns modificarmos um atributo de classe, isso afetar cada instncia da classe. Por exemplo, se ns decidirmos que "Valete de Ouros" deveria realmente se chamar "Valete de Baleias Rodopiantes", ns poderamos fazer isso:
>>> carta1.listaDeNaipes = "Baleias Rodopiantes" >>> print carta1 3 de Baleias Rodopiantes

O problema que todos os Ouros se tornam Baleias Rodopiantes:


>>> print carta2 3 de Baleias Rodopiantes

Normalmente, no uma boa idia modificar atributos de classe.

15.4 Comparando cartas

Para tipos primitivos, existem operadores condicionais (<, >, ==, etc.) que comparam valores e determinam quando um maior que, menor que ou igual a outro. Para tipos definidos pelo usurio, ns podemos sobrescrever o comportamento dos operadores pr-definidos fornecendo um mtodo __cmp__. Por conveno, __cmp__ recebe dois parmetros, self e other, e retorna 1 se o primeiro objeto for maior, -1 se o segundo objeto for maior, e 0 se eles forem iguais. Alguns tipos so totalmente ordenados, o que significa que ns podemos comparar quaisquer dois elementos e dizer qual o maior. Por exemplo, os inteiros e os nmeros de ponto flutuante so totalmente ordenados. Alguns conjuntos so no-ordenados, o que significa que no existe maneira significativa de dizer que um elemento maior que o outro. Por exemplo, as frutas so no-ordenadas, e por isso que no podemos comparar mas e laranjas. O conjunto de cartas de jogo parcialmente ordenado, o que significa que s vezes voc pode comparar cartas, e s vezes no. Por exemplo, voc sabe que o 3 de Paus maior do que o 2 de Paus, e que o 3 de Ouros maior do que o 3 de Paus. Mas qual o melhor, o 3 de Paus ou o 2 de Ouros? Um tem uma posio maior, mas o outro tem um naipe maior. Para tornar as cartas comparveis, voc tem que decidir o que mais importante: posio ou naipe. Para ser honesto, a escolha arbitrria. Por questo de escolha, ns iremos dizer que naipe mais importante, porque um baralho de cartas novo vem ordenado com todas as cartas de Paus juntas, seguidas pelas de Ouros, e assim por diante. Com essa deciso, ns podemos escrever __cmp__:
def __cmp__(self, other): # verificar os naipes if self.naipe > other.naipe: return 1 if self.naipe < other.naipe: return -1 # as cartas tm o mesmo naipe... verificar as posies if self.posicao > other.posicao: return 1 if self.posicao < other.posicao> return -1 # as posies so iguais... um empate return 0

Nesta ordenao, Ases so menores do que 2. Como um exerccio, modifique ``__cmp__``, de modo que os Ases sejam maiores do que os Reis.

15.5 Baralhos

Agora que ns temos objetos para representar Cartas, o prximo passo lgico definir uma classe para representar um Baralho. claro que um baralho formado por cartas; portanto, cada objeto Baralho ir conter uma lista de cartas como um atributo. A seguir, damos uma definio para a classe Baralho. O mtodo de inicializao cria o atributo cartas e gera o conjunto padro de 52 cartas:
classe Baralho def __init__(self): self.cartas = [] for naipe in range(4): for posicao in range(1, 14): self.cartas.append(Carta(naipe, posicao))

A maneira mais fcil de popular o baralho com um lao aninhado. O lao externo enumera os naipes de 0 at 3. O lao interno enumera as posies de 1 at 13. Como o lao externo repete quatro vezes e o lao interno 13 vezes, o nmero total de vezes que o corpo executado 52 (13 vezes quatro). Cada iterao cria uma nova instncia de Carta com o naipe e posio atuais e a inclui na lista cartas. O mtodo append trabalha sobre listas mas no, obviamente, sobre tuplas.

15.6 Imprimindo o baralho

Como sempre, quando ns definimos um novo tipo de objeto, ns gostaramos de ter um mtodo para imprimir o contedo de um objeto. Para imprimir um Baralho, ns percorremos a lista e imprimimos cada Carta:
class Baralho: ... def imprimirBaralho(self): for carta in self.cartas:

print carta

Aqui, e a partir daqui, as reticncias (...) indicam que ns omitimos os outros mtodos da classe. Como uma alternativa a imprimirBaralho, ns poderamos escrever um mtodo __str__ para a classe Baralho. A vantagem de __str__ que ela mais flexvel. Em vez de apenas imprimir o contedo de um objeto, ela gera uma representao em string que outras partes do programa podem manipular antes de imprimir ou armazenar para uso posterior. Abaixo, uma verso de __str__ que devolve uma representao em string de um Baralho. Para adicionar um pouco de estilo, ela distribui as cartas em uma cascata, na qual cada carta indentada um espao a mais do que a carta anterior:
class Baralho: ... def __str__(self): s = "" for i in range(len(self.cartas)): s = s + " "*i + str(self.cartas[i]) + "\n" return s

Este exemplo demonstra diversas caractersticas. Primeiro, em vez de percorrer self.cartas e atribuir cada carta a uma varivel, ns estamos usando i como uma varivel de lao e um ndice para a lista de cartas. Segundo, ns estamos usando o operador de multiplicao de strings para indentar cada carta com um espao adicional com relao anterior. A expresso " "*i produz um nmero de espaos igual ao valor atual de i. Terceiro, em vez de usar o comando print para imprimir as cartas, ns usamos a funo str. Passar um objeto como um argumento para str equivale a invocar o mtodo __str__ sobre o objeto. Finalmente, ns estamos usando a varivel s como um acumulador. Inicialmente, s a string vazia. A cada repetio do lao, uma nova string gerada e concatenada com o valor antigo de s para obter um novo valor. Quando o lao termina, s contm a representao em string completa do Baralho, que se parece com:
>>> baralho = Baralho() >>> print Baralho s de Paus

2 de Paus 3 de Paus 4 de Paus 5 de Paus 6 de Paus 7 de Paus 8 de Paus 9 de Paus 10 de Paus Valete de Paus Rainha de Paus Rei de Paus s de Ouros

E assim por diante. Mesmo que o resultado aparea em 52 linhas, uma string longa que contm newlines.

15.7 Embaralhando

Se um baralho estiver perfeitamente embaralhado, ento cada carta tem a mesma probabilidade de aparecer em qualquer lugar no baralho, e qualquer localizao no baralho tem a mesma probabilidade de conter qualquer carta. Para embaralhar as cartas, ns usaremos a funo randrange do mdulo random. Com dois argumentos inteiros, a e b, randrange escolhe um inteiro aleatrio no intervalo a <= x < b. Como o limite superior estritamente menor que b, ns podemos usar o comprimento de uma lista como o segundo parmetro, e ns garantimos que o ndice sempre ser vlido. Por exemplo, esta expresso escolhe o ndice de uma carta aleatria em um baralho:
random.randrange(0, len(self.cartas))

Uma maneira fcil de embaralhar as cartas percorrer a lista e trocar cada carta por outra escolhida aleatoriamente. possvel que a carta seja trocada por ela mesma, mas isso no problema. Na verdade, se ns exclussemos essa possibilidade, a ordem das cartas no seria totalmente aleatria:

class Baralho: ... def embaralhar(self): import random nCartas = len(self.cartas) for i in range(nCartas): j = random.randrange(i, nCartas) self.cartas[i], self.cartas[j] = self.cartas[j], self.cartas[i]

Em vez de assumir que existem 52 cartas no baralho, ns obtivemos o comprimento real da lista e o guardamos na varivel nCartas. Para cada carta no baralho, ns escolhemos uma carta aleatria dentre as cartas que ainda no foram embaralhadas. Ento, ns trocamos a carta atual (i) pela carta selecionada (j). Para trocar as cartas, ns usamos uma atribuio de tupla, como visto na Seo 9.2:
self.cartas[i], self.cartas[j] = self.cartas[j], self.cartas[i]

Como exerccio, reescreva esta linha de cdigo sem usar uma atribuio de seqncia.

15.8 Removendo e distribuindo cartas

Outro mtodo que pode ser til para a classe Baralho removerCarta. Ele recebe uma carta como parmetro, remove-a do baralho e retorna verdadeiro (1), se a carta estava no baralho e falso (0), caso contrrio:
class Baralho: ... def removerCarta(self, carta): if carta in self.cartas: self.cartas.remove(carta) return 1 else return 0

O operador in retorna verdadeiro se o primeiro operando estiver contido no segundo, que deve ser uma lista ou uma tupla. Se o primeiro operando for um objeto, Python usa o mtodo __cmp__ do objeto para determinar igualdade com os itens da lista. Como o mtodo __cmp__ da classe Carta verifica por igualdade profunda, o mtodo removerCarta tambm testa por igualdade profunda. Para distribuir as cartas, ns iremos remover e devolver a carta do topo. O mtodo de lista pop fornece uma maneira conveniente de fazer isso:
class Baralho: ... def distribuirCarta(self): return self.cards.pop()

Na verdade, pop remove a ltima carta da lista. Portanto, ns estamos realmente distribuindo as cartas do fim para o incio do baralho. Uma ltima operao que ns poderamos querer a funo booleana estahVazio, que retorna verdadeiro se o baralho no contm cartas:
class Baralho: ... def estahVazio(self): return (len(self.cartas) == 0)

15.9 Glossrio

codificar (encode) Representar um conjunto de valores usando outro conjunto de valores, construindo um mapeamento entre eles. atributo de classe (class atribute) Uma varivel que definida dentro de uma definio de classe, mas fora de qualquer mtodo. Atributos de classe podem ser acessados a partir de qualquer mtodo da classe e so compartilhados por todas as instncias da classe. acumulador (accumulator)

Uma varivel usada em um lao para acumular uma srie de valores, para, por exemplo, concaten-los em uma string ou som-los a uma soma em andamento. System Message: WARNING/2 (<string>, line 17961) Block quote ends without a blank line; unexpected unindent.

Capitulo 16: Herana


Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos o 3.4 Funes matemticas o 3.5 Composio o 3.6 Adicionando novas funes o 3.7 Definies e uso o 3.8 Fluxo de execuo o 3.9 Parmetros e argumentos o 3.10 Variveis e parmetros so locais o 3.11 Diagramas da pilha o 3.12 Funes com resultados o 3.13 Glossrio

Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao

Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores 16.1 - Herana

Uma das caractersitcas mais frequentes das linguagens orientadas a objetos a herana. Herana a habilidade de definir uma nova classe utilizando uma verso modificada de uma classe existente. A principal vantagem desta caracterstica que voc pode adicionar novos mtodos a uma classe sem ter que modificar uma classe existente. Isso chamado Herana porque a nova classe herda todos os mtodos da classe existente. Extendendo esta metfora, podemos dizer que classe existente as vezes chamada de classe pai. A nova classe pode ser chamada de classe filho ou simplesmente "subclasse". Herana uma poderosa caracterstica. Alguns programas seriam muito complicados sem a herana, que podem ser escrito de forma simples e concisa com a ajuda da herana. E a herana tambm permite o reuso do cdigo, uma vez que voc pode modificar o comportamento de classes pai sem ter que modifica-las. Em alguns casos, a estrutura da herana reflete a

natureza real do problema, o que torna o programa simples de se entender. Em outras vezes, a herana pode fazer com que o programa seja difcil de ler. Quando um mtodo invocado, as vezes ele no claro onde procurar a sua definio. A parte relevante do cdigo pode ser dispersado em uma srie de mdulos. E tambm a maioria das coisas que podem ser feitas utilizando heranas tambm podem ser feitas elegantemente sem ela. Se a estrutura natural do problema no leve a s mesmo a utilizar a herana, este pode ser um estilo de programao que cause mais dano que ajuda. Neste captulo, ns iremos demonstrar o uso da herana como parte de um programa de jogar cartas Old Maid . O Objetivo escrever um cdigo que permite o reuso implementando em outros jogos de cartas.

Capitulo 16: Herana


System Message: INFO/1 (<string>, line 17994); backlink Duplicate implicit target name: "capitulo 16: herana". Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos

3.4 Funes matemticas 3.5 Composio 3.6 Adicionando novas funes 3.7 Definies e uso 3.8 Fluxo de execuo 3.9 Parmetros e argumentos 3.10 Variveis e parmetros so locais 3.11 Diagramas da pilha 3.12 Funes com resultados 3.13 Glossrio Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 5: Funes frutferas
o o o o o o o o o o

5.1 Valores de retorno 5.2 Desenvolvimento de programas 5.3 Composio 5.4 Funes booleanas 5.5 Mais recursividade 5.6 Voto de confiana (Leap of faith) 5.7 Mais um exemplo 5.8 Checagem de tipos 5.9 Glossrio Captulo 6: Iterao Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores
o o o o o o o o o

16.1 - Herana

Uma das caractersitcas mais frequentes das linguagens orientadas a objetos a herana. Herana a habilidade de definir uma nova classe utilizando uma verso modificada de uma classe existente. A principal vantagem desta caracterstica que voc pode adicionar novos mtodos a uma classe sem ter que modificar uma classe existente. Isso chamado Herana porque a nova classe herda todos os mtodos da classe

existente. Extendendo esta metfora, podemos dizer que classe existente as vezes chamada de classe pai. A nova classe pode ser chamada de classe filho ou simplesmente "subclasse". Herana uma poderosa caracterstica. Alguns programas seriam muito complicados sem a herana, que podem ser escrito de forma simples e concisa com a ajuda da herana. E a herana tambm permite o reuso do cdigo, uma vez que voc pode modificar o comportamento de classes pai sem ter que modifica-las. Em alguns casos, a estrutura da herana reflete a natureza real do problema, o que torna o programa simples de se entender. Em outras vezes, a herana pode fazer com que o programa seja difcil de ler. Quando um mtodo invocado, as vezes ele no claro onde procurar a sua definio. A parte relevante do cdigo pode ser dispersado em uma srie de mdulos. E tambm a maioria das coisas que podem ser feitas utilizando heranas tambm podem ser feitas elegantemente sem ela. Se a estrutura natural do problema no leve a s mesmo a utilizar a herana, este pode ser um estilo de programao que cause mais dano que ajuda. System Message: SEVERE/4 (<string>, line 18020) Title level inconsistent:
Neste captulo, ns iremos demonstrar o uso da herana como parte de um programa de jogar cartas **Old Maid** . O Objetivo escrever um cdigo que permite o reuso implementando em outros jogos de cartas. ==============================

System Message: SEVERE/4 (<string>, line 18022) Title level inconsistent:


Captulo 17: Listas encadeadas ==============================

Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos

2.1 Valores e tipos 2.2 Variveis 2.3 Nomes de variveis e palavras reservadas 2.4 Comandos 2.5 Avaliando expresses 2.6 Operadores e operandos 2.7 Ordem dos operadores 2.8 Operaes com strings 2.9 Composio 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos o 3.4 Funes matemticas o 3.5 Composio o 3.6 Adicionando novas funes o 3.7 Definies e uso o 3.8 Fluxo de execuo o 3.9 Parmetros e argumentos o 3.10 Variveis e parmetros so locais o 3.11 Diagramas da pilha o 3.12 Funes com resultados o 3.13 Glossrio Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas
o o o o o o o o o o

4.11 Recursividade infinita 4.12 Entrada pelo teclado 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas
o o o

Captulo 20: rvores Captulo 20: rvores

17.1 Referncias Embutidas

Ns temos visto exemplos de atributos que referenciam outros objetos, que so chamados referncias embutidas (veja a Seo 12.8). Uma estrutura de dados comum, a lista ligada, tira vantagem desta caracterstica. Listas ligadas so constitudas de ns (nodos), onde cada n contm uma referncia para o prximo n na lista. Alm disto, cada n contm uma unidade de dados chamada a carga. Uma lista ligada considerada uma estrutura de dados recorrente porque ela tem uma definio recorrente. Uma lista ligada Uma lista vazia, representada por None, ou Um n que contm um objeto carga e uma referncia para uma lista ligada. Estruturas de dados recorrentes so adequadas para mtodos recorrentes.

17.2 A classe No (Node)

Como usual quando se escreve uma nova classe, ns comearemos com os mtodos de inicializao e __str__ de modo que podemos testar o mecanismo bsico de se criar e mostrar o novo tipo:
class No: def __init__(self, carga=None, proximo=None): self.carga = carga self.proximo = proximo

def __str__(self): return str(self.carga)

Como de costume, os parmetros para o mtodo de inicializao so opcionais. Por omisso (default), ambos, a carga e a ligao, proximo, so definidas como None. A representao string de um n simplesmente a representao string da carga. Como qualquer valor pode ser passado para a funo str, ns podemos armazenar qualquer valor em uma lista. Para testar a implementao at agora, ns criamos um No e o imprimimos:
>>> no = No("teste") >>> print no teste

Para ficar interessante, ns precisamos uma lista com mais do que um n:


>>> no1 = No(1) >>> no2 = No(2) >>> no3 = No(3)

Este cdigo cria trs ns, mas ns ainda no temos uma lista ainda porque os ns no esto ligados. O diagrama de estado parecido com este:

Para ligar os ns, temos que fazer o primeiro n da lista referir ao segundo e o segundo n referir ao terceiro:
>>> no1.proximo = no2 >>> no2.proximo = no3

A referncia do terceiro n None, que indica que ele o final da lista. Agora o diagrama de estado se parece com:

Agora voc sabe como criar ns e lig-los em uma lista. O que pode estar menos claro neste ponto por qu.

17.3 Listas como Colees

Listas so teis porque elas provm um modo de montar mltiplos objetos em uma nica entidade, algumas vezes chamada uma coleo. No exemplo, o primeiro n da lista serve como uma referncia para toda a lista. Para passar uma lista como um parmetro, voc apenas tem que passar uma referncia ao primeiro n. Por exemplo, a funo imprimeLista toma um nico n como um argumento. Iniciando com o cabea da lista, ela imprime cada n at que chegue ao fim:
def imprimeLista(no): while no: print no, no = no.proximo print

Para chamar este mtodo, ns passamos uma referncia ao primeiro no:


>>> imprimeLista(no1) 123

Dentro de imprimeLista ns temos uma referncia para o primeiro n da lista, mas no h variveis que refiram aos outros ns. Ns temos que usar o valor proximo de cada n para alcanar o prximo n. Para percorrer uma lista ligada, comum usar uma varivel lao como no para referir a cada um dos ns sucessivamente. Este diagrama mostra o valor de lista e os valores que no assume:

Por conveno, listas so freqentemente impressas em braquetes com vrgulas entre os elementos, como em [1, 2, 3]. Como um exerccio, modifique imprimeLista para que ela gere uma sada neste formato.

17.4 Listas e Recorrncia

natural expressar muitas operaes de listas utilizando mtodos recorrentes. Por exemplo, o seguinte um algoritmo recorrente para imprimir uma lista de trs para frente. 1. Separe a lista em dois pedaos: o primeiro n (chamado a cabea); e o resto (chamado o rabo). 2. Imprima o rabo de trs para frente. 3. Imprima a cabea. Logicamente, o Passo 2, a chamada recorrente, assume que ns temos um modo de imprimir a lista de trs para frente. Mas se ns assumimos que a chamada recorrente funciona -- o passo de f -- ento podemos nos convencer de que o algoritmo funciona. Tudo o que precisamos so um caso base e um modo de provar que para qualquer lista, ns iremos, ao final, chegar no caso base. Dada a definio recorrente de uma lista, um caso base natural a lista vazia, representada por None:
def imprimeDeTrasParaFrente(lista): if lista == None : return cabeca = lista rabo = lista.proximo imprimeDeTrasParaFrente(rabo) print cabeca,

A primeira linha trata o caso base fazendo nada. As prximas duas linhas dividem a lista em cabeca e rabo. As duas ltimas linhas imprimem a lista. A vrgula no final da ltima linha impede o Python de imprimir uma nova linha aps cada n. Ns invocamos este mtodo como invocamos o imprimeLista:
>>> imprimeDeTrasParaFrente(no1) 321

O resultado a lista de trs para frente. Voc pode se perguntar por qu imprimeLista e imprimeDeTrasParaFrente so funes e no mtodos da classe No. A razo que ns queremos usar None

para representa a lista vazia e no legal invocar um mtodo sobre None. Esta limitao torna complicado escrever cdigo de manipulao de lista em estilo orientado a objeto limpo. Podemos provar que imprimeDeTrasParaFrente sempre termina? Em outras palavras, ir ela sempre atingir o caso base? De fato, a resposta no. Algumas listas faro este mtodo falhar.

17.5 Listas Infinitas

No h nada que impea um n de referenciar de volta um n anterior na lista, incluindo ele mesmo. Por exemplo, esta figura mostra uma lista com dois ns, um dos quais refere-se a si mesmo:

Se ns invocarmos imprimeLista nesta lista, ele ficar em lao para sempre. Se ns invocarmos imprimeDeTrasParaFrente, ele recorrer infinitamente. Este tipo de comportamento torna as listas infinitas difceis de se lidar. A despeito disto, elas ocasionalmente so teis. Por exemplo, podemos representar um nmero como uma lista de dgitos e usar uma lista infinita para representar uma frao repetente. Mesmo assim, problemtico que no possamos provar que imprimeLista e imprimeDeTrasParaFrente terminem. O melhor que podemos fazer a afirmao hipottica, "Se a lista no contm laos, ento este mtodo terminar." Este tipo de hiptese chamado uma pr-condio. Ele impe uma limitao sobre um dos parmetros e descreve o comportamento do mtodo se a limitao satisfeita. Voc ver mais exemplos em breve.

17.6 O Teorema da Ambigidade Fundamental

Uma parte de imprimeDeTrasParaFrente pode ter gerado surpresa:


cabeca = lista

rabo = lista.proximo

Aps a primeira atribuio, cabeca e lista tm o mesmo tipo e o mesmo valor. Ento por que ns criamos uma nova varivel? A razo que as duas variveis tm diferentes papis. Quando pensamos em cabeca, pensamos como uma referncia a um nico n, e quando pensamos em lista o fazemos como uma referncia ao primeiro n da lista. Estes "papis" no so parte do programa; eles esto na mente do programador. Em geral no podemos dizer olhando para o programa qual o papel que uma varivel tem. Esta ambigidade pode ser til, mas tambm pode tornar os programas difceis de serem lidos. Usamos freqentemente nomes de variveis como no e lista para documentar como pretendemos usar uma varivel e algumas vezes criamos variveis adicionais para remover a ambigidade. Poderamos ter escrito imprimeDeTrasParaFrente sem cabeca e rabo, que a tornaria mais concisa mas possivelmente menos clara:
def imprimeDeTrasParaFrente(lista): if lista == None : return imprimeDeTrasParaFrente(lista.proximo) print lista,

Olhando para as duas chamadas de funo, temos que lembrar que imprimeDeTrasParaFrente trata seu argumento como uma coleo e print trata seu argumento como um objeto nico. O teorema da ambigidade fundamental descreve a ambigidade que inerente referncia a um n: Uma varivel que refere a um n pode tratar o n como um objeto nico ou como o primeiro em uma lista de ns.

17.7 Modificando Listas

Existem duas maneiras de se modificar uma lista ligada. Obviamente, podemos modificar a carga dos ns, mas as operaes mais interessantes so aquelas que adicionam, removem ou reordenam os ns. Como um exemplo, vamos escrever um mtodo que remove o segundo n na lista e retorna uma referncia ao n removido:
def removeSegundo(lista):

if lista == None : return primeiro = lista segundo = lista.proximo # faz o primeiro no referir ao terceiro primeiro.proximo = segundo.proximo # separa o segundo no do resto da lista segundo.proximo = None return segundo

Novamente, estamos usando variveis temporrias para tornar o cdigo mais fcil de ser lido. Aqui est como usar este mtodo:
>>> imprimeLista(no1) 123 >>> removido = removeSegundo(no1) >>> imprimeLista(removido) 2 >>> imprimeLista(no1) 13

Este diagrama de estado mostra o efeito da operao:

O que acontece se voc invocar este mtodo e passar uma lista com somente um elemento (um singleton)? O que acontece se voc passar a lista vazia como um argumento? Existe uma pr-condio para este mtodo? Se houver, corrija o mtodo para tratar uma violao da pr-condio de modo razovel.

17.8 Envoltrios e Ajudadores

Freqentemente til dividir uma operao de lista em dois mtodos. Por

exemplo, para imprimir uma lista de trs para frente no formato convencional de lista [3, 2, 1], podemos usar o mtodo imprimeDeTrasParaFrente para imprimir 3, 2, mas queremos um metodo separado para imprimir os braquetes e o primeiro n. Vamos cham-lo de imprimeDeTrasParaFrenteLegal:
def imprimeDeTrasParaFrenteLegal(lista): print "[", if lista != None : cabeca = lista rabo = lista.proximo imprimeDeTrasParaFrente(rabo) print cabeca, print "]",

Novamente, uma boa idia verificar mtodos como este para ver se eles funcionam com casos especiais como uma lista vazia ou um singleton. Quando usamos este mtodo em algum lugar no programa, invocamos imprimeDeTrasParaFrenteLegal diretamente, e ele invoca imprimeDeTrasParaFrente por ns. Neste sentido, imprimeDeTrasParaFrenteLegal atua como um envoltrio, e usa imprimeDeTrasParaFrente como um ajudador.

17.9 A Classe ListaLigada

Existem alguns problemas sutis com o modo que implementamos listas. Em um inverso de causa e efeito, proporemos uma implementao alternativa primeiro e ento explicaremos qual problema ela resolve. Primeiro, criaremos uma nova classe chamada ListaLigada. Seus atributos so um inteiro que contm o comprimento da lista e uma referncia para o primeiro n. Objetos do tipo ListaLigada servem como cabos (handles) para se manipular listas de objetos No:
class ListaLigada: def __init__(self): self.comprimento = 0 self.cabeca = None

Uma coisa legal acerca da classe ListaLigada que ela prov um lugar natural para se colocar funes envoltrias como imprimeDeTrasParaFrenteLegal, que podemos transformar em um mtodo da classe ListaLigada:
class ListaLigada: ... def imprimeDeTrasParaFrente(self): print "[", if self.cabeca != None : self.cabeca.imprimeDeTrasParaFrente() print "]",

class No: ... def imprimeDeTrasParaFrente(self): if self.proximo != None: rabo = self.proximo rabo.imprimeDeTrasParaFrente() print self.carga,

Apenas para tornar as coisas confusas, mudamos o nome de imprimeDeTrasParaFrenteLegal. Agora existem dois mtodos chamados imprimeDeTrasParaFrente: um na classe No (o ajudador); e um na classe ListaLigada``(o envoltrio). Quano o envoltrio invoca ``self.cabeca.imprimeDeTrasParaFrente, ele est invocando o ajudador, porque self.cabeca um objeto No. Outro benefcio da classe ListaLigada que ela torna mais fcil adicionar e remover o primeiro elemento de uma lista. Por exemplo, adicionaPrimeiro um mtodo para ListaLigada; ele toma um item de carga como argumento e o coloca no incio da lista:
class ListaLigada: ... def adicionaPrimeiro(self, carga): no = No(carga)

no.proximo = self.cabeca self.cabeca = no self.comprimento = self.comprimento + 1

Como de costume, voc deve conferir cdigos como este para ver se eles tratam os casos especiais. Por exemplo, o que acontece se a lista est inicialmente vazia?

17.10 Invariantes

Algumas listas so "bem formadas"; outras no o so. Por exemplo, se uma lista contm um lao, ela far muitos de nossos mtodos falharem, de modo que podemos querer requerer que listas no contenham laos. Outro requerimento que o valor de comprimento no objeto ListaLigada seja igual ao nmero real de ns da lista. Requerimentos como estes so chamados de invariantes porque, idealmente, eles deveriam ser verdade para cada objeto o tempo todo. Especificar invariantes para objetos um prtica de programao til porque torna mais fcil provar a correo do cdigo, verificar a integridade das estruturas de dados e detectar erros. Uma coisa que algumas vezes confusa acerca de invariantes que existem momentos em que eles so violados. Por exemplo, no meio de adicionaPrimeiro, aps termos adicionado o n mas antes de termos incrementado comprimento, o invariante violado. Este tipo de violao aceitvel; de fato, freqentemente impossvel modificar um objeto sem violar um invariante por, no mnimo, um pequeno instante. Normalmente, requeremos que cada mtodo que viola um invariante deve restaurar este invariante. Se h qualquer aumento significativo de cdigo no qual o invariante violado, importante tornar isto claro nos comentrios, de modo que nenhuma operao seja feita que dependa daquele invariante.

17.11 Glossrio

referncia embutida (embedded reference) Uma referncia armazenada/associada em/a um atributo de um objeto.

lista ligada (linked list) Uma estrutura de dados que implementa uma coleo usando uma sequncia de ns ligados. n ou nodo (node) Um elemento de uma lista, usualmente implementado como um objeto que contm uma referncia para outro objeto do mesmo tipo. carga (cargo) Um item de dado contido em um n. ligao (link) Uma referncia embutida usada para ligar/conectar um objeto a outro. pr-condio (precondition) Uma assero que precisa/deve ser verdadeira para que um mtodo trabalhe corretamante. teorema da ambigidade fundamental (fundamental ambiguity theorem) Uma referncia para um n de uma lista pode ser tratada como um objeto nico ou como o primeiro em uma lista de ns. singleton (singleton) Uma lista ligada com somente um n. envoltrio (wrapper) Um mtodo que atua como um intermedirio (middleman) entre um chamador e um mtodo ajudador (helper), freqentemente tornando a invocao do mtodo mais fcil ou menos propensa a erros. ajudador (helper) Um mtodo que no invocado diretamente pelo chamador (caller) mas usado por outro mtodo para realizar parte de uma operao. invariante (invariant) Uma assero que deveria ser verdadeira sempre para um objeto (exceto talvez enquanto o objeto estiver sendo modificado).

Captulo 17: Listas encadeadas


Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos o 3.4 Funes matemticas o 3.5 Composio o 3.6 Adicionando novas funes o 3.7 Definies e uso o 3.8 Fluxo de execuo o 3.9 Parmetros e argumentos o 3.10 Variveis e parmetros so locais o 3.11 Diagramas da pilha o 3.12 Funes com resultados o 3.13 Glossrio Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa

4.6 Condicionais encadeados 4.7 Condicionais aninhados 4.8 A instruo return 4.9 Recursividade 4.10 Diagramas de pilha para funes recursivas 4.11 Recursividade infinita 4.12 Entrada pelo teclado 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas
o o o o o o o o

Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores

17.1 Referncias Embutidas

Ns temos visto exemplos de atributos que referenciam outros objetos, que so chamados referncias embutidas (veja a Seo 12.8). Uma estrutura de dados comum, a lista ligada, tira vantagem desta caracterstica. Listas ligadas so constitudas de ns (nodos), onde cada n contm uma referncia para o prximo n na lista. Alm disto, cada n contm uma unidade de dados chamada a carga. Uma lista ligada considerada uma estrutura de dados recorrente porque ela tem uma definio recorrente. Uma lista ligada Uma lista vazia, representada por None, ou Um n que contm um objeto carga e uma referncia para uma lista ligada. Estruturas de dados recorrentes so adequadas para mtodos recorrentes.

17.2 A classe No (Node)

Como usual quando se escreve uma nova classe, ns comearemos com os mtodos de inicializao e __str__ de modo que podemos testar o mecanismo bsico de se criar e mostrar o novo tipo:
class No: def __init__(self, carga=None, proximo=None): self.carga = carga self.proximo = proximo

def __str__(self): return str(self.carga)

Como de costume, os parmetros para o mtodo de inicializao so opcionais. Por omisso (default), ambos, a carga e a ligao, proximo, so definidas como None. A representao string de um n simplesmente a representao string da carga. Como qualquer valor pode ser passado para a funo str, ns podemos armazenar qualquer valor em uma lista. Para testar a implementao at agora, ns criamos um No e o imprimimos:
>>> no = No("teste") >>> print no teste

Para ficar interessante, ns precisamos uma lista com mais do que um n:


>>> no1 = No(1) >>> no2 = No(2) >>> no3 = No(3)

Este cdigo cria trs ns, mas ns ainda no temos uma lista ainda porque os ns no esto ligados. O diagrama de estado parecido com este:

Para ligar os ns, temos que fazer o primeiro n da lista referir ao segundo e o segundo n referir ao terceiro:
>>> no1.proximo = no2 >>> no2.proximo = no3

A referncia do terceiro n None, que indica que ele o final da lista. Agora o diagrama de estado se parece com:

Agora voc sabe como criar ns e lig-los em uma lista. O que pode estar menos claro neste ponto por qu.

17.3 Listas como Colees

Listas so teis porque elas provm um modo de montar mltiplos objetos em uma nica entidade, algumas vezes chamada uma coleo. No exemplo, o primeiro n da lista serve como uma referncia para toda a lista. Para passar uma lista como um parmetro, voc apenas tem que passar uma referncia ao primeiro n. Por exemplo, a funo imprimeLista toma um nico n como um argumento. Iniciando com o cabea da lista, ela imprime cada n at que chegue ao fim:
def imprimeLista(no): while no: print no, no = no.proximo print

Para chamar este mtodo, ns passamos uma referncia ao primeiro no:


>>> imprimeLista(no1)

123

Dentro de imprimeLista ns temos uma referncia para o primeiro n da lista, mas no h variveis que refiram aos outros ns. Ns temos que usar o valor proximo de cada n para alcanar o prximo n. Para percorrer uma lista ligada, comum usar uma varivel lao como no para referir a cada um dos ns sucessivamente. Este diagrama mostra o valor de lista e os valores que no assume:

Por conveno, listas so freqentemente impressas em braquetes com vrgulas entre os elementos, como em [1, 2, 3]. Como um exerccio, modifique imprimeLista para que ela gere uma sada neste formato.

17.4 Listas e Recorrncia

natural expressar muitas operaes de listas utilizando mtodos recorrentes. Por exemplo, o seguinte um algoritmo recorrente para imprimir uma lista de trs para frente. 1. Separe a lista em dois pedaos: o primeiro n (chamado a cabea); e o resto (chamado o rabo). 2. Imprima o rabo de trs para frente. 3. Imprima a cabea. Logicamente, o Passo 2, a chamada recorrente, assume que ns temos um modo de imprimir a lista de trs para frente. Mas se ns assumimos que a chamada recorrente funciona -- o passo de f -- ento podemos nos convencer de que o algoritmo funciona. Tudo o que precisamos so um caso base e um modo de provar que para qualquer lista, ns iremos, ao final, chegar no caso base. Dada a definio recorrente de uma lista, um caso base natural a lista vazia, representada por None:
def imprimeDeTrasParaFrente(lista):

if lista == None : return cabeca = lista rabo = lista.proximo imprimeDeTrasParaFrente(rabo) print cabeca,

A primeira linha trata o caso base fazendo nada. As prximas duas linhas dividem a lista em cabeca e rabo. As duas ltimas linhas imprimem a lista. A vrgula no final da ltima linha impede o Python de imprimir uma nova linha aps cada n. Ns invocamos este mtodo como invocamos o imprimeLista:
>>> imprimeDeTrasParaFrente(no1) 321

O resultado a lista de trs para frente. Voc pode se perguntar por qu imprimeLista e imprimeDeTrasParaFrente so funes e no mtodos da classe No. A razo que ns queremos usar None para representa a lista vazia e no legal invocar um mtodo sobre None. Esta limitao torna complicado escrever cdigo de manipulao de lista em estilo orientado a objeto limpo. Podemos provar que imprimeDeTrasParaFrente sempre termina? Em outras palavras, ir ela sempre atingir o caso base? De fato, a resposta no. Algumas listas faro este mtodo falhar.

17.5 Listas Infinitas

No h nada que impea um n de referenciar de volta um n anterior na lista, incluindo ele mesmo. Por exemplo, esta figura mostra uma lista com dois ns, um dos quais refere-se a si mesmo:

Se ns invocarmos imprimeLista nesta lista, ele ficar em lao para sempre. Se ns invocarmos imprimeDeTrasParaFrente, ele recorrer infinitamente.

Este tipo de comportamento torna as listas infinitas difceis de se lidar. A despeito disto, elas ocasionalmente so teis. Por exemplo, podemos representar um nmero como uma lista de dgitos e usar uma lista infinita para representar uma frao repetente. Mesmo assim, problemtico que no possamos provar que imprimeLista e imprimeDeTrasParaFrente terminem. O melhor que podemos fazer a afirmao hipottica, "Se a lista no contm laos, ento este mtodo terminar." Este tipo de hiptese chamado uma pr-condio. Ele impe uma limitao sobre um dos parmetros e descreve o comportamento do mtodo se a limitao satisfeita. Voc ver mais exemplos em breve.

17.6 O Teorema da Ambigidade Fundamental

Uma parte de imprimeDeTrasParaFrente pode ter gerado surpresa:


cabeca = lista rabo = lista.proximo

Aps a primeira atribuio, cabeca e lista tm o mesmo tipo e o mesmo valor. Ento por que ns criamos uma nova varivel? A razo que as duas variveis tm diferentes papis. Quando pensamos em cabeca, pensamos como uma referncia a um nico n, e quando pensamos em lista o fazemos como uma referncia ao primeiro n da lista. Estes "papis" no so parte do programa; eles esto na mente do programador. Em geral no podemos dizer olhando para o programa qual o papel que uma varivel tem. Esta ambigidade pode ser til, mas tambm pode tornar os programas difceis de serem lidos. Usamos freqentemente nomes de variveis como no e lista para documentar como pretendemos usar uma varivel e algumas vezes criamos variveis adicionais para remover a ambigidade. Poderamos ter escrito imprimeDeTrasParaFrente sem cabeca e rabo, que a tornaria mais concisa mas possivelmente menos clara:
def imprimeDeTrasParaFrente(lista): if lista == None : return imprimeDeTrasParaFrente(lista.proximo) print lista,

Olhando para as duas chamadas de funo, temos que lembrar que imprimeDeTrasParaFrente trata seu argumento como uma coleo e print trata seu argumento como um objeto nico. O teorema da ambigidade fundamental descreve a ambigidade que inerente referncia a um n: Uma varivel que refere a um n pode tratar o n como um objeto nico ou como o primeiro em uma lista de ns.

17.7 Modificando Listas

Existem duas maneiras de se modificar uma lista ligada. Obviamente, podemos modificar a carga dos ns, mas as operaes mais interessantes so aquelas que adicionam, removem ou reordenam os ns. Como um exemplo, vamos escrever um mtodo que remove o segundo n na lista e retorna uma referncia ao n removido:
def removeSegundo(lista): if lista == None : return primeiro = lista segundo = lista.proximo # faz o primeiro no referir ao terceiro primeiro.proximo = segundo.proximo # separa o segundo no do resto da lista segundo.proximo = None return segundo

Novamente, estamos usando variveis temporrias para tornar o cdigo mais fcil de ser lido. Aqui est como usar este mtodo:
>>> imprimeLista(no1) 123 >>> removido = removeSegundo(no1) >>> imprimeLista(removido) 2

>>> imprimeLista(no1) 13

Este diagrama de estado mostra o efeito da operao:

O que acontece se voc invocar este mtodo e passar uma lista com somente um elemento (um singleton)? O que acontece se voc passar a lista vazia como um argumento? Existe uma pr-condio para este mtodo? Se houver, corrija o mtodo para tratar uma violao da pr-condio de modo razovel.

17.8 Envoltrios e Ajudadores

Freqentemente til dividir uma operao de lista em dois mtodos. Por exemplo, para imprimir uma lista de trs para frente no formato convencional de lista [3, 2, 1], podemos usar o mtodo imprimeDeTrasParaFrente para imprimir 3, 2, mas queremos um metodo separado para imprimir os braquetes e o primeiro n. Vamos cham-lo de imprimeDeTrasParaFrenteLegal:
def imprimeDeTrasParaFrenteLegal(lista): print "[", if lista != None : cabeca = lista rabo = lista.proximo imprimeDeTrasParaFrente(rabo) print cabeca, print "]",

Novamente, uma boa idia verificar mtodos como este para ver se eles funcionam com casos especiais como uma lista vazia ou um singleton. Quando usamos este mtodo em algum lugar no programa, invocamos imprimeDeTrasParaFrenteLegal diretamente, e ele invoca imprimeDeTrasParaFrente por ns. Neste sentido, imprimeDeTrasParaFrenteLegal atua como um envoltrio, e usa

imprimeDeTrasParaFrente como um ajudador.

17.9 A Classe ListaLigada

Existem alguns problemas sutis com o modo que implementamos listas. Em um inverso de causa e efeito, proporemos uma implementao alternativa primeiro e ento explicaremos qual problema ela resolve. Primeiro, criaremos uma nova classe chamada ListaLigada. Seus atributos so um inteiro que contm o comprimento da lista e uma referncia para o primeiro n. Objetos do tipo ListaLigada servem como cabos (handles) para se manipular listas de objetos No:
class ListaLigada: def __init__(self): self.comprimento = 0 self.cabeca = None

Uma coisa legal acerca da classe ListaLigada que ela prov um lugar natural para se colocar funes envoltrias como imprimeDeTrasParaFrenteLegal, que podemos transformar em um mtodo da classe ListaLigada:
class ListaLigada: ... def imprimeDeTrasParaFrente(self): print "[", if self.cabeca != None : self.cabeca.imprimeDeTrasParaFrente() print "]",

class No: ... def imprimeDeTrasParaFrente(self): if self.proximo != None:

rabo = self.proximo rabo.imprimeDeTrasParaFrente() print self.carga,

Apenas para tornar as coisas confusas, mudamos o nome de imprimeDeTrasParaFrenteLegal. Agora existem dois mtodos chamados imprimeDeTrasParaFrente: um na classe No (o ajudador); e um na classe ListaLigada``(o envoltrio). Quano o envoltrio invoca ``self.cabeca.imprimeDeTrasParaFrente, ele est invocando o ajudador, porque self.cabeca um objeto No. Outro benefcio da classe ListaLigada que ela torna mais fcil adicionar e remover o primeiro elemento de uma lista. Por exemplo, adicionaPrimeiro um mtodo para ListaLigada; ele toma um item de carga como argumento e o coloca no incio da lista:
class ListaLigada: ... def adicionaPrimeiro(self, carga): no = No(carga) no.proximo = self.cabeca self.cabeca = no self.comprimento = self.comprimento + 1

Como de costume, voc deve conferir cdigos como este para ver se eles tratam os casos especiais. Por exemplo, o que acontece se a lista est inicialmente vazia?

17.10 Invariantes

Algumas listas so "bem formadas"; outras no o so. Por exemplo, se uma lista contm um lao, ela far muitos de nossos mtodos falharem, de modo que podemos querer requerer que listas no contenham laos. Outro requerimento que o valor de comprimento no objeto ListaLigada seja igual ao nmero real de ns da lista. Requerimentos como estes so chamados de invariantes porque, idealmente, eles deveriam ser verdade para cada objeto o tempo todo. Especificar invariantes para objetos um prtica de programao til porque torna mais fcil provar a correo do cdigo, verificar a integridade das estruturas de

dados e detectar erros. Uma coisa que algumas vezes confusa acerca de invariantes que existem momentos em que eles so violados. Por exemplo, no meio de adicionaPrimeiro, aps termos adicionado o n mas antes de termos incrementado comprimento, o invariante violado. Este tipo de violao aceitvel; de fato, freqentemente impossvel modificar um objeto sem violar um invariante por, no mnimo, um pequeno instante. Normalmente, requeremos que cada mtodo que viola um invariante deve restaurar este invariante. Se h qualquer aumento significativo de cdigo no qual o invariante violado, importante tornar isto claro nos comentrios, de modo que nenhuma operao seja feita que dependa daquele invariante.

17.11 Glossrio

referncia embutida (embedded reference) Uma referncia armazenada/associada em/a um atributo de um objeto. lista ligada (linked list) Uma estrutura de dados que implementa uma coleo usando uma sequncia de ns ligados. n ou nodo (node) Um elemento de uma lista, usualmente implementado como um objeto que contm uma referncia para outro objeto do mesmo tipo. carga (cargo) Um item de dado contido em um n. ligao (link) Uma referncia embutida usada para ligar/conectar um objeto a outro. pr-condio (precondition) Uma assero que precisa/deve ser verdadeira para que um mtodo trabalhe corretamante. teorema da ambigidade fundamental (fundamental ambiguity theorem)

Uma referncia para um n de uma lista pode ser tratada como um objeto nico ou como o primeiro em uma lista de ns. singleton (singleton) Uma lista ligada com somente um n. envoltrio (wrapper) Um mtodo que atua como um intermedirio (middleman) entre um chamador e um mtodo ajudador (helper), freqentemente tornando a invocao do mtodo mais fcil ou menos propensa a erros. ajudador (helper) Um mtodo que no invocado diretamente pelo chamador (caller) mas usado por outro mtodo para realizar parte de uma operao. invariante (invariant) Uma assero que deveria ser verdadeira sempre para um objeto (exceto talvez enquanto o objeto estiver sendo modificado). System Message: WARNING/2 (<string>, line 19309) Block quote ends without a blank line; unexpected unindent.

Captulo 18: Pilhas


Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses

2.6 Operadores e operandos 2.7 Ordem dos operadores 2.8 Operaes com strings 2.9 Composio 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos o 3.4 Funes matemticas o 3.5 Composio o 3.6 Adicionando novas funes o 3.7 Definies e uso o 3.8 Fluxo de execuo o 3.9 Parmetros e argumentos o 3.10 Variveis e parmetros so locais o 3.11 Diagramas da pilha o 3.12 Funes com resultados o 3.13 Glossrio Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno
o o o o o

5.2 Desenvolvimento de programas 5.3 Composio 5.4 Funes booleanas 5.5 Mais recursividade 5.6 Voto de confiana (Leap of faith) 5.7 Mais um exemplo 5.8 Checagem de tipos 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores
o o o o o o o o

18.1 Tipos abstratos de dados

Os tipos de dados que voc viu at agora so todos concretos, no sentido que ns especificamos completamente como eles so implementados. Por exemplo, a classe Card(XXX ver como foi traduzido) representa uma carta utilizando dois inteiros. Como discutimos no momento, esta no a nica maneira de representar uma carta; existem muitas implementaes alternativas. Um tipo abstrato de dado, ou TAD, especifica um conjunto de operaes (ou mtodos) e a semntica das operaes (o que elas fazem), mas no especifica a implementao das operaes. Isto o que o faz abstrato. Por que isto til? Simplifica a tarefa dde especificar um algoritmo se voc pode XXXdenotar(denote) as operaes que voc precisa sem ter que pensar, ao mesmo tempo, como as operaes so executadas. Uma vez que existem geralmente muitas maneiras de implementar um TAD, pode ser til escrever um algritmo que pode ser usado com qualquer das possveis implementaes. TADs bastante conhecidos, como o TAD Pilha deste captulo, j esto implementados em bibliotecas padro, ento eles podem ser escritos uma vez e usado por muitos programadores. As operaes em TADs provm uma linguagem de alto nvel comum para especificar e falar sobre algoritmos. Quando falamos sobre TADs, geralmente distinguimos o cdigo que usa o TAD, chamado cliente, do cdigo que implementa o TAD, chamado cdigo fornecedor. 18.2 O TAD Pilha

Neste captulo, iremos olhar um TAD comum, a pilha. Uma pilha uma coleo, ou seja, uma estrutura de dados que contei mltiplos elementos. Outras colees que vimos incluem dicionrios e listas. Um TAd definido pelo conjunto de operaes que podem ser executadas nele, que chamado interface. A interface para uma pilha consiste nestas operaes: __init__ : Inicializa uma nova pilha vazia. push : Adiciona um novo item na pilha pop : Remove um tem da pilha e o retorna, O tem que retornadao sempre o ltimo adicionado.

isEmpty : Verifica se a pilha est vazia. Uma s vezes chamada uma estrutura de dados "last in, first out" ou LIFO, porque o ltimo tem adicionad o primeiro a ser removido. 18.3 Implementando pilhas com listas de Python

As operaes de lista que Python oferecem so similares s operaes que definem uma pilha. A interface no exatamente o que se supe ser, mas podemos escrever um cdigo para traduzir do TAD Pilha para as operaes nativas. Este cdigo chamado uma implementao do TAD Pilha. Geralmente, uma implementaa um conjunto de mtodos que satisfazem os requisitos sintticos e semnticos de uma interface. Aqui est uma implementao do TAD Pilha que usa uma lista do Python:
class Stack : def __init__(self) : self.items = []

def push(self, item) : self.items.apend(item)

def pop(self) : return self.items.pop()

def isEmpty(self) : return (self.items == [])

Um objeto Stack contm um atributo chamado items que uma lista de tens na pilha. O mtodo de inicializao define items como uma lista vazia. Para adicionar um novo tem na pilha, push o coloca em items. Para remover um tem da pilha, pop usa o mtodo de lista homnimo para remover e retornar um ltimo tem da lista. Finalmente, para verificar se a pilha est vazia, isEmpty comprara items a uma lista vazia.

Uma implementao como esta, na qual os mtodos consistem de simples invocaes de mtodos existentes, chamado revestimento. Na vida real, revestimento uma fina camada de madeira de boa qualidade usado em XXX*furniture-making* para esconder madeira de menor qualidade embaixo. Cientistas da Computao usam esta metfora para descrever um pequeno trecho de cdigo que esconde os detalhes de uma implementao e fornece uma interface mais simples, ou mais padronizada. 18.4 Empilhando e desempilhando

Uma pilha uma estrutura de dados genrica, o que significa que podemos adicionar qualquer tipo de tem a ela. O exemplo a seguir empilha dois inteiros e uma XXXstring na pilha:
>>> s = Stack() >>> s.push(54) >>> s.push(45) >>> s.push("+")

Podemos usar isEmpty e pop para remover e imprimir todos os tens da pilha: while not s.isEmpty() : priint s.pop() A sada + 45 54. Em outras palavras, usamos a pilha para imprimir os tens ao contrrio! Sabidamente, este no o formato padro de imprimir uma lista, mas, usando uma pilha, foi notavelmente fcil de fazer. Voc deve comparar este trecho de cdigo com a implementao de printBackward na seo 17.4. Existe um paralelo natura entre a verso recursiva de printBackward e o algoritmo de pilha aqui. A diferen que printBackward usa a pilha de execuo para XXXmanter a trilha(keep track) dos ns enquanto percorre a lista, e ento imprime-a no retorno da recurso. o algoritmo de pilha faz a mesma coisa, exceto que usa o objeto Stack ao invs da pilha de execuo. 18.5 Usando uma pilha para avaliar expresses ps-fixas

Em muitas linguagens de programao, expresses matemticas so executadas com o poerador entre os roid operandos, como em 1 + 2. Este formato chamado notao infixa. Uma alternativa usada por algumas calculadoras chamada notao ps-fixa. Em notao ps-fixa, o operador segue os operandos, como em 1 2 +. A razo pela qual a notao ps-fixa til algumas vezes que existe uma

maneira natural de avaliar uma expresso ps-fixa usando uma pilha: comeando no incio da expresso, peque um termo (operador ou operando) de cada vez. Se o termo um operando, empilhe-o Se o termo um operador, desempilhe dois operandos, execute a operao neles, e empilhe o resultado. Quando chegar ao fim da expresso, deve existir exatamente um operando sobrando na pilha. Este operando o resultado. Como um exerccio, aplique este algoritmo expresso 1 2 + 3 * . Este exemplo demonstra uma das vantagens da notao ps-fixa - no necessrio usar parnteses para controlar a ordem das operaes. Para ter o mesmo resultado em notao infixa, deveramos escrever (1 + 2) * 3. Como um exerccio, escreva a expresso ps-fixa que equivalente a 1 + 2 * 3. 18.6 Anlise sinttica

Para implementar o algoritmo anterior, necessitamos estar prontos para percorrer uma string e quebr-la em operandos e operadores. Este process um exemplo de XXXparsing, e o resultado - os pedaos da string - so chamados XXXtokens. Voc deve lembrar estas palavras do captulo 1. Python fornece um mtodo split nos mdulos string e re (expresses regulares). A funo string.split separa uma string numa lista usando um nico caracter como delimitador. Por exemplo:
>>> import string >>> string.split ("Now is the time", " ")

['Now', 'is', 'the', 'time'] Neste caso, o delimitador o caracter de espao, ento a string dividida a cada espao. A funo re.split mais poderosa, permitindo-nos fornecer uma expreso regular ao invs de um delimitador. Uma expresso regular uma maneira de especificar um conjunto de strings. Por exemplo, [A-z] o conjunto de todas as letras e [0-9] o conjunto de todos os dgitos. O operador ^nega um conunto, ento [^0-9] o conjunto de tudo o que no nmero, que exatamente o que queremos para dividir expresses ps-fixas.
>>> import re >>> re.split ("[^0-9]", "123+456*/")

['123', '+', '456', '*', '', '/', ' ']

Note que a ordem dos argumentos diferente de string.split, o delimitador vem antes da string. A lista resultante inclui os operandos 123 e 456, e os operadores * e /. Tambm inclui duas strings vazias que so inseridas depois dos operadores. 18.7 Avaliando em ps-fixo.

Para avaliar uma expresso ps-fixa, usaremos o parser da seo anterior e o algoritmo da seo anterior a ela. Para manter as coisas simples, comearemos com um avaliador que implementa somente os operadores + e .
def evalPostfix (expr) : import re tokenList = re.split ("([^0-9])", expr) stack = Stack() for token in tokenList if token == '' or token = ' ' : continue if token == '+' : sum = stack.pop() + stack.pop() stack.push(sum) if token == '*' : product = stack.pop() * stack.pop() stack.push(product) else: stack.push(int(token)) return stack.pop()

A primeira condio cuida de espaos e strings vazias. As duas prximas condies manipulam os operadores. Ns assumimos, agora que qualquer coisa um operador. claro, seria melhor chegar por entrada errnea e enviar uma mensagem de erro, mas faremos isto depois. Vamos test-lo avaliando a forma ps-fixa de (56 + 47) * 2
>>> print evalPostfix("56 47 + 2 *")

206 XXXthat's close enough 18.8 Clientes de fornecedores. Um dos objetivos de um TAD separar os interesses do fornecedor, quem escreve o cdigo que implementa o TAD, e o cliente, que usa o TAD. O fornecedor tem que se preocupar apenas se a implementao est correta - de acordo com a especificao do TAD - e no como ele ser usado. Inversamente, o cliente assume que a implementao do TAD est correta e no se preocupa com os detalhes. Quando voc est usando um tipo nativo do Python, tem o luxo de pensar exclusivamente como um cliente. claro, quanto voc implementa um TAD, voc tambm tem que escrever cdigo cliente para test-lo. Neste caso, voc faz os dois papis, o que pode ser confuso. Voc deve fazer algum esfor para manter a trilha do papel que est fazendo a cada momento.

18.9 Glossrio

tipo abstrato de dados (TAD) (abstract data type(ADT)): Um tipo de dado(geralmente uma coleo de objetos) que definidopor um conjunto de operaes, que podem ser implementadas de vrias maneiras. interface (interface): o conjunto de operaes que definem um TDA. implementao (implementation): Cdigo que satisfaz(preenche?) os requisitos sintticos e semnticos de uma interface. cliente (client): Um programa (ou o programador que o escreveu) que faz utilizao de um TDA. fornecedor (provider): Cdigo (ou o programador que o escreveu) que implementa um TDA.

revestimento (veneer): Definio de classe que implementa um TDA com definies de mtodos que so chamadas a outros mtodos, s vezes com pequenas modificaes. A lmina faz um trabalho insignificante, mas melhora ou padroniza a interface dada ao cliente. estrutura de dados genrica (generic data structure): Tipo de estrutura de dados que contem data de um tipo qualquer(tipo genrico). infixa (infix): Notao matemtica em que os operadores se situam entre os operandos. ps-fixa (postfix): Notao matemtica em que os operadores se situam aps os operandos. XXX parse (parse): Ler um conjunto de caracteres(string de caracteres) ou tokens(smbolos atmicos) e analisar sua estrutura gramatical. XXX token (token): Conjunto de caracteres que so tratados como uma unidade atmica para fins de anlise gramatical, como as palavras na linguagem natural. delimitador (delimiter): Um caracter que utilizado para separar os smbolos atmicos(tokens), como a pontuao na linguagem natural.

Captulo 18: Pilhas


System Message: INFO/1 (<string>, line 19750); backlink Duplicate implicit target name: "captulo 18: pilhas". Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas

2.4 Comandos 2.5 Avaliando expresses 2.6 Operadores e operandos 2.7 Ordem dos operadores 2.8 Operaes com strings 2.9 Composio 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos o 3.4 Funes matemticas o 3.5 Composio o 3.6 Adicionando novas funes o 3.7 Definies e uso o 3.8 Fluxo de execuo o 3.9 Parmetros e argumentos o 3.10 Variveis e parmetros so locais o 3.11 Diagramas da pilha o 3.12 Funes com resultados o 3.13 Glossrio Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas
o o o o o o o

4.3 Operadores lgicos 4.4 Execuo condicional 4.5 Execuo alternativa 4.6 Condicionais encadeados 4.7 Condicionais aninhados 4.8 A instruo return 4.9 Recursividade 4.10 Diagramas de pilha para funes recursivas 4.11 Recursividade infinita 4.12 Entrada pelo teclado 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos
o o o o o o o o o o o

Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores 18.1 Tipos abstratos de dados

Os tipos de dados que voc viu at agora so todos concretos, no sentido que ns especificamos completamente como eles so implementados. Por exemplo, a classe Card(XXX ver como foi traduzido) representa uma carta utilizando dois inteiros. Como discutimos no momento, esta no a nica maneira de representar uma carta; existem muitas implementaes alternativas. Um tipo abstrato de dado, ou TAD, especifica um conjunto de operaes (ou mtodos) e a semntica das operaes (o que elas fazem), mas no especifica a implementao das operaes. Isto o que o faz abstrato. Por que isto til? Simplifica a tarefa dde especificar um algoritmo se voc pode XXXdenotar(denote) as operaes que voc precisa sem ter que pensar, ao mesmo tempo, como as operaes so executadas. Uma vez que existem geralmente muitas maneiras de implementar um TAD, pode ser til escrever um algritmo que pode ser usado com qualquer das possveis implementaes. TADs bastante conhecidos, como o TAD Pilha deste captulo, j esto implementados em bibliotecas padro, ento eles podem ser escritos uma vez e usado por muitos programadores. As operaes em TADs provm uma linguagem de alto nvel comum para especificar e falar sobre algoritmos. Quando falamos sobre TADs, geralmente distinguimos o cdigo que usa o TAD, chamado cliente, do cdigo que implementa o TAD, chamado cdigo fornecedor. 18.2 O TAD Pilha

Neste captulo, iremos olhar um TAD comum, a pilha. Uma pilha uma coleo, ou seja, uma estrutura de dados que contei mltiplos elementos.

Outras colees que vimos incluem dicionrios e listas. Um TAd definido pelo conjunto de operaes que podem ser executadas nele, que chamado interface. A interface para uma pilha consiste nestas operaes: __init__ : Inicializa uma nova pilha vazia. push : Adiciona um novo item na pilha pop : Remove um tem da pilha e o retorna, O tem que retornadao sempre o ltimo adicionado. isEmpty : Verifica se a pilha est vazia. Uma s vezes chamada uma estrutura de dados "last in, first out" ou LIFO, porque o ltimo tem adicionad o primeiro a ser removido. 18.3 Implementando pilhas com listas de Python

As operaes de lista que Python oferecem so similares s operaes que definem uma pilha. A interface no exatamente o que se supe ser, mas podemos escrever um cdigo para traduzir do TAD Pilha para as operaes nativas. Este cdigo chamado uma implementao do TAD Pilha. Geralmente, uma implementaa um conjunto de mtodos que satisfazem os requisitos sintticos e semnticos de uma interface. Aqui est uma implementao do TAD Pilha que usa uma lista do Python:
class Stack : def __init__(self) : self.items = []

def push(self, item) : self.items.apend(item)

def pop(self) : return self.items.pop()

def isEmpty(self) : return (self.items == [])

Um objeto Stack contm um atributo chamado items que uma lista de tens na pilha. O mtodo de inicializao define items como uma lista vazia. Para adicionar um novo tem na pilha, push o coloca em items. Para remover um tem da pilha, pop usa o mtodo de lista homnimo para remover e retornar um ltimo tem da lista. Finalmente, para verificar se a pilha est vazia, isEmpty comprara items a uma lista vazia. Uma implementao como esta, na qual os mtodos consistem de simples invocaes de mtodos existentes, chamado revestimento. Na vida real, revestimento uma fina camada de madeira de boa qualidade usado em XXX*furniture-making* para esconder madeira de menor qualidade embaixo. Cientistas da Computao usam esta metfora para descrever um pequeno trecho de cdigo que esconde os detalhes de uma implementao e fornece uma interface mais simples, ou mais padronizada. 18.4 Empilhando e desempilhando

Uma pilha uma estrutura de dados genrica, o que significa que podemos adicionar qualquer tipo de tem a ela. O exemplo a seguir empilha dois inteiros e uma XXXstring na pilha:
>>> s = Stack() >>> s.push(54) >>> s.push(45) >>> s.push("+")

Podemos usar isEmpty e pop para remover e imprimir todos os tens da pilha: while not s.isEmpty() : priint s.pop() A sada + 45 54. Em outras palavras, usamos a pilha para imprimir os tens ao contrrio! Sabidamente, este no o formato padro de imprimir uma lista, mas, usando uma pilha, foi notavelmente fcil de fazer. Voc deve comparar este trecho de cdigo com a implementao de printBackward na seo 17.4. Existe um paralelo natura entre a verso recursiva de printBackward e o algoritmo de pilha aqui. A diferen que printBackward usa a pilha de execuo para XXXmanter a trilha(keep track) dos ns enquanto percorre a lista, e ento imprime-a no retorno da recurso. o algoritmo de pilha faz a mesma coisa, exceto que usa o objeto Stack ao invs

da pilha de execuo. 18.5 Usando uma pilha para avaliar expresses ps-fixas

Em muitas linguagens de programao, expresses matemticas so executadas com o poerador entre os roid operandos, como em 1 + 2. Este formato chamado notao infixa. Uma alternativa usada por algumas calculadoras chamada notao ps-fixa. Em notao ps-fixa, o operador segue os operandos, como em 1 2 +. A razo pela qual a notao ps-fixa til algumas vezes que existe uma maneira natural de avaliar uma expresso ps-fixa usando uma pilha: comeando no incio da expresso, peque um termo (operador ou operando) de cada vez. Se o termo um operando, empilhe-o Se o termo um operador, desempilhe dois operandos, execute a operao neles, e empilhe o resultado. Quando chegar ao fim da expresso, deve existir exatamente um operando sobrando na pilha. Este operando o resultado. Como um exerccio, aplique este algoritmo expresso 1 2 + 3 * . Este exemplo demonstra uma das vantagens da notao ps-fixa - no necessrio usar parnteses para controlar a ordem das operaes. Para ter o mesmo resultado em notao infixa, deveramos escrever (1 + 2) * 3. Como um exerccio, escreva a expresso ps-fixa que equivalente a 1 + 2 * 3. 18.6 Anlise sinttica

Para implementar o algoritmo anterior, necessitamos estar prontos para percorrer uma string e quebr-la em operandos e operadores. Este process um exemplo de XXXparsing, e o resultado - os pedaos da string - so chamados XXXtokens. Voc deve lembrar estas palavras do captulo 1. Python fornece um mtodo split nos mdulos string e re (expresses regulares). A funo string.split separa uma string numa lista usando um nico caracter como delimitador. Por exemplo:
>>> import string >>> string.split ("Now is the time", " ")

['Now', 'is', 'the', 'time']

Neste caso, o delimitador o caracter de espao, ento a string dividida a cada espao. A funo re.split mais poderosa, permitindo-nos fornecer uma expreso regular ao invs de um delimitador. Uma expresso regular uma maneira de especificar um conjunto de strings. Por exemplo, [A-z] o conjunto de todas as letras e [0-9] o conjunto de todos os dgitos. O operador ^nega um conunto, ento [^0-9] o conjunto de tudo o que no nmero, que exatamente o que queremos para dividir expresses ps-fixas.
>>> import re >>> re.split ("[^0-9]", "123+456*/")

['123', '+', '456', '*', '', '/', ' '] Note que a ordem dos argumentos diferente de string.split, o delimitador vem antes da string. A lista resultante inclui os operandos 123 e 456, e os operadores * e /. Tambm inclui duas strings vazias que so inseridas depois dos operadores. 18.7 Avaliando em ps-fixo.

Para avaliar uma expresso ps-fixa, usaremos o parser da seo anterior e o algoritmo da seo anterior a ela. Para manter as coisas simples, comearemos com um avaliador que implementa somente os operadores + e .
def evalPostfix (expr) : import re tokenList = re.split ("([^0-9])", expr) stack = Stack() for token in tokenList if token == '' or token = ' ' : continue if token == '+' : sum = stack.pop() + stack.pop() stack.push(sum) if token == '*' : product = stack.pop() * stack.pop() stack.push(product)

else: stack.push(int(token)) return stack.pop()

A primeira condio cuida de espaos e strings vazias. As duas prximas condies manipulam os operadores. Ns assumimos, agora que qualquer coisa um operador. claro, seria melhor chegar por entrada errnea e enviar uma mensagem de erro, mas faremos isto depois. Vamos test-lo avaliando a forma ps-fixa de (56 + 47) * 2
>>> print evalPostfix("56 47 + 2 *")

206 XXXthat's close enough 18.8 Clientes de fornecedores. Um dos objetivos de um TAD separar os interesses do fornecedor, quem escreve o cdigo que implementa o TAD, e o cliente, que usa o TAD. O fornecedor tem que se preocupar apenas se a implementao est correta - de acordo com a especificao do TAD - e no como ele ser usado. Inversamente, o cliente assume que a implementao do TAD est correta e no se preocupa com os detalhes. Quando voc est usando um tipo nativo do Python, tem o luxo de pensar exclusivamente como um cliente. claro, quanto voc implementa um TAD, voc tambm tem que escrever cdigo cliente para test-lo. Neste caso, voc faz os dois papis, o que pode ser confuso. Voc deve fazer algum esfor para manter a trilha do papel que est fazendo a cada momento.

18.9 Glossrio

tipo abstrato de dados (TAD) (abstract data type(ADT)): Um tipo de dado(geralmente uma coleo de objetos) que definidopor um conjunto de operaes, que podem ser implementadas de vrias maneiras. interface (interface): o conjunto de operaes que definem um TDA.

implementao (implementation): Cdigo que satisfaz(preenche?) os requisitos sintticos e semnticos de uma interface. cliente (client): Um programa (ou o programador que o escreveu) que faz utilizao de um TDA. fornecedor (provider): Cdigo (ou o programador que o escreveu) que implementa um TDA. revestimento (veneer): Definio de classe que implementa um TDA com definies de mtodos que so chamadas a outros mtodos, s vezes com pequenas modificaes. A lmina faz um trabalho insignificante, mas melhora ou padroniza a interface dada ao cliente. estrutura de dados genrica (generic data structure): Tipo de estrutura de dados que contem data de um tipo qualquer(tipo genrico). infixa (infix): Notao matemtica em que os operadores se situam entre os operandos. ps-fixa (postfix): Notao matemtica em que os operadores se situam aps os operandos. XXX parse (parse): Ler um conjunto de caracteres(string de caracteres) ou tokens(smbolos atmicos) e analisar sua estrutura gramatical. XXX token (token): Conjunto de caracteres que so tratados como uma unidade atmica para fins de anlise gramatical, como as palavras na linguagem natural. delimitador (delimiter): Um caracter que utilizado para separar os smbolos atmicos(tokens), como a pontuao na linguagem natural.

System Message: WARNING/2 (<string>, line 20185) Block quote ends without a blank line; unexpected unindent.

Captulo 19: Filas


Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos o 3.4 Funes matemticas o 3.5 Composio o 3.6 Adicionando novas funes o 3.7 Definies e uso o 3.8 Fluxo de execuo o 3.9 Parmetros e argumentos o 3.10 Variveis e parmetros so locais o 3.11 Diagramas da pilha o 3.12 Funes com resultados o 3.13 Glossrio Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo

4.2 Expresses booleanas 4.3 Operadores lgicos 4.4 Execuo condicional 4.5 Execuo alternativa 4.6 Condicionais encadeados 4.7 Condicionais aninhados 4.8 A instruo return 4.9 Recursividade 4.10 Diagramas de pilha para funes recursivas 4.11 Recursividade infinita 4.12 Entrada pelo teclado 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings
o o o o o o o o o o o o

Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores

19.7 Glossrio

fila (queue) Um conjunto de objetos ordenados esperando por algum tipo de servio. Fila (Queue) Um TAD (Tipo Abstrato de Dado) que realiza as operaes que algum poderia realizar em uma fila. poltica de enfileiramento (queueing policy) As regras que determinam qual membro de uma fila o prximo a ser removido. FIFO "First In, First Out," (Primeiro a entrar, primeiro a sair) uma poltica de enfileiramento em que o primeiro membro a chegar o primeiro a ser

removido. fila de prioridade (priority queue) Uma poltica de enfileiramento em que cada membro tem uma prioridade determinada por fatores externos. O membro com a maior prioridade o primeiro a ser removido. Fila de Prioridade (Priority Queue) Um TAD que define as operaes que algum deveria realizar em uma fila de prioridade. fila encadeada (linked queue) Uma implementao de uma fila usando uma lista encadeada. tempo constante (constant time) Uma operao cujo tempo de execuo no depende do tamanho da estrutura de dados. tempo linear (linear time) Uma operao cujo tempo de execuo uma funo linear do tamanho da estrutura de dados.

Captulo 19: Filas


System Message: INFO/1 (<string>, line 20256); backlink Duplicate implicit target name: "captulo 19: filas". Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos

2.2 Variveis 2.3 Nomes de variveis e palavras reservadas 2.4 Comandos 2.5 Avaliando expresses 2.6 Operadores e operandos 2.7 Ordem dos operadores 2.8 Operaes com strings 2.9 Composio 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos o 3.4 Funes matemticas o 3.5 Composio o 3.6 Adicionando novas funes o 3.7 Definies e uso o 3.8 Fluxo de execuo o 3.9 Parmetros e argumentos o 3.10 Variveis e parmetros so locais o 3.11 Diagramas da pilha o 3.12 Funes com resultados o 3.13 Glossrio Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita
o o o o o o o o o

4.12 Entrada pelo teclado 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores
o o

Captulo 20: rvores

19.7 Glossrio

fila (queue) Um conjunto de objetos ordenados esperando por algum tipo de servio. Fila (Queue) Um TAD (Tipo Abstrato de Dado) que realiza as operaes que algum poderia realizar em uma fila. poltica de enfileiramento (queueing policy) As regras que determinam qual membro de uma fila o prximo a ser removido. FIFO "First In, First Out," (Primeiro a entrar, primeiro a sair) uma poltica de enfileiramento em que o primeiro membro a chegar o primeiro a ser removido. fila de prioridade (priority queue) Uma poltica de enfileiramento em que cada membro tem uma prioridade determinada por fatores externos. O membro com a maior prioridade o primeiro a ser removido. Fila de Prioridade (Priority Queue) Um TAD que define as operaes que algum deveria realizar em uma fila de prioridade. fila encadeada (linked queue) Uma implementao de uma fila usando uma lista encadeada. tempo constante (constant time) Uma operao cujo tempo de execuo no depende do tamanho da estrutura de dados. tempo linear (linear time)

Uma operao cujo tempo de execuo uma funo linear do tamanho da estrutura de dados.

Captulo 20: rvores


Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos o 3.4 Funes matemticas o 3.5 Composio o 3.6 Adicionando novas funes o 3.7 Definies e uso o 3.8 Fluxo de execuo o 3.9 Parmetros e argumentos o 3.10 Variveis e parmetros so locais o 3.11 Diagramas da pilha o 3.12 Funes com resultados o 3.13 Glossrio Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos

4.4 Execuo condicional 4.5 Execuo alternativa 4.6 Condicionais encadeados 4.7 Condicionais aninhados 4.8 A instruo return 4.9 Recursividade 4.10 Diagramas de pilha para funes recursivas 4.11 Recursividade infinita 4.12 Entrada pelo teclado 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas
o o o o o o o o o o

Captulo 9: Tuplas Captulo 9: Tuplas Captulo 10: Dicionrios Captulo 10: Dicionrios Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores Note Esta traduo est uns 70% completa em 06set04. Em particular, falta traduzir os programas. Comentrios e sugestes so bem vindos. Veja a discusso sobre o vocabulrio usado no fim da pgina. Em 15nov04 as figuras foram colocadas em sidebars. Clique em exibir fonte (no topo da pgina) para ver a dica.

Como listas ligadas, rvores so constitudas de clulas. Uma espcie comum de rvores a rvore binria, em que cada clula contm referncias a duas outras clulas (possivelmente nulas). Tais referncias so chamadas de subrvore esquerda e direita. Como as clulas de listas ligadas, as clulas de rvores tambm contm uma carga. Um diagrama de estados para uma rvore pode aparecer assim: Figura 1

Para evitar a sobrecarga da figura, ns frequentemente omitimos os Nones. O topo da rvore (a clula qual o apontador tree se refere) chamada de raiz. Seguindo a metfora das rvores, as outras clulas so chamadas de galhos e as clulas nas pontas contendo as referncias vazia so chamadas de folhas. Pode parecer estranho que desenhamos a figura com a raiz em cima e as folhas em baixo, mas isto nem ser a coisa mais estranha. Para piorar as coisas, cientistas da computao misturam outra metfora alm da metfora biolgica - a rvore genealgica. Uma clula superior pode ser chamada de pai e as clulas a que ela se refere so chamadas de seus filhos. Clulas com o mesmo pai so chamadas de irmos. Finalmente, existe tambm o vocabulrio geomtrico para falar de rvores. J mencionamos esquerda e direita, mas existem tambm as direes "para cima" (na direo da raiz) e "para baixo" (na direo dos filhos/folhas). Ainda nesta terminologia, todas as clulas situadas mesma distncia da raiz constituem um nvel da rvore. Provavelmente no precisamos de trs metforas para falar de rvores, mas a elas esto. Como listas ligadas, rvores so estruturas de dados recursivas j que elas so definidas recursivamente: Uma rvore a rvore vazia, representada por None, ou uma clula que contm uma referncia a um objeto (a carga da clula) e duas referncias a rvores. 20.1 Construindo rvores

O processo de montar uma rvore similar ao processo de montar uma lista ligada. cada invocao do construtor cria uma clula.
class Tree :

def __init__(self, cargo, left=None, right=None) : self.cargo = cargo self.left = left self.right = right

def __str__(self) : return str(self.cargo)

A carga pode ser de qualquer tipo, mas os parmetros left e right devem ser clulas. left e right so opcionais; o valor default None. Para imprimir uma clula, imprimimos apenas a sua carga. Uma forma de construir uma rvore de baixo para cima. Aloque os filhos primeiro:
left = Tree(2) right = Tree(3)

Em seguida crie a clula pai e ligue ela a seus filhos:


tree = Tree(1, left, right);

Podemos escrever este cdigo mais concisamente encaixando as invocaes do construtor:


>>> tree = Tree(1, Tree(2), Tree(3))

De qualquer forma, o resultado a rvore que apareceu no incio do captulo. 20.2 Percorrendo rvores

Cada vez que Voc v uma nova estrutura de dados, sua primeira pergunta deveria ser "Como eu percorro esta estrutura?" A forma mais natural de percorrer uma rvore fazer o percurso recursivamente. Por exemplo, se a rvore contm inteiros na carga, a funo abaixo retorna a soma das cargas:
def total(tree) : if tree == None : return 0 return total(tree.left) + total(tree.right) + tree.cargo

O caso base a rvore vazia, que no contm nenhuma carga, logo a soma das cargas 0. O passo recursivo faz duas chamadas recursivas para achar a

soma das cargas das subrvores dos filhos. Ao finalizar a chamada recursiva, adicionamos a carga do pai e devolvemos o valor total. 20.3 rvores de expresses

Uma rvore uma forma natural para representar a estrutura de uma expresso. Ao contrrio de outras notaes, a rvore pode representar a computao de forma no ambgua. Por exemplo, a expresso infixa 1 + 2 * 3 ambgua, a menos que saibamos que a multiplicao feita antes da adio. A rvore de expresso seguinte representa a mesma computao: Figura 2

As clulas de uma rvore de expresso podem ser operandos como 1 e 2 ou operaes como + e *. As clulas contendo operandos so folhas; aquelas contendo operaes devem ter referncias aos seus operandos. (Todos os nossos operandos so binrios, significando que eles tem exatamente dois operandos.) Podemos construir rvores assim:
>>> tree = Tree('+', Tree(1), Tree('*', Tree(2), Tree(3)))

Examinando a figura, no h dvida quanto ordem das operaes; a multiplicao feita primeiro para calcular o segundo operando da adio. rvores de expresso tem muitos usos. O exemplo neste captulo usa rvores para traduzir expresses para as notaes psfixa, prefixa e infixa. rvores similares so usadas em compiladores para analisar sintaticamente, otimizar e traduzir programas. 20.4 Percurso de rvores

Podemos percorrer uma rvore de expresso e imprimir o seu contedo como segue:
def printTree(tree) : if tree == None : return print tree.cargo, printTree(tree.left) printTree(tree.right)

Em outras palavras, para imprimir uma rvore, imprima primeiro o contedo da raiz, em seguida imprima toda a subrvore esquerda e finalmente imprima toda a subrvore direita. Esta forma de percorrer uma rvore chamada de prordem, porque o contedo da raiz aparece antes dos contedos dos filhos. Para o exemplo anterior, a sada :
>>> tree = Tree('+', Tree(1), Tree('*', Tree(2), Tree(3))) >>> printTree(tree) +1*23

Esta notao diferente tanto da notao psfixa quanto da infixa; uma notao chamada de prefixa, em que os operadores aparecem antes dos seus operandos. Voc pode suspeitar que se Voc percorre a rvore numa ordem diferente, Voc produzir expresses numa notao diferente. Por exemplo, se Voc imprime subrvores primeiro e depois a raiz, Voc ter:
def printTreePostorder(tree) : if tree == None : return printTreePostorder(tree.left) printTreePostorder(tree.right) print tree.cargo,

O resultado, 1 2 3 * +, est na notao psfixa! Esta ordem de percurso chamada de psordem. Finalmente, para percorrer uma rvore em inordem, Voc imprime a subrvore esquerda, depois a raiz e depois a subrvore direita:
def printTreeInorder(tree) : if tree == None : return

printTreeInorder(tree.left) print tree.cargo, printTreeInorder(tree.right)

O resultado 1 + 2 * 3, que a expresso na notao infixa. Para sermos justos, devemos lembrar que acabamos de omitir uma complicao importante. algumas vezes quando escrevemos expresses na notao infixa devemos usar parntesis para prescrever a ordem das operaes. Ou seja, um percurso em inordem no suficiente para gerar a expresso infixa. Ainda assim, com alguns aperfeioamentos, a rvore de expresso e os trs modos recursivos de percurso resultam em algoritmos para transformar expresses de uma notao para outra. Como um exerccio, modifique `printTreeInorder` de modo que ele coloque parntesis em volta de cada operador e par de operandos. A sada correta e no ambgua? Os parntesis so sempre necessrios? Se percorrermos uma rvore em inordem e acompanharmos em qual nvel na rvore estamos, podemos gerar uma representao grfica da rvore:
def printTreeIndented(tree, level=0) : if tree == None : return printTreeIndented(tree.right, level+1) print ' '*level + str(tree.cargo) printTreeIndented(tree.left, level+1)

O parmetro level registra aonde estamos na rvore. Por 'default', o nvel inicialmente zero. A cada chamada recursiva repassamos level+1 porque o nvel do filho sempre um a mais do que o nvel do pai. Cada item indentado dois espaos por nvel. Para o nosso exemplo obtemos:
>>> printTreeIndented(tree) 3 * 2 + 1

Se Voc deitar a sada acima Voc enxerga uma verso simplificada da figura

original. 20.5 Construindo uma rvore de expresso

Nesta seo analisamos expresses infixas e construmos as rvores de express correspondentes. Por exemplo, para a expresso (3+7)*9 resultar a seguinte rvore: Figura 3

Note que simplificamos o diagrama omitindo os nomes dos campos. O analisador que escreveremos aceitar expresses que incluam nmeros, parntesis e as operaes + e *. Vamos supor que a cadeia de entrada j foi tokenizada numa lista do Python. A lista de tokens para a expresso (3+7)*9 : ['(', 3, '+', 7, ')', '*', 9, 'end'] O token final end prtico para prevenir que o analisador tente buscar mais dados aps o trmino da lista. A ttulo de um exerccio, escreva uma funo que recebe uma expresso na forma de uma cadeia e devolve a lista de tokens. A primeira funo que escreveremos getToken que recebe como parmetros uma lista de tokens e um token esperado. Ela compara o token esperado com o o primeiro token da lista: se eles batem a funo remove o token da lista e devolve um valor verdadeiro, caso contrrio a funo devolve um valor falso:
def getToken(tokenList, expected) : if tokenList[0] == expected : tokenList[0:1] = [] # remove the token return 1 else : return 0

J que tokenList refere a um objeto mutvel, as alteraes feitas aqui so

visveis para qualquer outra varivel que se refira ao mesmo objeto. A prxima funo, getNumber, trata de operandos. Se o primeiro token na tokenList for um nmero ento getNumber o remove da lista e devolve uma clula folha contendo o nmero; caso contrrio ele devolve None.
def getNumber(tokenList) : x = tokenList[0] if type(x) != type(0) : return None del tokenList[0] return Tree(x, None, None)

Antes de continuar, convm testar getNumber isoladamente. Atribumos uma lista de nmeros a tokenList, extramos o primeiro, imprimimos o resultado e imprimimos o que resta na lista de tokens:
>>> tokenList = [9, 11, 'end'] >>> x = getNumber(tokenList) >>> printTreePostorder(x) 9 >>> print tokenList [11, 'end']

Em seguida precisaremos da funo getProduct, que constri uma rvore de expresso para produtos. Os dois operandos de um produto simples so nmeros, como em 3 * 7. Segue uma verso de getProduct que trata de produtos simples.
def getProduct(tokenList) : a = getNumber(tokenList) if getToken(tokenList, '*') : b = getNumber(tokenList) return Tree('*', a, b) else : return a

Supondo que a chamada de getNumber seja bem sucedida e devolva uma rvore de uma s clula atribumos o primeiro operando a `. Se o prximo caractere for *, vamos buscar o segundo nmero e construir a rvore com a, b

e o operador. Se o caractere seguinte for qualquer outra coisa, ento simplesmente devolvemos uma clula folha com a. Seguem dois exemplos:
>>> tokenList = [9, '*', 11, 'end'] >>> tree = getProduct(tokenList) >>> printTreePostorder(tree) 9 11 *

>>> tokenList = [9, '+', 11, 'end'] >>> tree = getProduct(tokenList) >>> printTreePostorder(tree) 9

O segundo exemplo sugere que ns consideramos um operando unitrio como uma espcie de produto. Esta definio de "produto" talvez no seja intuitiva, mas ela ser til. Agora tratamos produtos compostos, como 3 * 5 * 13. Encaramos esta expresso como um produto de produtos, mais precisamente como 3 * (5 * 13). A rvore resultante : Figura 4

Com uma pequena alterao em getProduct, podemos acomodar produtos arbitrariamente longos:
def getProduct(tokenList) : a = getNumber(tokenList) if getToken(tokenList, '*') : b = getProduct(tokenList) return Tree('*', a, b) # this line changed

else : return a

Em outras palavras, um produto pode ser um singleton ou uma rvore com * na raiz, que tem um nmero como filho esquerdo e um produto como filho direito. Este tipo de definio recursiva devia comear a ficar familiar. Testemos a nova verso com um produto composto:
>>> tokenList = [2, '*', 3, '*', 5 , '*', 7, 'end'] >>> tree = getProduct(tokenList) >>> printTreePostorder(tree) 2357***

A seguir adicionamos o tratamento de somas. De novo, usamos uma definio de "soma" que ligeiramente no intuitiva. Para ns, uma soma pode ser uma rvore com + na raiz, que tem um produto como filho esquerdo e uma soma como filho direito. Ou, uma soma pode ser simplesmente um produto. Se Voc est disposto a brincar com esta definio, ela tem uma propriedade interessante: podemos representar qualquer expresso (sem parntesis) como uma soma de produtos. Esta propriedade a base do nosso algoritmo de anlise sinttica. getSum tenta construir a rvore com um produto esquerda e uma soma direita. Mas, se ele no encontra uma +, ele simplesmente constri um produto.
def getSum(tokenList) : a = getProduct(tokenList) if getToken(tokenList, '+') : b = getSum(tokenList) return Tree('+', a, b) else : return a

Vamos testar o algoritmo com 9 * 11 + 5 * 7:


>>> tokenList = [9, '*', 11, '+', 5, '*', 7, 'end'] >>> tree = getSum(tokenList) >>> printTreePostorder(tree) 9 11 * 5 7 * +

Quase terminamos, mas ainda temos que tratar dos parntesis. Em qualquer lugar numa expresso onde podemos ter um nmero, podemos tambm ter uma soma inteira envolvida entre parntesis. Precisamos, apenas, modificar getNumber para que ela possa tratar de subexpresses:
def getNumber(tokenList) : if getToken(tokenList, '(') : x = getSum(tokenList) getToken(tokenList, ')') return x else : x = tokenList[0] if type(x) != type(0) : return None tokenList[0:1] = [] # remove the token return Tree(x, None, None) # return a leaf with the number # get subexpression # eat the closing parenthesis

Testemos este cdigo com 9 * (11 + 5) * 7:


>>> tokenList = [9, '*', '(', 11, '+', 5, ')', '*', 7, 'end'] >>> tree = getSum(tokenList) >>> printTreePostorder(tree) 9 11 5 + 7 * *

O analisador tratou os parntesis corretamente; a adio feita antes da multiplicao. Na verso final do programa, seria uma boa idia dar a getNumber um nome mais descritivo do seu novo papel. 20.6 Manipulando erros

Ao longo do analisador sinttico tnhamos suposto que as expresses (de entrada) so bem formadas. Por exemplo, quando atingimos o fim de uma subexpresso, supomos que o prximo caractere um facha parntesis. Caso haja um erro e o prximo caractere seja algo diferente, devemos tratar disto.
def getNumber(tokenList) : if getToken(tokenList, '(') :

x = getSum(tokenList) if not getToken(tokenList, ')'): raise 'BadExpressionError', 'missing parenthesis' return x else : # the rest of the function omitted

O comando raise cria uma exceo; neste caso criamos um novo tipo de exceo, chamada de BadExpressionError. Se a funo que chamou getNumber, ou uma das outras funes no traceback, manipular a exceo, ento o programa pode continuar. caso contrrio Python vai imprimir uma mensagem de erro e terminar o processamento em seguida. A ttulo de exerccio, encontre outros locais nas funes criadas onde erros possam ocorrer e adiciona comandos ``raise`` apropriados. Teste seu cdigo com expresses mal formadas. 20.7 A rvore dos animais

Nesta seo, desenvolvemos um pequeno programa que usa uma rvore para representar uma base de conhecimento. O programa interage com o usurio para criar uma rvore de perguntas e de nomes de animais. Segue uma amostra da funcionalidade:
Are you thinking of an animal? y Is it a bird? n What is the animals name? dog What question would distinguish a dog from a bird? Can it fly If the animal were dog the answer would be? n

Are you thinking of an animal? y Can it fly? n Is it a dog? n What is the animals name? cat What question would distinguish a cat from a dog? Does it bark If the animal were cat the answer would be? n

Are you thinking of an animal? y Can it fly? n Does it bark? y Is it a dog? y I rule!

Are you thinking of an animal? n

Aqui est a rvore que este dilogo constri: Figura 5

No comeo de cada rodada, o programa parte do topo da rvore e faz a primeira pergunta. Dependendo da resposta, ele segue pelo filho esquerdo ou direito e continua at chegar numa folha. Neste ponto ele arrisca um palpite. Se o palpite no for correto, ele pergunta ao usurio o nome de um novo animal e uma pergunta que distingue o palpite errado do novo animal. A seguir, adiciona uma clula rvore contendo a nova pergunta e o novo animal. Aqui est o cdigo:
def animal() : # start with a singleton root = Tree("bird")

# loop until the user quits while 1 : print if not yes("Are you thinking of an animal? ") : break

# walk the tree

tree = root while tree.getLeft() != None : prompt = tree.getCargo() + "? " if yes(prompt): tree = tree.getRight() else: tree = tree.getLeft()

# make a guess guess = tree.getCargo() prompt = "Is it a " + guess + "? " if yes(prompt) : print "I rule!" continue

# get new information prompt = "What is the animal\'s name? " animal = raw_input(prompt) prompt = "What question would distinguish a %s from a %s? " question = raw_input(prompt % (animal,guess))

# add new information to the tree tree.setCargo(question) prompt = "If the animal were %s the answer would be? " if yes(prompt % animal) : tree.setLeft(Tree(guess)) tree.setRight(Tree(animal)) else : tree.setLeft(Tree(animal)) tree.setRight(Tree(guess))

A funo yes um auxiliar; ele imprime um prompt e em seguida solicita do usurio uma entrada. Se a resposta comear com y ou Y, a funo devolve um valor verdadeiro:
def yes(ques) : from string import lower ans = lower(raw_input(ques)) return (ans[0:1] == 'y')

A condio do lao externo 1`, que significa que ele continuar at a execuo de um comando break, caso o usurio no pense num animal. O lao while interno caminha na rvore de cima para baixo, guiado pelas respostas do usurio. Quando uma nova clula adicionada rvore, a nova pergunta substitui a carga e os dois filhos so o novo animal e a carga original. Uma falha do programa que ao sair ele esquece tudo que lhe foi cuidadosamente ensinado! A ttulo de exerccio, pense de vrias jeitos para salvar a rvore do conhecimento acumulado num arquivo. Implemente aquele que Voc pensa ser o mais fcil. 20.8 Glossrio

rvore binria (binary tree) Uma rvore em que cada clula tem zero, um ou dois descendentes. raiz (root) A clula mais alta de uma rvore, a (nica) clula de uma rvore que no tem pai. folha (leaf) Uma clula mais baixa numa rvore; uma clula que no tem descendentes. pai (parent) A clula que aponta para uma clula dada.

filho (child) Uma clula apontada por uma clula dada. irmos (siebling) Clulas que tem o mesmo pai. nvel (level) Um conjunto de clulas equidistantes da raiz. operador binrio (binary operator) Um operador sobre dois operandos. subexpresso (subexpression) Uma expresso entre parntesis que se comporta como um operando simples numa expresso maior. pr-ordem (preorder) Uma forma de percorrer uma rvore visitando cada clula antes dos seus filhos. notao prefixa (prefix notation) Uma forma de escrever uma expresso matemtica em que cada operador aparece antes dos seus operandos. ps-ordem (postorder) Uma forma de percorrer uma rvore visitando os filhos de cada clula antes da prpria clula. in-ordem (inorder) Uma forma de percorrer uma rvore visitando a subrvore esquerda, seguida da raiz e finalmente da subrvore direita.

Captulo 20: rvores


System Message: INFO/1 (<string>, line 21277); backlink Duplicate implicit target name: "captulo 20: rvores".

Tpicos Captulo 1: O caminho do programa Captulo 1: O caminho do programa Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 2: Variveis, expresses e comandos o 2.1 Valores e tipos o 2.2 Variveis o 2.3 Nomes de variveis e palavras reservadas o 2.4 Comandos o 2.5 Avaliando expresses o 2.6 Operadores e operandos o 2.7 Ordem dos operadores o 2.8 Operaes com strings o 2.9 Composio o 2.11 Glossrio Captulo 3: Funes o 3.1 Chamadas de funes o 3.2 Converso entre tipos o 3.3 Coero entre tipos o 3.4 Funes matemticas o 3.5 Composio o 3.6 Adicionando novas funes o 3.7 Definies e uso o 3.8 Fluxo de execuo o 3.9 Parmetros e argumentos o 3.10 Variveis e parmetros so locais o 3.11 Diagramas da pilha o 3.12 Funes com resultados o 3.13 Glossrio Captulo 3: Funes Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados

4.8 A instruo return 4.9 Recursividade 4.10 Diagramas de pilha para funes recursivas 4.11 Recursividade infinita 4.12 Entrada pelo teclado 4.13 Glossrio Captulo 4: Condicionais e recurso o 4.1 O operador mdulo o 4.2 Expresses booleanas o 4.3 Operadores lgicos o 4.4 Execuo condicional o 4.5 Execuo alternativa o 4.6 Condicionais encadeados o 4.7 Condicionais aninhados o 4.8 A instruo return o 4.9 Recursividade o 4.10 Diagramas de pilha para funes recursivas o 4.11 Recursividade infinita o 4.12 Entrada pelo teclado o 4.13 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 5: Funes frutferas o 5.1 Valores de retorno o 5.2 Desenvolvimento de programas o 5.3 Composio o 5.4 Funes booleanas o 5.5 Mais recursividade o 5.6 Voto de confiana (Leap of faith) o 5.7 Mais um exemplo o 5.8 Checagem de tipos o 5.9 Glossrio Captulo 6: Iterao Captulo 6: Iterao Captulo 7: Strings Captulo 7: Strings Captulo 8: Listas Captulo 8: Listas Captulo 9: Tuplas Captulo 9: Tuplas Captulo 10: Dicionrios Captulo 10: Dicionrios
o o o o o o

Captulo 11: Arquivos e excees Captulo 11: Arquivos e excees Captulo 12: Classes e objetos Captulo 12: Classes e objetos Captulo 13: Classes e funes Captulo 13: Classes e funes Captulo 14: Classes e mtodos Captulo 14: Classes e mtodos Captulo 15: Conjuntos de objetos Captulo 15: Conjuntos de objetos Capitulo 16: Herana Capitulo 16: Herana Captulo 17: Listas encadeadas Captulo 18: Pilhas Captulo 18: Pilhas Captulo 19: Filas Captulo 19: Filas Captulo 20: rvores Captulo 20: rvores Note Esta traduo est uns 70% completa em 06set04. Em particular, falta traduzir os programas. Comentrios e sugestes so bem vindos. Veja a discusso sobre o vocabulrio usado no fim da pgina. Em 15nov04 as figuras foram colocadas em sidebars. Clique em exibir fonte (no topo da pgina) para ver a dica.

Como listas ligadas, rvores so constitudas de clulas. Uma espcie comum de rvores a rvore binria, em que cada clula contm referncias a duas outras clulas (possivelmente nulas). Tais referncias so chamadas de subrvore esquerda e direita. Como as clulas de listas ligadas, as clulas de rvores tambm contm uma carga. Um diagrama de estados para uma rvore pode aparecer assim: Figura 1

Para evitar a sobrecarga da figura, ns frequentemente omitimos os Nones. O topo da rvore (a clula qual o apontador tree se refere) chamada de raiz. Seguindo a metfora das rvores, as outras clulas so chamadas de galhos e as clulas nas pontas contendo as referncias vazia so chamadas de folhas. Pode parecer estranho que desenhamos a figura com a raiz em cima e as folhas em baixo, mas isto nem ser a coisa mais estranha. Para piorar as coisas, cientistas da computao misturam outra metfora alm da metfora biolgica - a rvore genealgica. Uma clula superior pode ser chamada de pai e as clulas a que ela se refere so chamadas de seus filhos. Clulas com o mesmo pai so chamadas de irmos. Finalmente, existe tambm o vocabulrio geomtrico para falar de rvores. J mencionamos esquerda e direita, mas existem tambm as direes "para cima" (na direo da raiz) e "para baixo" (na direo dos filhos/folhas). Ainda nesta terminologia, todas as clulas situadas mesma distncia da raiz constituem um nvel da rvore. Provavelmente no precisamos de trs metforas para falar de rvores, mas a elas esto. Como listas ligadas, rvores so estruturas de dados recursivas j que elas so definidas recursivamente: Uma rvore a rvore vazia, representada por None, ou uma clula que contm uma referncia a um objeto (a carga da clula) e duas referncias a rvores. 20.1 Construindo rvores

O processo de montar uma rvore similar ao processo de montar uma lista ligada. cada invocao do construtor cria uma clula.
class Tree : def __init__(self, cargo, left=None, right=None) : self.cargo = cargo self.left = left self.right = right

def __str__(self) :

return str(self.cargo)

A carga pode ser de qualquer tipo, mas os parmetros left e right devem ser clulas. left e right so opcionais; o valor default None. Para imprimir uma clula, imprimimos apenas a sua carga. Uma forma de construir uma rvore de baixo para cima. Aloque os filhos primeiro:
left = Tree(2) right = Tree(3)

Em seguida crie a clula pai e ligue ela a seus filhos:


tree = Tree(1, left, right);

Podemos escrever este cdigo mais concisamente encaixando as invocaes do construtor:


>>> tree = Tree(1, Tree(2), Tree(3))

De qualquer forma, o resultado a rvore que apareceu no incio do captulo. 20.2 Percorrendo rvores

Cada vez que Voc v uma nova estrutura de dados, sua primeira pergunta deveria ser "Como eu percorro esta estrutura?" A forma mais natural de percorrer uma rvore fazer o percurso recursivamente. Por exemplo, se a rvore contm inteiros na carga, a funo abaixo retorna a soma das cargas:
def total(tree) : if tree == None : return 0 return total(tree.left) + total(tree.right) + tree.cargo

O caso base a rvore vazia, que no contm nenhuma carga, logo a soma das cargas 0. O passo recursivo faz duas chamadas recursivas para achar a soma das cargas das subrvores dos filhos. Ao finalizar a chamada recursiva, adicionamos a carga do pai e devolvemos o valor total. 20.3 rvores de expresses

Uma rvore uma forma natural para representar a estrutura de uma expresso. Ao contrrio de outras notaes, a rvore pode representar a

computao de forma no ambgua. Por exemplo, a expresso infixa 1 + 2 * 3 ambgua, a menos que saibamos que a multiplicao feita antes da adio. A rvore de expresso seguinte representa a mesma computao: Figura 2

As clulas de uma rvore de expresso podem ser operandos como 1 e 2 ou operaes como + e *. As clulas contendo operandos so folhas; aquelas contendo operaes devem ter referncias aos seus operandos. (Todos os nossos operandos so binrios, significando que eles tem exatamente dois operandos.) Podemos construir rvores assim:
>>> tree = Tree('+', Tree(1), Tree('*', Tree(2), Tree(3)))

Examinando a figura, no h dvida quanto ordem das operaes; a multiplicao feita primeiro para calcular o segundo operando da adio. rvores de expresso tem muitos usos. O exemplo neste captulo usa rvores para traduzir expresses para as notaes psfixa, prefixa e infixa. rvores similares so usadas em compiladores para analisar sintaticamente, otimizar e traduzir programas. 20.4 Percurso de rvores

Podemos percorrer uma rvore de expresso e imprimir o seu contedo como segue:
def printTree(tree) : if tree == None : return print tree.cargo, printTree(tree.left)

printTree(tree.right)

Em outras palavras, para imprimir uma rvore, imprima primeiro o contedo da raiz, em seguida imprima toda a subrvore esquerda e finalmente imprima toda a subrvore direita. Esta forma de percorrer uma rvore chamada de prordem, porque o contedo da raiz aparece antes dos contedos dos filhos. Para o exemplo anterior, a sada :
>>> tree = Tree('+', Tree(1), Tree('*', Tree(2), Tree(3))) >>> printTree(tree) +1*23

Esta notao diferente tanto da notao psfixa quanto da infixa; uma notao chamada de prefixa, em que os operadores aparecem antes dos seus operandos. Voc pode suspeitar que se Voc percorre a rvore numa ordem diferente, Voc produzir expresses numa notao diferente. Por exemplo, se Voc imprime subrvores primeiro e depois a raiz, Voc ter:
def printTreePostorder(tree) : if tree == None : return printTreePostorder(tree.left) printTreePostorder(tree.right) print tree.cargo,

O resultado, 1 2 3 * +, est na notao psfixa! Esta ordem de percurso chamada de psordem. Finalmente, para percorrer uma rvore em inordem, Voc imprime a subrvore esquerda, depois a raiz e depois a subrvore direita:
def printTreeInorder(tree) : if tree == None : return printTreeInorder(tree.left) print tree.cargo, printTreeInorder(tree.right)

O resultado 1 + 2 * 3, que a expresso na notao infixa. Para sermos justos, devemos lembrar que acabamos de omitir uma complicao importante. algumas vezes quando escrevemos expresses na notao infixa devemos usar parntesis para prescrever a ordem das

operaes. Ou seja, um percurso em inordem no suficiente para gerar a expresso infixa. Ainda assim, com alguns aperfeioamentos, a rvore de expresso e os trs modos recursivos de percurso resultam em algoritmos para transformar expresses de uma notao para outra. Como um exerccio, modifique `printTreeInorder` de modo que ele coloque parntesis em volta de cada operador e par de operandos. A sada correta e no ambgua? Os parntesis so sempre necessrios? Se percorrermos uma rvore em inordem e acompanharmos em qual nvel na rvore estamos, podemos gerar uma representao grfica da rvore:
def printTreeIndented(tree, level=0) : if tree == None : return printTreeIndented(tree.right, level+1) print ' '*level + str(tree.cargo) printTreeIndented(tree.left, level+1)

O parmetro level registra aonde estamos na rvore. Por 'default', o nvel inicialmente zero. A cada chamada recursiva repassamos level+1 porque o nvel do filho sempre um a mais do que o nvel do pai. Cada item indentado dois espaos por nvel. Para o nosso exemplo obtemos:
>>> printTreeIndented(tree) 3 * 2 + 1

Se Voc deitar a sada acima Voc enxerga uma verso simplificada da figura original. 20.5 Construindo uma rvore de expresso

Nesta seo analisamos expresses infixas e construmos as rvores de express correspondentes. Por exemplo, para a expresso (3+7)*9 resultar a seguinte rvore:

Figura 3

Note que simplificamos o diagrama omitindo os nomes dos campos. O analisador que escreveremos aceitar expresses que incluam nmeros, parntesis e as operaes + e *. Vamos supor que a cadeia de entrada j foi tokenizada numa lista do Python. A lista de tokens para a expresso (3+7)*9 : ['(', 3, '+', 7, ')', '*', 9, 'end'] O token final end prtico para prevenir que o analisador tente buscar mais dados aps o trmino da lista. A ttulo de um exerccio, escreva uma funo que recebe uma expresso na forma de uma cadeia e devolve a lista de tokens. A primeira funo que escreveremos getToken que recebe como parmetros uma lista de tokens e um token esperado. Ela compara o token esperado com o o primeiro token da lista: se eles batem a funo remove o token da lista e devolve um valor verdadeiro, caso contrrio a funo devolve um valor falso:
def getToken(tokenList, expected) : if tokenList[0] == expected : tokenList[0:1] = [] # remove the token return 1 else : return 0

J que tokenList refere a um objeto mutvel, as alteraes feitas aqui so visveis para qualquer outra varivel que se refira ao mesmo objeto. A prxima funo, getNumber, trata de operandos. Se o primeiro token na tokenList for um nmero ento getNumber o remove da lista e devolve uma clula folha contendo o nmero; caso contrrio ele devolve None.
def getNumber(tokenList) : x = tokenList[0] if type(x) != type(0) : return None

del tokenList[0] return Tree(x, None, None)

Antes de continuar, convm testar getNumber isoladamente. Atribumos uma lista de nmeros a tokenList, extramos o primeiro, imprimimos o resultado e imprimimos o que resta na lista de tokens:
>>> tokenList = [9, 11, 'end'] >>> x = getNumber(tokenList) >>> printTreePostorder(x) 9 >>> print tokenList [11, 'end']

Em seguida precisaremos da funo getProduct, que constri uma rvore de expresso para produtos. Os dois operandos de um produto simples so nmeros, como em 3 * 7. Segue uma verso de getProduct que trata de produtos simples.
def getProduct(tokenList) : a = getNumber(tokenList) if getToken(tokenList, '*') : b = getNumber(tokenList) return Tree('*', a, b) else : return a

Supondo que a chamada de getNumber seja bem sucedida e devolva uma rvore de uma s clula atribumos o primeiro operando a `. Se o prximo caractere for *, vamos buscar o segundo nmero e construir a rvore com a, b e o operador. Se o caractere seguinte for qualquer outra coisa, ento simplesmente devolvemos uma clula folha com a. Seguem dois exemplos:
>>> tokenList = [9, '*', 11, 'end'] >>> tree = getProduct(tokenList) >>> printTreePostorder(tree) 9 11 *

>>> tokenList = [9, '+', 11, 'end'] >>> tree = getProduct(tokenList) >>> printTreePostorder(tree) 9

O segundo exemplo sugere que ns consideramos um operando unitrio como uma espcie de produto. Esta definio de "produto" talvez no seja intuitiva, mas ela ser til. Agora tratamos produtos compostos, como 3 * 5 * 13. Encaramos esta expresso como um produto de produtos, mais precisamente como 3 * (5 * 13). A rvore resultante : Figura 4

Com uma pequena alterao em getProduct, podemos acomodar produtos arbitrariamente longos:
def getProduct(tokenList) : a = getNumber(tokenList) if getToken(tokenList, '*') : b = getProduct(tokenList) return Tree('*', a, b) else : return a # this line changed

Em outras palavras, um produto pode ser um singleton ou uma rvore com * na raiz, que tem um nmero como filho esquerdo e um produto como filho direito. Este tipo de definio recursiva devia comear a ficar familiar. Testemos a nova verso com um produto composto:
>>> tokenList = [2, '*', 3, '*', 5 , '*', 7, 'end'] >>> tree = getProduct(tokenList)

>>> printTreePostorder(tree) 2357***

A seguir adicionamos o tratamento de somas. De novo, usamos uma definio de "soma" que ligeiramente no intuitiva. Para ns, uma soma pode ser uma rvore com + na raiz, que tem um produto como filho esquerdo e uma soma como filho direito. Ou, uma soma pode ser simplesmente um produto. Se Voc est disposto a brincar com esta definio, ela tem uma propriedade interessante: podemos representar qualquer expresso (sem parntesis) como uma soma de produtos. Esta propriedade a base do nosso algoritmo de anlise sinttica. getSum tenta construir a rvore com um produto esquerda e uma soma direita. Mas, se ele no encontra uma +, ele simplesmente constri um produto.
def getSum(tokenList) : a = getProduct(tokenList) if getToken(tokenList, '+') : b = getSum(tokenList) return Tree('+', a, b) else : return a

Vamos testar o algoritmo com 9 * 11 + 5 * 7:


>>> tokenList = [9, '*', 11, '+', 5, '*', 7, 'end'] >>> tree = getSum(tokenList) >>> printTreePostorder(tree) 9 11 * 5 7 * +

Quase terminamos, mas ainda temos que tratar dos parntesis. Em qualquer lugar numa expresso onde podemos ter um nmero, podemos tambm ter uma soma inteira envolvida entre parntesis. Precisamos, apenas, modificar getNumber para que ela possa tratar de subexpresses:
def getNumber(tokenList) : if getToken(tokenList, '(') : x = getSum(tokenList) getToken(tokenList, ')') # get subexpression # eat the closing parenthesis

return x else : x = tokenList[0] if type(x) != type(0) : return None tokenList[0:1] = [] # remove the token return Tree(x, None, None) # return a leaf with the number

Testemos este cdigo com 9 * (11 + 5) * 7:


>>> tokenList = [9, '*', '(', 11, '+', 5, ')', '*', 7, 'end'] >>> tree = getSum(tokenList) >>> printTreePostorder(tree) 9 11 5 + 7 * *

O analisador tratou os parntesis corretamente; a adio feita antes da multiplicao. Na verso final do programa, seria uma boa idia dar a getNumber um nome mais descritivo do seu novo papel. 20.6 Manipulando erros

Ao longo do analisador sinttico tnhamos suposto que as expresses (de entrada) so bem formadas. Por exemplo, quando atingimos o fim de uma subexpresso, supomos que o prximo caractere um facha parntesis. Caso haja um erro e o prximo caractere seja algo diferente, devemos tratar disto.
def getNumber(tokenList) : if getToken(tokenList, '(') : x = getSum(tokenList) if not getToken(tokenList, ')'): raise 'BadExpressionError', 'missing parenthesis' return x else : # the rest of the function omitted

O comando raise cria uma exceo; neste caso criamos um novo tipo de

exceo, chamada de BadExpressionError. Se a funo que chamou getNumber, ou uma das outras funes no traceback, manipular a exceo, ento o programa pode continuar. caso contrrio Python vai imprimir uma mensagem de erro e terminar o processamento em seguida. A ttulo de exerccio, encontre outros locais nas funes criadas onde erros possam ocorrer e adiciona comandos ``raise`` apropriados. Teste seu cdigo com expresses mal formadas. 20.7 A rvore dos animais

Nesta seo, desenvolvemos um pequeno programa que usa uma rvore para representar uma base de conhecimento. O programa interage com o usurio para criar uma rvore de perguntas e de nomes de animais. Segue uma amostra da funcionalidade:
Are you thinking of an animal? y Is it a bird? n What is the animals name? dog What question would distinguish a dog from a bird? Can it fly If the animal were dog the answer would be? n

Are you thinking of an animal? y Can it fly? n Is it a dog? n What is the animals name? cat What question would distinguish a cat from a dog? Does it bark If the animal were cat the answer would be? n

Are you thinking of an animal? y Can it fly? n Does it bark? y Is it a dog? y I rule!

Are you thinking of an animal? n

Aqui est a rvore que este dilogo constri: Figura 5

No comeo de cada rodada, o programa parte do topo da rvore e faz a primeira pergunta. Dependendo da resposta, ele segue pelo filho esquerdo ou direito e continua at chegar numa folha. Neste ponto ele arrisca um palpite. Se o palpite no for correto, ele pergunta ao usurio o nome de um novo animal e uma pergunta que distingue o palpite errado do novo animal. A seguir, adiciona uma clula rvore contendo a nova pergunta e o novo animal. Aqui est o cdigo:
def animal() : # start with a singleton root = Tree("bird")

# loop until the user quits while 1 : print if not yes("Are you thinking of an animal? ") : break

# walk the tree tree = root while tree.getLeft() != None : prompt = tree.getCargo() + "? " if yes(prompt): tree = tree.getRight() else:

tree = tree.getLeft()

# make a guess guess = tree.getCargo() prompt = "Is it a " + guess + "? " if yes(prompt) : print "I rule!" continue

# get new information prompt = "What is the animal\'s name? " animal = raw_input(prompt) prompt = "What question would distinguish a %s from a %s? " question = raw_input(prompt % (animal,guess))

# add new information to the tree tree.setCargo(question) prompt = "If the animal were %s the answer would be? " if yes(prompt % animal) : tree.setLeft(Tree(guess)) tree.setRight(Tree(animal)) else : tree.setLeft(Tree(animal)) tree.setRight(Tree(guess))

A funo yes um auxiliar; ele imprime um prompt e em seguida solicita do usurio uma entrada. Se a resposta comear com y ou Y, a funo devolve um valor verdadeiro:
def yes(ques) : from string import lower ans = lower(raw_input(ques)) return (ans[0:1] == 'y')

A condio do lao externo 1`, que significa que ele continuar at a execuo de um comando break, caso o usurio no pense num animal. O lao while interno caminha na rvore de cima para baixo, guiado pelas respostas do usurio. Quando uma nova clula adicionada rvore, a nova pergunta substitui a carga e os dois filhos so o novo animal e a carga original. Uma falha do programa que ao sair ele esquece tudo que lhe foi cuidadosamente ensinado! A ttulo de exerccio, pense de vrias jeitos para salvar a rvore do conhecimento acumulado num arquivo. Implemente aquele que Voc pensa ser o mais fcil. 20.8 Glossrio

rvore binria (binary tree) Uma rvore em que cada clula tem zero, um ou dois descendentes. raiz (root) A clula mais alta de uma rvore, a (nica) clula de uma rvore que no tem pai. folha (leaf) Uma clula mais baixa numa rvore; uma clula que no tem descendentes. pai (parent) A clula que aponta para uma clula dada. filho (child) Uma clula apontada por uma clula dada. irmos (siebling) Clulas que tem o mesmo pai. nvel (level) Um conjunto de clulas equidistantes da raiz.

operador binrio (binary operator) Um operador sobre dois operandos. subexpresso (subexpression) Uma expresso entre parntesis que se comporta como um operando simples numa expresso maior. pr-ordem (preorder) Uma forma de percorrer uma rvore visitando cada clula antes dos seus filhos. notao prefixa (prefix notation) Uma forma de escrever uma expresso matemtica em que cada operador aparece antes dos seus operandos. ps-ordem (postorder) Uma forma de percorrer uma rvore visitando os filhos de cada clula antes da prpria clula. in-ordem (inorder) Uma forma de percorrer uma rvore visitando a subrvore esquerda, seguida da raiz e finalmente da subrvore direita.

Docutils System Messages


System Message: ERROR/3 (<string>, line 1512); backlinks: 1, 2 Too many autonumbered footnote references: only 4 corresponding footnotes available.

Você também pode gostar