Você está na página 1de 98

Como pensar como um cientista da

Computao usando Python

Allen Downey

Jerey Elkner

Chris Meyers

Traduo: Equipe do projeto http://pensarpython.incubadora.fapesp.br

Edio: Crlisson Galdino


Como pensar como um cientista da Computao usando Python

Copyright (c) 2002 Allen Downey, Jerey Elkner, and Chris Meyers.
Edited by Shannon Turlington and Lisa Cutler. Cover design by Rebecca
Gimenez.
Printing history:
April 2002: First edition.
Green Tea Press
1 Grove St.
P.O. Box 812901
Wellesley, MA 02482
Permission is granted to copy, distribute, and/or modify this document under the
terms of the GNU Free Documentation License, Version 1.1 or any later version
published by the Free Software Foundation; with the Invariant Sections being
Foreword, Preface, and Contributor List, with no Front-Cover Texts, and
with no BackCover Texts. A copy of the license is included in the appendix
entitled GNU Free Documentation License.
The GNU Free Documentation License is available from www.gnu.org or by
writing to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307, USA.

Como pensar como um cientista da Computao usando Python


Verso atual: 1.0
Data de Publicao: 16 de janeiro de 2008
Classificao: Tutorial
Autor: Jeffrey Elkner (traduzido pelo projeto Pensar Python -
http://pensarpython.incubadora.fapesp.br)
Publicao: Cyaneus.net

#2
Como pensar como um cientista da Computao usando Python

ndice

Foreword....................................................................5 4.8 A instruo return....................................................28


Apresentao..............................................................6 4.9 Recursividade..........................................................29
Preface........................................................................7 4.10 Diagramas de pilha para funes recursivas........29
How and why I came to use Python...............................7 4.11 Recursividade infinita...........................................30
Finding a textb o ok........................................................7 4.12 Entrada pelo teclado..............................................30
Intro ducing programming with Python.........................7 4.13 Glossrio...............................................................30
Building a community.....................................................8 Captulo 5: Funes frutferas.................................31
Prefcio................................................................... ....9 5.1 Valores de retorno...................................................31
Como e porque eu vim a usar Python.............................9 5.2 Desenvolvimento de programas.............................31
Encontrando um livro texto............................................9 5.3 Composio.............................................................32
Introduzindo programao com Python.......................10 5.4 Funes booleanas..................................................32
Construindo uma comunidade......................................10 5.5 Mais recursividade..................................................33
5.6 Voto de confiana (Leap of faith)...........................33
Contributor List........................................................11 5.7 Mais um exemplo....................................................34
Verso Brasileira.....................................................13 5.8 Checagem de tipos..................................................34
Captulo 1: O caminho do programa......................14 5.9 Glossrio.................................................................34
1.1 A linguagem de programao Python....................14 Captulo 6: Iterao.................................................36
1.2 O que um programa?............................................15 6.1 Reatribuies...........................................................36
1.3 O que depurao (debugging)?............................15 6.2 O comando while....................................................36
1.3.1 Erros de sintaxe.........................................15 6.3 Tabelas....................................................................37
1.3.2 Erros em tempo de execuo (runtime errors) 6.4 Tabelas de duas dimenses (ou bi-dimensionais). .38
........................................................................ ....15 6.5 Encapsulamento e generalizao............................38
1.3.3 Erros de semntica.....................................15 6.6 Mais encapsulamento..............................................38
1.3.4 Depurao experimental (Debugging)........16
1.4 Linguagens naturais e linguagens formais.............16 6.7 Variveis locais.......................................................38
1.5 O primeiro programa...............................................17 6.8 Mais generalizao..................................................39
1.6 Glossrio.................................................................17 6.9 Funes...................................................................39
6.10 Glossrio...............................................................40
Captulo 2: Variveis, expresses e comandos......18 Captulo 7: Strings...................................................41
2.1 Valores e tipos.........................................................18
2.2 Variveis.................................................................18 7.1 Um tipo de dado composto.....................................41
2.3 Nomes de variveis e palavras reservadas..............18 7.2 Comprimento..........................................................41
2.4 Comandos................................................................19 7.3 Travessia e o loop for..............................................41
2.5 Avaliando expresses..............................................19 7.4 Fatias de strings.......................................................42
2.6 Operadores e operandos..........................................19 7.5 Comparao de strings............................................42
2.7 Ordem dos operadores............................................20 7.6 Strings so imutveis..............................................42
2.8 Operaes com strings............................................20 7.7 Uma funo find (encontrar)...................................42
2.9 Composio.............................................................20 7.8 Iterando e contando.................................................43
2.11 Glossrio...............................................................20 7.9 O mdulo string......................................................43
7.10 Classificao de caracteres...................................43
Captulo 3: Funes.................................................22 7.11 Glossrio...............................................................43
3.1 Chamadas de funes..............................................22 7.11 Glossrio2.............................................................44
3.2 Converso entre tipos..............................................22 Captulo 8: Listas.....................................................45
3.3 Coero entre tipos.................................................22
3.4 Funes matemticas..............................................22 8.1 Valores da lista........................................................45
3.5 Composio.............................................................23 8.2 Acessado elementos................................................45
3.6 Adicionando novas funes....................................23 8.3 Comprimento da lista..............................................45
3.7 Definies e uso......................................................24 8.4 Membros de uma lista.............................................46
3.8 Fluxo de execuo...................................................24 8.5 Listas e laos for.....................................................46
3.9 Parmetros e argumentos........................................24 8.6 Operaes em listas.................................................46
3.10 Variveis e parmetros so locais.........................25 8.7 Fatiamento de listas.................................................46
3.11 Diagramas da pilha...............................................25 8.8 Listas so mutveis.................................................46
3.12 Funes com resultados........................................25 8.9 Remoo em lista....................................................47
3.13 Glossrio...............................................................26 8.10 Ojetos e valores.....................................................47
8.11 Apelidos................................................................47
Captulo 4: Condicionais e recursividade...............27 8.12 Clonando listas......................................................48
4.1 O operador mdulo.................................................27 8.13 Lista como parmetro...........................................48
4.2 Expresses booleanas..............................................27 8.14 Lista aninhadas......................................................48
4.3 Operadores lgicos..................................................27 8.15 Matrizes.................................................................48
4.4 Execuo condicional.............................................27 8.16 Strings e listas.......................................................49
4.5 Execuo alternativa...............................................28 8.17 Glossrio...............................................................49
4.6 Condicionais encadeados........................................28 Captulo 9: Tuplas....................................................50
4.7 Condicionais aninhados..........................................28

#3
Como pensar como um cientista da Computao usando Python

9.1 Mutabilidade e tuplas..............................................50 16.1 Herana.................................................................75


9.2 Atribuies de tupla................................................50 16.2 Uma mo de cartas................................................75
9.3 Tuplas como valores de retorno..............................50 16.3 Dando as cartas.....................................................75
9.4 Nmeros aleatrios.................................................50 16.4 Exibindo a mao.....................................................76
9.5 Lista de nmeros aleatrios....................................51 16.5 A classe JogoDeCartas..........................................76
9.6 Contando.................................................................51 16.6 Classe MaoDeMico...............................................76
9.7 Vrios intervalos.....................................................51 16.7 Classe Mico...........................................................77
9.8 Uma soluo em um s passo.................................52 16.8 Glossrio...............................................................78
9.9 Glossrio.................................................................52 Captulo 17: Listas encadeadas...............................79
Captulo 10: Dicionrios.........................................54 17.1 Referncias Embutidas.........................................79
10.1 Operaes dos Dicionrios...................................54 17.2 A classe No (Node)...............................................79
10.2 Mtodos dos Dicionrios......................................54 17.3 Listas como Colees...........................................79
10.3 Aliasing (XXX) e Copiar......................................55 17.4 Listas e Recorrncia..............................................80
10.4 Matrizes Esparsas..................................................55 17.5 Listas Infinitas.......................................................80
10.5 Hint........................................................................55 17.6 O Teorema da Ambigidade Fundamental...........80
10.6 Inteiros Longos.....................................................56 17.7 Modificando Listas...............................................81
10.7 Contando Letras....................................................56 17.8 Envoltrios e Ajudadores......................................81
10.8 Glossrio...............................................................56 17.9 A Classe ListaLigada............................................81
Captulo 11: Arquivos e excees..........................58 17.10 Invariantes...........................................................82
Arquivos e excees......................................................58 17.11 Glossrio.............................................................82
11.1 Arquivos texto.......................................................58 Captulo 18: Pilhas...................................................83
11.2 Gravando variveis...............................................59 18.1 Tipos abstratos de dados.......................................83
11.3 Diretrios...............................................................60 18.2 O TAD Pilha.........................................................83
11.4 Pickling.................................................................60 18.3 Implementando pilhas com listas de Python........83
11.5 Excees................................................................60 18.4 Empilhando e desempilhando...............................83
11.6 Glossrio...............................................................61 18.5 Usando uma pilha para avaliar expresses ps-
Captulo 12: Classes e objetos................................62 fixas...............................................................................84
12.1 Tipos compostos definidos pelo usurio..............62 18.6 Anlise sinttica....................................................84
12.2 Atributos................................................................62 18.7 Avaliando em ps-fixo..........................................84
12.3 Instncias como parmetros..................................63 18.8 Clientes de fornecedores.......................................84
12.4 O significado de "mesmo"....................................63 18.9 Glossrio...............................................................85
12.5 Retngulos.............................................................63 Captulo 19: Filas.....................................................86
12.6 Instancias como valores retornados......................64 19.1 Um TDA Fila........................................................86
12.7 Objetos so mutveis............................................64 19.2 Fila encadeada.......................................................86
12.8 Copiando...............................................................64 19.3 Caractersticas de performance.............................86
12.9 Glossrio...............................................................65 19.4 Fila encadeada aprimorada...................................86
Captulo 13: Classes e funes................................66 19.5 Fila por prioridade.................................................87
13.1 Horario..................................................................66 19.6 A classe Golfer......................................................88
13.2 Funes Puras.......................................................66 19.7 Glossrio...............................................................88
13.3 Modificadores.......................................................66 Captulo 20: rvores...............................................89
13.4 O que melhor ?...................................................67 20.1 Construindo rvores..............................................89
13.5 Desenvolvimento Prototipado versus 20.2 Percorrendo rvores..............................................89
Desenvolvimento Planejado.........................................67 20.3 rvores de expresses...........................................89
13.6 Generalizao........................................................67 20.4 Percurso de rvores...............................................90
13.7 Algoritmos.............................................................68 20.5 Construindo uma rvore de expresso..................90
13.8 Glossrio...............................................................68 20.6 Manipulando erros................................................92
Captulo 14: Classes e mtodos..............................69 20.7 A rvore dos animais............................................92
14.1 Caractersticas da orientao a objetos.................69 20.8 Glossrio...............................................................93
14.2 exibeHora (printTime)..........................................69 GNU Free Documentation License.........................94
14.3 Um outro exemplo................................................70 0. PREAMBLE ............................................................94
14.10 Glossrio.............................................................70 1. APPLICABILITY AND DEFINITIONS ................94
Captulo 15: Conjuntos de objetos..........................71 2. VERBATIM COPYING ..........................................95
15.1 Composio...........................................................71 3. COPYING IN QUANTITY .....................................95
15.2 Objetos Carta.........................................................71 4. MODIFICATIONS ..................................................95
15.3 Atributos de classe e o mtodo __str__................71 5. COMBINING DOCUMENTS .................................96
15.4 Comparando cartas................................................72 6. COLLECTIONS OF DOCUMENTS ......................96
15.5 Baralhos.................................................................72 7. AGGREGATION WITH INDEPENDENT WORKS .
15.6 Imprimindo o baralho...........................................72 96
15.7 Embaralhando.......................................................73 8. TRANSLATION ......................................................96
15.8 Removendo e distribuindo cartas.........................73 9. TERMINATION ......................................................96
15.9 Glossrio...............................................................74 10. FUTURE REVISIONS OF THIS LICENSE.........96
Capitulo 16: Herana...............................................75 How to use this License for your documents.......96

#4
Como pensar como um cientista da Computao usando Python

Foreword

By David Beazley One of the reasons why I like Python is that it


provides a really nice balance between the practical and the
As an educator, researcher, and book author, I conceptual. Since Python is interpreted, beginners can pick up
am delighted to see the completion of this book. Python is a the language and start doing neat things almost immediately
fun and extremely easy-to-use programming language that has without getting lost in the problems of compilation and
steadily gained in popularity over the last few years. linking. Furthermore, Python comes with a large library of
Developed over ten years ago by Guido van Rossum, modules that can be used to do all sorts of tasks ranging from
Pythons simple syntax and overall feel is largely derived web-programming to graphics. Having such a practical focus
from ABC, a teaching language that was developed in the is a great way to engage students and it allows them to
1980s. However, Python was also created to solve real complete significant pro jects. However, Python can also
problems and it borrows a wide variety of features from serve as an excellent foundation for introducing important
programming languages such as C++, Java, Modula-3, and computer science concepts. Since Python fully supports
Scheme. Because of this, one of Pythons most remarkable procedures and classes, students can be gradually introduced
features is its broad appeal to professional software to topics such as procedural abstraction, data structures, and
developers, scientists, researchers, artists, and educators. ob ject-oriented programmingall of which are applicable to
Despite Pythons appeal to many dierent later courses on Java or C++. Python even borrows a number
communities, you may still wonder why Python? or why of features from functional programming languages and can
teach programming with Python? Answering these questions be used to introduce concepts that would be covered in more
is no simple taskespecially when popular opinion is on the detail in courses on Scheme and Lisp.
side of more masochistic alternatives such as C++ and Java. In reading Jereys preface, I am struck by his
However, I think the most direct answer is that programming comments that Python allowed him to see a higher level of
in Python is simply a lot of fun and more productive. success and a lower level of frustration and that he was able
When I teach computer science courses, I want to move faster with better results. Although these comments
to cover important concepts in addition to making the material refer
these
to his introductory course, I sometimes use Python for
exact same reasons in advanced graduate level computer
interesting and engaging to students. Unfortunately, there is a science courses at the University of Chicago. In these courses,
tendency for introductory programming courses to focus far I am constantly faced with the daunting task of covering a lot
too much attention on mathematical abstraction and for of dicult course material in a blistering nine week quarter.
students to be come frustrated with annoying problems related Although it is certainly
to low-level details of syntax, compilation, and the and suering by using possible for me to inict a lot of pain
enforcement of seemingly arcane rules. Although such found this approach to a belanguage like C++, I have often
abstraction and formalism is important to professional when the course is aboutcounterproductive especially
software engineers and students who plan to continue their programming. I nd that usinga Python topic unrelated to just
allows me to better
study of computer science, taking such an approach in an focus on the actual topic at hand while allowing students to
introductory course mostly succeeds in making computer complete substantial class pro jects.
science boring. When I teach a course, I dont want to have a
room of uninspired students. I would much rather see them Although Python is still a young and evolving
trying to solve interesting problems by exploring dierent language, I believe that it has a bright future in education. This
ideas, taking unconventional approaches, breaking the rules, book is an important step in that direction.
and learning from their mistakes. In doing so, I dont want to
waste half of the semester trying to sort out obscure syntax David Beazley
problems, unintelligible compiler error messages, or the
several hundred ways that a program might generate a general University of Chicago
protection fault. Author of the Python Essential Reference

Foreword #5
Como pensar como um cientista da Computao usando Python

Apresentao

Traduo do captulo anterior, que foi mantido por ter sido marcado como seo invariante pelo autor original.
Como educador, pesquisador e autor de livros, regozija-me que ele oferece um equilbrio realmente bom entre o lado
ver completo este trabalho. Python uma linguagem de prtico e o lado conceitual. Sendo Python interpretado, os
programao divertida e extremamente fcil de usar que tem iniciantes podem pegar a linguagem e comear a fazer coisas
ganho forte popularidade nestes ltimos poucos anos. legais quase imediatamente sem se perderem em problemas de
Desenvolvida dez anos atrs por Guido van Rossun, a sintaxe compilao e ligao. Alm disso, Python vem com uma
simples do Python e seu sentido geral so grandemente grande biblioteca de mdulos que podem ser utilizados para
derivados do ABC, uma linguagem didtica que foi fazer todo tipo de tarefa, desde a programao para a web at
desenvolvida nos anos 80. Entretanto, Python tambm foi grficos. Com tal enfoque prtico temos uma bela maneira de
criado para solucionar problemas reais e tomou emprestado alcanar o engajamento dos alunos e permitir que eles
uma grande quantidade de caractersticas de linguagens de finalizem projetos significativos. Entretanto, Python tambm
programao como C++, Java, Modula-3 e Scheme. Por causa pode servir de excelente embasamento para a introduo de
disso, uma das mais notveis caractersticas do Python o conceitos importantes em cincia da computao. J que
grande apelo que tem junto a desenvolvedores profissionais de Python suporta plenamente procedimentos (procedures) e
software, cientistas, pesquisadores, artistas e educadores. classes, os alunos podem ser gradualmente introduzidos a
tpicos como abstrao procedural, estruturas de dados, e
A Despeito deste apelo do Python junto s mais programao orientada a objetos ? todos aplicveis em cursos
variadas comunidades, voc pode ainda estar pensando ?por posteriores de Java ou C++. Python ainda toma emprestado
que Python?? ou ?por que ensinar programao com certas caractersticas de linguagens de programao funcionais
Python??. Responder estas perguntas no uma tarefa fcil ? e pode ser usado para introduzir conceitos cujos detalhes
especialmente se a opinio pblica est do lado de alternativas poderiam ser aprofundados em cursos de Scheme e Lisp.
mais masoquistas como C++ e Java. Entretanto, eu acho que a
resposta mais direta que programar com Python um Lendo o prefcio de Jeffrey, fiquei
bocado divertido e mais produtivo. impressionado com seu comentrio de que Python o fez ver
um ?maior nvel de sucesso e um menor nvel de frustrao? o
Quando ministro cursos de cincias da que lhe permitiu ?progredir mais depressa com resultados
computao, o que desejo cobrir conceitos importantes alm melhores?. Embora estes comentrios refiram-se aos seus
de tornar a matria interessante e os alunos participativos. cursos introdutrios, eu s vezes uso Python exatamente pelas
Infelizmente, existe uma tendncia entre os cursos mesmas razes em cursos avanados de ps-graduao em
introdutrios de programao a focar ateno demais em cincia da computao na Universidade de Chicago. Nestes
abstraes matemticas, e de frustrao entre os alunos com cursos, enfrento constantemente a assustadora tarefa de cobrir
problemas enfadonhos e inoportunos relacionados a detalhes muitos tpicos difceis em um rapidssimo trimestre de nove
de sintaxe em baixo nvel, compilao e a imposio de regras semanas. Embora me seja possvel inflingir um bocado de dor
que aparentemente s um expert pode compreender. Embora e sofrimento pelo uso de uma linguagem como C++, tenho
alguma abstrao e formalismo sejam importantes para percebido muitas vezes que este enfoque contraproducente ?
engenheiros profissionais de software e estudantes que especialmente quando o curso sobre um tpico no
planejam continuar seus estudos em cincias da computao, relacionado apenas com ?programar?. Acho que usar Python
escolher tal abordagem em um curso introdutrio faz da me permite um melhor foco no tpico em questo, enquanto
cincia da computao algo entediante. Quando ministro um permite que os alunos completem projetos substanciais em
curso, no desejo uma sala cheia de alunos sem inspirao. classe.
Em vez disso, preferiria muito mais v-los tentando solucionar
problemas interessantes explorando idias diferentes, Embora Python seja ainda uma linguagem
trilhando caminhos no convencionais, quebrando regras, e jovem e em evoluo, acredito que tem um futuro brilhante
aprendendo a partir de seus erros. Fazendo assim, no em educao. Este livro um passo importante nessa direo.
pretendo desperdiar metade de um semestre tentando explicar
problemas obscuros de sintaxe, mensagens ininteligveis de David Beazley
compiladores ou as vrias centenas de maneiras pelas quais Universidade de Chicago
um programa pode gerar uma falha geral de proteo.
Uma das razes pelas quais eu gosto de Python Autor de Python Essencial Reference

Apresentao #6
Como pensar como um cientista da Computao usando Python

Preface

By Je Elkner computer science classes the following year, the most pressing
problem was the lack of an available textbook.
This book owes its existence to the
collaboration made possible by the Internet and the free Free content came to the rescue. Earlier in the
software movement. Its three authorsa college professor, a year, Richard Stallman had introduced me to Allen Downey.
high school teacher, and a professional programmerhave yet Both of us had written to Richard expressing an interest in
to meet face to face, but we have been able to work closely developing free educational content. Allen had already written
together and have been aided by many wonderful folks who a rst-year computer science textbook, How to Think Like a
have donated their time and energy to helping make this book Computer Scientist. When I read this book, I knew
better. immediately that I wanted to use it in my class. It was the
clearest and most helpful computer science text I had seen. It
We think this book is a testament to the benets emphasized the processes of thought involved in
and future possibilities of this kind of collaboration, the programming rather than the features of a particular language.
framework for which has been put in place by Richard Reading it immediately made me a better teacher.
Stallman and the Free Software Foundation.
How to Think Like a Computer Scientist was not
just an excellent book, but it had been released under a GNU
public license, which meant it could be used freely and
How and why I came to use Python modied to meet the needs of its user. Once I decided to use
Python, it occurred to me that I could translate Allens original
In 1999, the College Boards Advanced Placement (AP) Java version of the book into the new language. While I would
Computer Science exam was given in C++ for the rst time. not have been able to write a textbook on my own, having
As in many high schools throughout the country, the decision Allens book to work from made it possible for me to do so, at
to change languages had a direct impact on the computer the same time demonstrating that the cooperative development
science curriculum at Yorktown High School in Arlington, model used so well in software could also work for
Virginia, where I teach. Up to this point, Pascal was the educational content.
language of instruction in both our rst-year and AP courses.
In keeping with past practice of giving students two years of Working on this book for the last two years has
exposure to the same language, we made the decision to been rewarding for both my students and me, and my students
switch to C++ in the rst-year course for the 1997-98 school played a big part in the process. Since I could make instant
year so that we would be in step with the College Boards changes whenever someone found a spelling error or dicult
change for the AP course the following year. passage, I encouraged them to look for mistakes in the book
by giving them a bonus point each time they made a
Two years later, I was convinced that C++ was suggestion that resulted in a change in the text. This had the
a poor choice to use for introducing students to computer double benet of encouraging them to read the text more
science. While it is certainly a very powerful programming carefully and of getting the text thoroughly reviewed by its
language, it is also an extremely dicult language to learn and most important critics, students using it to learn computer
teach. I found myself constantly ghting with C++s dicult science.
syntax and multiple ways of doing things, and I was losing
many students unnecessarily as a result. Convinced there had For the second half of the book on ob ject-
to be a better language choice for our rst-year class, I went oriented programming, I knew that someone with more real
looking for an alternative to C++. programming experience than I had would be needed to do it
right. The book sat in an unnished state for the better part of
I needed a language that would run on the a year until the free software community once again provided
machines in our Linux lab as well as on the Windows and the needed means for its completion.
Macintosh platforms most students have at home. I wanted it
to be free and available electronically, so that students could I received an email from Chris Meyers
use it at home regardless of their income. I wanted a language expressing interest in the book. Chris is a professional
that was used by professional programmers, and one that had programmer who started teaching a programming course last
an active developer community around it. It had to support year using Python at Lane Community College in Eugene,
both procedural and ob ject-oriented programming. And most Oregon. The prospect of teaching the course had led Chris to
importantly, it had to be easy to learn and teach. When I the book, and he started helping out with it immediately. By
investigated the choices with these goals in mind, Python the end of the school year he had created a companion project
stood out as the best candidate for the job. on our Website at http://www.ibiblio.org/obp called Python
for Fun and was working with some of my most advanced
I asked one of Yorktowns talented students, students as a master teacher, guiding them beyond where I
Matt Ahrens, to give Python a try. In two months he not only could take them.
learned the language but wrote an application called pyTicket
that enabled our sta to report technology problems via the
Web. I knew that Matt could not have nished an application
of that scale in so short a time in C++, and this Intro ducing programming with Python
accomplishment, combined with Matts positive assessment of
Python, suggested that Python was the solution I was looking The process of translating and using How to Think Like a
for. Computer Scientist for the past two years has conrmed
Pythons suitability for teaching beginning students. Python
greatly simplies programming examples and makes
important programming ideas easier to teach.
Finding a textb o ok
The rst example from the text illustrates this
Having decided to use Python in both of my introductory point. It is the traditional hello, world program, which in the

Preface #7
Como pensar como um cientista da Computao usando Python

C++ version of the book looks like this: they learned in their math courses. I had much less diculty
teaching variables this year than I did in the past, and I spent
#include <iostream.h> less time helping students with problems using them.
void main()
{
Another example of how Python aids in the
teaching and learning of programming is in its syntax for
cout << "Hello, world." << endl; functions. My students have always had a great deal of
} diculty understanding functions. The main problem centers
in the Python version it becomes: around the dierence between a function denition and a
function call, and the related distinction between a parameter
print "Hello, World!" and an argument. Python comes to the rescue with syntax that
Even though this is a trivial example, the is nothing short of beautiful. Function denitions begin with
advantages of Python stand out. Yorktowns Computer the keyword def, so I simply tell my students, When you
Science I course has no prerequisites, so many of the students dene a function, begin with def, followed by the name of the
seeing this example are looking at their rst program. Some of function that you are dening; when you call a function,
them are undoubtedly a little nervous, having heard that simply call (type) out its name. Parameters go with
computer programming is dicult to learn. The C++ version denitions; arguments go with calls. There are no return types,
has always forced me to choose between two unsatisfying parameter types, or reference and value parameters to get in
options: either to explain the #include, void main(), {, and } the way, so I am now able to teach functions in less than half
statements and risk confusing or intimidating some of the the time that it previously took me, with better
students right at the start, or to tell them, Just dont worry comprehension.
about all of that stu now; we will talk about it later, and risk Using Python has improved the eectiveness of
the same thing. The educational ob jectives at this point in theour computer science program for all students. I see a higher
course are to introduce students to the idea of a programming general level of success and a lower level of frustration than I
statement and to get them to write their rst program, thereby experienced during the two years I taught C++. I move faster
introducing them to the programming environment. The with better results. More students leave the course with the
Python program has exactly what is needed to do these things, ability to create meaningful programs and with the positive
and nothing more. attitude toward the experience of programming that this
Comparing the explanatory text of the program engenders.
in each version of the book further illustrates what this means
to the beginning student. There are thirteen paragraphs of
explanation of Hello, world! in the C++ version; in the Building a community
Python version, there are only two. More importantly, the
missing eleven paragraphs do not deal with the big ideas in
computer programming but with the minutia of C++ syntax. I I have received email from all over the globe from people
found this same thing happening throughout the book. Whole using this book to learn or to teach programming. A user
paragraphs simply disappear from the Python version of the community has begun to emerge, and many people have been
text because Pythons much clearer syntax renders them contributing to the pro ject by sending in materials for the
unnecessary. companion Website at http://www.thinkpython.com.
Using a very high-level language like Python With the publication of the book in print form, I
allows a teacher to postpone talking about low-level details of expect the growth in the user community to continue and
the machine until students have the background that they need accelerate. The emergence of this user community and the
to better make sense of the details. It thus creates the ability to possibility it suggests for similar collaboration among
put rst things rst pedagogically. One of the best examples educators have been the most exciting parts of working on this
of this is the way in which Python handles variables. In C++ a pro ject for me. By working together, we can increase the
variable is a name for a place that holds a thing. Variables quality of materials available for our use and save valuable
have to be declared with types at least in part because the size time. I invite you to join our community and look forward to
of the place to which they refer needs to be predetermined. hearing from you. Please write to the authors at
Thus, the idea of a variable is bound up with the hardware of feedback@thinkpython.com.
the machine. The powerful and fundamental concept of a
variable is already dicult enough for beginning students (in Jerey Elkner
both computer science and algebra). Bytes and addresses do Yorktown High School
not help the matter. In Python a variable is a name that refers
to a thing. This is a far more intuitive concept for beginning Arlington, Virginia
students and is much closer to the meaning of variable that

Preface #8
Como pensar como um cientista da Computao usando Python

Prefcio

Traduo do captulo anterior, que foi mantido por ter sido marcado como seo invariante pelo autor original.
Este livro deve sua existncia colaborao tornada possvel
pela Internet e pelo movimento do software livre. Seus trs Encontrando um livro texto
autores ? um professor universitrio, um secundrio e um
programador profissional ? ainda no se encontraram Tendo decidido usar Python em ambas as minhas classes
pessoalmente, mas temos podido trabalhar bem de perto e introdutrias de cincia da computao do ano seguinte, o
temos sido ajudados por muitos colegas maravilhosos que tm problema mais urgente era a falta de um livro texto disponvel.
dedicado seu tempo e energia a ajudar a fazer deste um livro
cada vez melhor. O contedo livre veio em socorro.
Anteriormente naquele ano, Richard Stallman tinha me
Achamos que este livro um testemunho dos apresentado a Allen Downey. Ambos havamos escrito a
benefcios e possibilidades futuras deste tipo de colaborao, Richard expressando interesse em desenvolver contedo
cujo modelo tem sido colocado por Richard Stallman e pela educacional livre. Allen j tinha escrito um livro texto para o
Free Software Foundation. primeiro ano de cincia da computao, How to Think Like a
Computer Scientist. Quando li este livro, soube imediatamente
que queria utiliz-lo nas minhas aulas. Era o texto mais claro e
proveitoso em cincia da computao que eu tinha visto. Ele
Como e porque eu vim a usar Python enfatizava o processo de reflexo envolvido em programao
em vez de caractersticas de uma linguagem em particular. L-
Em 1999, o Exame de Colocao Avanada em Cincia da lo fez de mim imediatamente um melhor professor.
Computao da Comisso de Faculdades (College Board?s
Advanced Placement (AP) Computer Science) foi aplicado em O How to Think Like a Computer Scientist era
C++ pela primeira vez. Como em muitas escolas secundrias no s um excelente livro, como tambm fora lanado sob
atravs do pas, a deciso de mudar linguagens teve um uma licena pblica GNU, o que significava que ele poderia
impacto direto no currculo de cincia da computao na ser usado livremente e modificado para atender as
Yorktown High School em Arlington, Virginia, onde leciono. necessidades de seu usurio. Uma vez que eu havia decidido
At ento, Pascal era a linguagem didtica para nossos cursos usar Python, me ocorreu que eu poderia traduzir a verso
de primeiro ano e avanado. Mantendo a prtica corrente de original do livro de Allen do Java para a nova linguagem.
dar aos estudantes dois anos de exposio mesma Apesar de no estar capacitado para escrever eu mesmo um
linguagem, tomamos a deciso de mudar para C++ no curso livro texto, tendo o livro de Allen a partir do qual trabalhar
de primeiro ano para o ano letivo de 1997-98 de modo que tornou possvel para mim faz-lo, ao mesmo tempo
estaramos em sincronismo com a mudana da Comisso de demonstrando que o modelo de desenvolvimento cooperativo
Faculdades (College Board?s) em relao ao curso avanado to bem utilizado em software poderia tambm funcionar para
para o ano seguinte. contedo educacional.
Dois anos depois, eu estava convencido que Trabalhar neste livro pelos ltimos dois anos
C++ foi uma escolha infeliz para introduzir os alunos em tem sido recompensador para mim e meus alunos, e eles
cincia da computao. Ao mesmo tempo em que tiveram um grande papel neste processo. A partir do momento
certamente uma linguagem de programao muito poderosa, em que eu podia fazer mudanas instantneas assim que
tambm uma linguagem extremamente difcil de aprender e algum encontrasse um erro ortogrfico ou um trecho difcil,
de ensinar. Eu me encontrava constantemente lutando com a eu os encorajei a procurar por erros no livro, dando a eles
sintaxe difcil do C++ e as mltiplas maneiras de fazer a pontos de bonificao cada vez que eles fizessem uma
mesma coisa, e estava, como resultado, perdendo muitos sugesto que resultasse em uma mudana no texto. Isto teve o
alunos desnecessariamente. Convencido de que deveria existir duplo benefcio de encoraj-los a ler o texto mais
uma linguagem melhor para a nossa classe de primeiro ano, cuidadosamente e de ter o texto totalmente revisado por seus
fui procurar por uma alternativa ao C++. crticos mais importantes: alunos utilizando-o para aprender
cincia da computao.
Eu precisava de uma linguagem que pudesse
rodar nas mquinas em nosso laboratrio Linux bem como nas Para a segunda metade do livro, sobre
plataformas Windows e Macintosh que a maioria dos alunos programao orientada a objetos, eu sabia que seria preciso
tinha em casa. Eu precisava que ela fosse gratuita e disponvel algum com uma maior experincia do que a minha em
eletronicamente, assim os alunos poderiam utiliz-la em casa programao real para faz-lo corretamente. O livro esteve em
independentemente de suas rendas. Eu queria uma linguagem estado inacabado por quase um ano at que a comunidade de
que fosse utilizada por programadores profissionais, e que software livre providenciasse mais uma vez os meios
tivesse uma comunidade de desenvolvimento ativa em torno necessrios para sua concluso.
dela. Ela teria que suportar ambas, programao procedural e Eu recebi um e-mail de Chris Meyers mostrando
orientada a objetos. E, mais importante, deveria ser fcil de interesse no livro.
aprender e de ensinar. Quando considerei as alternativas tendo comeou a dar umChris um programador profissional que
curso de programao no ano anterior
em mente aquelas metas, Python sobressaiu-se como a melhor usando Python no Lane Community College em Eugene,
candidata para a tarefa. Oregon. A perspectiva de dar aquele curso ligou Chris ao
Pedi para um dos talentosos estudantes de livro, e ele comeou a ajudar o trabalho imediatamente. Pelo
Yorktown, Matt Ahrens, que experimentasse Python. Em dois final do ano letivo ele tinha criado um projeto colaborativo em
meses ele no s aprendeu a linguagem como tambm nosso Website em http://www.ibiblio.org/obp chamado
escreveu uma aplicao chamada pyTicket que possibilitou Python for Fun e estava trabalhando com alguns dos meus
nossa equipe reportar problemas de tecnologia pela Web. Eu alunos mais avanados como um guru, guiando-os alm de
sabia que Matt no poderia ter finalizado uma aplicao onde eu poderia lev-los.
daquele porte em perodo to curto em C++, esta realizao,
combinada com a avaliao positiva do Python dada por Matt,
sugeriam que Python era a soluo que eu estava procurando.

Prefcio #9
Como pensar como um cientista da Computao usando Python

poderoso e fundamental de varivel j bastante difcil para o


Introduzindo programao com Python aluno iniciante (em ambas, cincia da computao e lgebra).
Bytes e endereos no ajudam neste caso. Em Python uma
O processo de traduzir e utilizar How to Think Like a varivel um nome que se refere a uma coisa. Este um
Computer Scientist pelos ltimos dois anos tem confirmado a conceito muito mais intuitivo para alunos iniciantes e est
convenincia de Python no ensino de alunos iniciantes. muito mais prximo do significado de ?varivel? que eles
Python simplifica tremendamente os programas exemplo e aprenderam em seus cursos de matemtica. Eu tive muito
torna idias importantes de programao mais fceis de menos dificuldade em ensinar variveis este ano do que tive
ensinar. no passado, e gastei menos tempo ajudando aos alunos com
problemas no uso delas.
O primeiro exemplo do texto ilustra este ponto.
o tradicional programa ?Al mundo?, do qual na verso Um outro exemplo de como Python ajuda no
C++ do livro se parece com isto: ensino e aprendizagem de programao em sua sintaxe para
funo. Meus alunos tm sempre tido grande dificuldade na
#include <iostream.h> compreenso de funes. O problema principal gira em torno
da diferena entre a definio de uma funo e a chamada de
void main() uma funo, e a distino relacionada entre um parmetro e
um argumento. Python vem em auxlio com uma sintaxe no
{ apenas curta quanto bela. As definies de funo comeam
cout << "Al, mundo." << endl; com def, ento eu simplesmente digo aos meus alunos ?
} Quando voc define uma funo, comece com def, seguido do
Na verso Python, ele se transforma em: nome da funo que voc est definindo; quando voc chama
uma funo, simplesmente chame-a digitando o nome dela?.
print "Al, Mundo!" Parmetros ficam nas definies; argumentos vo com as
Mesmo sendo um exemplo trivial, as vantagens chamadas. No existem tipos de retorno, tipos de parmetro
do Python saltam aos olhos. O curso de Cincia da ou passagem de parmetros por valor ou por referncia no
Computao I que ministro em Yorktown no tem pr- meio do caminho, permitindo-me ensinar funes em menos
requisitos, assim, muitos dos alunos que veem esse exemplo da metade do tempo que isto me tomava anteriormente, com
esto olhando para o seu primeiro programa. Alguns deles uma melhor compreenso.
esto indubitavelmente nervosos, por j terem ouvido falar
que programao de computadores difcil de aprender. A efetividade deAnosso utilizao do Python tem melhorado a
programa em cincia da computao para
verso C++ tem sempre me forado a escolher entre duas todos os estudantes. Eu
opes insatisfatrias: ou explicar os comandos #include, void mais alto e um nvel vejo um nvel geral de sucesso muito
mais baixo de frustrao do que
main(), {, e } e arriscar confundir ou intimidar alguns dos experimentei durante os dois anos
alunos logo assim que iniciam, ou dizer a eles ?No se avano mais rpido com melhores em que ensinei C++. Eu
resultados. Mais alunos
preocupem com todas estas coisas agora; falaremos sobre elas deixam o curso com a habilidade de criar programas
mais tarde?, e correr o mesmo risco. O objetivo educacional significativos e com uma atitude positiva em relao a
neste ponto do curso introduzir os alunos idia de experincia de programao que isso traz.
comando em programao e v-los escrever seu primeiro
programa, deste modo introduzindo-os ao ambiente de
programao. O programa em Python tem exatamente o que
necessrio para conseguir isto, e nada mais. Construindo uma comunidade
Comparar o texto explicativo do programa em
cada verso do livro ilustra ainda mais o que significa para o Tenho recebido e-mails de todo o planeta de pessoas
aluno iniciante. Existem treze pargrafos de explicao do ? utilizando este livro para aprender ou ensinar programao.
Al, mundo!? na verso C++; na verso Python existem Uma comunidade de usurios tem comeado a emergir e
apenas dois. Mais importante, os onze pargrafos perdidos no muitas pessoas tm contribudo com o projeto enviando seus
se ocupam das ?idias chave? da programao de materiais para o Website cooperativo em:
computadores, mas com a mincia da sintaxe C++. Vejo a
mesma coisa acontecendo atravs de todo o livro. Pargrafos http://www.thinkpython.com
inteiros simplesmente desaparecem da verso do texto para Com a publicao do livro em formato
Python porque a sintaxe muito mais clara do Python os torna impresso, minha expectativa quanto ao crescimento da
desnecessrios. comunidade de usurios que ela seja contnua e acelerada. O
Utilizar uma linguagem de to alto nvel como surgimento desta comunidade de usurios e a possibilidade
Python, permite ao professor deixar para falar mais tarde que sugere de colaborao semelhante entre educadores tem
sobre os nveis mais baixos, prximos mquina, quando os sido para mim a parte mais excitante do trabalho neste projeto.
alunos j tero a experincia necessria para ver com mais Trabalhando juntos, podemos aumentar a qualidade do
sentido os detalhes. Desta maneira podemos ?por em primeiro material disponvel para o nosso uso e poupar tempo valioso.
lugar as primeiras coisas?, pedagogicamente. Um dos Eu convido voc a se juntar a nossa comunidade e espero
melhores exemplos disto a maneira com que Python lida ouvir algo de voc. Por favor, escreva para os autores em
com variveis. Em C++ uma varivel um nome para um feedback@thinkpython.com.
lugar que guarda uma coisa. Variveis tm de ser declaradas Jeffrey Elkner
com seu tipo pelo menos em parte por que o tamanho do lugar
a que se referem precisa ser predeterminado. Assim, a idia de Yorktown High School
varivel fica amarrada ao hardware da mquina. O conceito
Arlington, Virginia

Prefcio #10
Como pensar como um cientista da Computao usando Python

Contributor List

To paraphrase the philosophy of the Free Software unconsciously in Chapter 1 needed to be changed
Foundation, this book is free like free speech, but not to subconsciously.
necessarily free like free pizza. It came about because of a
collaboration that would not have been possible without the Chris McAloon sent in several corrections to
GNU Free Documentation License. So we thank the Free Sections 3.9 and 3.10.
Software Foundation for developing this license and, of Matthew J. Moelter has been a long-time contributor
course, making it available to us. who sent in numerous corrections and suggestions to
We also thank the more than 100 sharp-eyed the book.
and thoughtful readers who have sent us suggestions and Simon Dicon Montford reported a missing function
corrections over the past few years. In the spirit of free denition and several typos in Chapter 3. He also
software, we decided to express our gratitude in the form of a found errors in the increment function in Chapter 13.
contributor list. Unfortunately, this list is not complete, but we
are doing our best to keep it up to date. John Ouzts corrected the denition of return value
If you have a chance to look through the list, in Chapter 3.
you should realize that each person here has spared you and Kevin Parks sent in valuable comments and
all subsequent readers from the confusion of a technical error suggestions as to how to improve the distribution of
or a less-than-transparent explanation, just by sending us a the book.
note.
David Pool sent in a typo in the glossary of Chapter
Impossible as it may seem after so many 1, as well as kind words of encouragement.
corrections, there may still be errors in this book. If you
should stumble across one, please check the online version of Michael Schmitt sent in a correction to the chapter on
the book at http://thinkpython.com, which is the most up-to- les and exceptions.
date version. If the error has not been corrected, please take a
minute to send us email at feedback@thinkpython.com. If we Robin Shaw pointed out an error in Section 13.1,
make a change due to your suggestion, you will appear in the where the printTime function was used in an example
next version of the contributor list (unless you ask to be without being dened.
omitted). Thank you! Paul Sleigh found an error in Chapter 7 and a bug in
Lloyd Hugh Allen sent in a correction to Section 8.4. Jonah Cohens Perlscript that generates HTML from
LaTeX.
Yvon Boulianne sent in a correction of a semantic
error in Chapter 5. Craig T. Snydal is testing the text in a course at Drew
University. He has contributed several valuable
Fred Bremmer submitted a correction in Section 2.1. suggestions and corrections.
Jonah Cohen wrote the Perl scripts to convert the Ian Thomas and his students are using the text in a
LaTeX source for this book into beautiful HTML. programming course. They are the rst ones to test
the chapters in the latter half of the book, and they
Michael Conlon sent in a grammar correction in have made numerous corrections and suggestions.
Chapter 2 and an improvement in style in Chapter 1,
and he initiated discussion on the technical aspects of Keith Verheyden sent in a correction in Chapter 3.
interpreters.
Peter Winstanley let us know about a longstanding
Benoit Girard sent in a correction to a humorous error in our Latin in Chapter 3.
mistake in Section 5.6.
Chris Wrobel made corrections to the code in the
Courtney Gleason and Katherine Smith wrote chapter on le I/O and exceptions.
horsebet.py, which was used as a case study in an
earlier version of the book. Their program can now Moshe Zadka has made invaluable contributions to
be found on the website. this pro ject. In addition to writing the rst draft of
the chapter on Dictionaries, he provided continual
Lee Harr submitted more corrections than we have guidance in the early stages of the book.
room to list here, and indeed he should be listed as
one of the principal editors of the text. Christoph Zwerschke sent several corrections and
pedagogic suggestions, and explained the dierence
James Kaylin is a student using the text. He has between gleich and selbe.
submitted numerous corrections.
James Mayer sent us a whole slew of spelling and
David Kershaw xed the broken catTwice function in typographical errors, including two in the contributor
Section 3.10. list.
Eddie Lam has sent in numerous corrections to Hayden McAfee caught a potentially confusing
Chapters 1, 2, and 3. He also xed the Makele so inconsistency between two examples.
that it creates an index the rst time it is run and
helped us set up a versioning scheme. Angel Arnal is part of an international team of
translators working on the Spanish version of the
Man-Yong Lee sent in a correction to the example text. He has also found several errors in the English
code in Section 2.4. version.
David Mayo pointed out that the word Tauhidul Hoque and Lex Berezhny created the

Contributor List #11


Como pensar como um cientista da Computao usando Python

illustrations in Chapter 1 and improved many of the Ben Logan sent in a number of typos and problems
other illustrations. with translating the book into HTML.
Dr. Michele Alzetta caught an error in Chapter 8 and Jason Armstrong saw the missing word in Chapter 2.
sent some interesting pedagogic comments and
suggestions about Fibonacci and Old Maid. Louis Cordier noticed a spot in Chapter 16 where the
code didnt match the text.
Andy Mitchell caught a typo in Chapter 1 and a
broken example in Chapter 2. Brian Cain suggested several clarications in
Chapters 2 and 3.
Kalin Harvey suggested a clarication in Chapter 7
and caught some typos. Rob Black sent in a passel of corrections, including
some changes for Python 2.2.
Christopher P. Smith caught several typos and is
helping us prepare to update the book for Python 2.2. Jean-Philippe Rey at Ecole Centrale Paris sent a
number of patches, including some updates for
David Hutchins caught a typo in the Foreword. Python 2.2 and other thoughtful improvements.
Gregor Lingl is teaching Python at a high school in Jason Mader at George Washington University made
Vienna, Austria. He is working on a German a number of useful suggestions and corrections.
translation of the book, and he caught a couple of bad
errors in Chapter 5. Jan Gundtofte-Bruun reminded us that a error is an
error.
Julie Peters caught a typo in the Preface.
Abel David and Alexis Dinno reminded us that the
Florin Oprina sent in an improvement in makeTime, plural of matrix is matrices, not matrixes. This
a correction in printTime, and a nice typo. error was in the book for years, but two readers with
the same initials reported it on the same day. Weird.
D. J. Webre suggested a clarication in Chapter 3.
Charles Thayer encouraged us to get rid of the semi-
Ken found a stful of errors in Chapters 8, 9 and 11. colons we had put at the ends of some statements and
Ivo Wever caught a typo in Chapter 5 and suggested to clean up our use of argument and parameter.
a clarication in Chapter 3. Roger Sperberg pointed out a twisted piece of logic
Curtis Yanko suggested a clarication in Chapter 2. in Chapter 3.

Contributor List #12


Como pensar como um cientista da Computao usando Python

Verso Brasileira

A verso traduzida para Portugus Brasileiro foi feita pela


equipe do site http://pensarpython.incubadora.fapesp.br,
abaixo relacionada:
Adrovane Kade (adrovane)
Alex Augusto da Luz dos Santos (nowayx)
Claudio Fernando Berrondo Soares (cl-audio)
Daniel Rosa Franzini (danielt3)
Douglas Soares de Andrade (dsa)
Fabio Rizzo Matos (fabrizmat)
Imre Simon (imres)
Joao Paulo Liberato (jpliberato)
Joo Paulo Gomes Vanzuita (taken)
Julio Monteiro (jmonteiro)
Luciano Ramalho (luciano)
Marcus Pereira (mvmendes)
Mario O. de Menezes (modemene)
Paulo J. S. Silva (pjssilva)
Victor Rafael da Paixo Lopes (reije)
marta mello (martamello)
vitor gurgel (vitor_gurgel)
Esta diagramao foi feita por Crlisson
Galdino <bardo@castelodotempo.com>, com algumas
modificaes visando a facilitar a publicao em duas colunas.
Alguns comentrios de depurao feitos pela equipe de
traduo foram omitidos.

Verso Brasileira #13


Como pensar como um cientista da Computao usando Python

Captulo 1: O caminho do programa

O objetivo deste livro ensinar o leitor a pensar como um


cientista da computao. Essa maneira de pensar combina
algumas das melhores caractersticas da matemtica, da
engenharia e das cincias naturais. Como os matemticos, os
cientistas da computao usam linguagens formais para
representar idias (especificamente, computaes). Como os
engenheiros, eles projetam coisas, montando sistemas a partir
de componentes e avaliando as vantagens e desvantagens de
diferentes alternativas. Como os cientistas naturais, eles O compilador l o programa e o traduz
observam o comportamento de sistemas complexos, completamente antes que o programa comece a rodar. Neste
formulam hipteses e testam previses. caso, o programa escrito em linguagem de alto nvel
A habilidade mais importante de um cientista da chamado de cdigo fonte, e o programa traduzido chamado
computao a soluo de problemas. Soluo de problemas compilado,objeto
de cdigo ou executvel. Uma vez que um programa
a habilidade de formular questes, pensar criativamente precise de nova voc pode execut-lo repetidamente, sem que
sobre solues possveis e expressar uma soluo de forma traduo.
clara e precisa. Ocorre que aprender a programar uma
excelente oportunidade de praticar a habilidade da soluo de
problemas. por isso que este captulo se chama "O caminho
do programa".
Em certo nvel, voc estar aprendendo a
programar, habilidade que til em si mesma. Em outro
nvel, voc usar a programao como um meio para atingir Python considerada uma linguagem
um objetivo. medida que voc for avanando na leitura, interpretada, porque os programas em Python so executados
esse objetivo ficar mais claro. por um interpretador. Existem duas maneiras de usar o
interpretador: no modo de linha de comando e no modo de
script. No modo de linha de comando, voc digita programas
em Python e o interpretador mostra o resultado:
1.1 A linguagem de programao Python
$ python
Python 2.4.3 (#2, Oct 6 2006, 07:49:22)
Python a linguagem de programao que voc vai estudar
neste livro. Python um exemplo de linguagem de [GCC 4.0.3 (Ubuntu 4.0.3-1ubuntu5)] on linux2
programao de alto nvel; outras linguagens de alto nvel Type "help", "copyright", "credits" or "license" for
de que voc j pode ter ouvido falar so C, C++, Perl e Java. more information.
>>> print 1 + 1
Como voc pode deduzir a partir da expresso 2
"linguagem de alto nvel", tambm existem as "linguagens de
baixo nvel", s vezes chamadas de "linguagens de mquina" A primeira linha deste exemplo o comando
ou "linguagem assembly" ("linguagens de montagem"). Dito que inicia o interpretador Python. As trs linhas seguintes so
de maneira simples, o computador s consegue executar mensagens do interpretador. A quarta linha comea com >>>,
programas escritos em linguagens de baixo nvel. Deste que o sinal usado pelo interpretador para indicar que ele est
modo, programas escritos em linguagens de alto nvel pronto. No exemplo anterior, digitamos print 1 + 1 e o
precisam ser processados antes que possam rodar. Esse interpretador respondeu 2.
processamento extra toma algum tempo, o que uma pequena Voc tambm pode escrever um programa em
desvantagem em relao s linguagens de alto nvel. um arquivo e usar o interpretador para executar o contedo
Mas as vantagens so enormes. Primeiro, desse arquivo. Um arquivo como este chamado de script.
muito mais fcil programar em uma linguagem de alto nvel. Por exemplo, usamos um editor de texto para criar um
mais rpido escrever programas em uma linguagem de alto arquivo chamado leticia.py com o seguinte contedo:
nvel; eles so mais curtos e mais fceis de ler e mais
provvel que estejam corretos. Segundo, as linguagens de alto print 1 + 1
nvel so portveis, o que significa que podem rodar em Por conveno, arquivos que contenham
diferentes tipos de computador, com pouca ou nenhuma programas em Python tm nomes que terminam com .py.
modificao. Programas em baixo nvel s podem rodar em
um nico tipo de computador e precisam ser re-escritos para Para executar o programa, temos de dizer ao
rodar em outro tipo. interpretador o nome do script:
Devido a essas vantagens, quase todos os $ python leticia.py
programas so escritos em linguagens de alto nvel. As de 2
baixo nvel so utilizadas somente para umas poucas Em outros ambientes de desenvolvimento, os
aplicaes especializadas. detalhes da execuo de programas podem ser diferentes.
Alm disso, a maioria dos programas so mais interessantes
Dois tipos de programas processam linguagens do que esse...
de alto nvel, traduzindo-as em linguagens de baixo nvel:
interpretadores e compiladores. O interpretador l um A maioria dos exemplos neste livro so
programa escrito em linguagem de alto nvel e o executa, ou executados a partir da linha de comando. Trabalhar com a
seja, faz o que o programa diz. Ele processa o programa um linha de comando conveniente no desenvolvimento e
pouco de cada vez, alternadamente: ora lendo algumas linhas, testagem de programas, porque voc pode digitar os
ora realizando computaes. programas e execut-los imediatamente. Uma vez que voc

Captulo 1: O caminho do programa #14


Como pensar como um cientista da Computao usando Python

tem um programa que funciona, deve guard-lo em um script, lugar, o interpretador Python vai exibir uma mensagem de
de forma a poder execut-lo ou modific-lo no futuro. erro e vai terminar - e o programa no vai rodar. Durante as
primeiras semanas da sua carreira como programador, voc
provavelmente perder um bocado de tempo procurando erros
de sintaxe. Conforme for ganhando experincia, entretanto,
1.2 O que um programa? cometer menos erros e os localizar mais rpido.
Um programa uma seqncia de instrues que 1.3.2 Erros em tempo de execuo (runtime errors)
especificam como executar uma computao. A computao
pode ser algo matemtico, como solucionar um sistema de O segundo tipo de erro o erro de runtime, ou erro em tempo
equaes ou encontrar as razes de um polinmio, mas de execuo, assim chamado porque s aparece quando voc
tambm pode ser uma computao simblica, como buscar e roda o programa. Esses erros so tambm conhecidos como
substituir uma palavra em um documento ou (estranhamente) excees, porque normalmente indicam que alguma coisa
compilar um programa. excepcional (e ruim) aconteceu.
Os detalhes so diferentes em diferentes Erros de runtime so raros nos programas
linguagens, mas algumas instrues bsicas aparecem em simples que voc vai ver nos primeiros captulos - ento, vai
praticamente todas as linguagens: demorar um pouco at voc se deparar com um erro desse
tipo.
entrar Pegar dados do teclado, de um arquivo
ou de algum outro dispositivo.
1.3.3 Erros de semntica
sair Mostrar dados na tela ou enviar dados
para um arquivo ou outro dispositivo. O terceiro tipo de erro o erro de semntica (mais
comumente chamado erro de lgica). Mesmo que o seu
calcular Executar operaes matemticas programa tenha um erro de semntica, ele vai rodar com
bsicas, como adio e multiplicao. sucesso, no sentido de que o computador no vai gerar
nenhuma mensagem de erro. S que o programa no vai fazer
executar Checar certas condies e executar a a coisa certa, vai fazer alguma outra coisa. Especificamente,
condicionalmente seqncia apropriada de instrues. aquilo que voc tiver dito para ele fazer.
repetir Executar alguma ao repetidamente, O problema que o programa que voc
normalmente com alguma variao. escreveu no aquele que voc queria escrever. O significado
Acredite se quiser: isso praticamente tudo. do programa (sua semntica ou lgica) est errado. Identificar
Todos os programas que voc j usou, no importa quo erros semnticos pode ser complicado, porque requer que
complicados, so feitos de instrues mais ou menos voc trabalhe de trs para frente, olhando a sada do programa
parecidas com essas. Assim, poderamos definir programao e tentando imaginar o que ele est fazendo.
como o processo de dividir uma tarefa grande e complexa em
sub-tarefas cada vez menores, at que as sub-tarefas sejam 1.3.4 Depurao experimental (Debugging)
simples o suficiente para serem executadas com uma dessas
instrues bsicas. Uma das habilidades mais importantes que voc vai adquirir
Isso pode parecer um pouco vago, mas vamos a de depurar. Embora possa ser frustrante, depurar uma das
voltar a esse tpico mais adiante, quando falarmos sobre partes intelectualmente mais ricas, desafiadoras e
algoritmos. interessantes da programao.
De certa maneira, a depurao como um
trabalho de detetive. Voc se depara com pistas, e tem que
1.3 O que depurao (debugging)? deduzir os processos e eventos que levaram aos resultados
que aparecem.
Programar um processo complicado e, como feito por Depurar tambm como uma cincia
seres humanos, freqentemente conduz a erros. Por mero experimental. Uma vez que voc tem uma idia do que est
capricho, erros em programas so chamados de bugs e o errado, voc modifica o seu programa e tenta de novo. Se a
processo de encontr-los e corrigi-los chamado de sua hiptese estava correta, ento voc consegue prever o
depurao (debugging). resultado da modificao e fica um passo mais perto de um
programa que funciona. Se a sua hiptese estava errada, voc
Trs tipos de erro podem acontecer em um tem que tentar uma nova. Como Sherlock Holmes mostrou,
programa: erros de sintaxe, erros em tempo de execuo "Quando voc tiver eliminado o impossvel, aquilo que
(runtime errors) e erros de semntica. Distinguir os trs tipos restou, ainda que improvvel, deve ser a verdade." (Arthur
ajuda a localiz-los mais rpido: Conan Doyle, O signo dos quatro).

1.3.1 Erros de sintaxe Para algumas pessoas, programao e


depurao so a mesma coisa. Ou seja, programar o
Python s executa um programa se ele estiver sintaticamente processo de gradualmente depurar um programa, at que ele
correto; caso contrrio, o processo falha e retorna uma faa o que voc quer. A idia comear com um programa
mensagem de erro. Sintaxe se refere estrutura de um que faa alguma coisa e ir fazendo pequenas modificaes,
programa e s regras sobre esta estrutura. Por exemplo, em depurando-as conforme avana, de modo que voc tenha
portugus, uma frase deve comear com uma letra maiscula sempre um programa que funciona.
e terminar com um ponto. Por exemplo, o Linux um sistema operacional
esta frase contm um erro de sintaxe. Assim que contm milhares de linhas de cdigo, mas comeou como
um programa simples, que Linus Torvalds usou para explorar
como esta o chip Intel 80386. De acordo com Larry Greenfield, "Um dos
Para a maioria dos leitores, uns errinhos de primeiros projetos de Linus Torvalds foi um programa que
sintaxe no chegam a ser um problema significativo e por deveria alternar entre imprimir AAAA e BBBB. Isso depois
isso que conseguimos ler a poesia moderna de e. e. cummings evoluiu at o Linux". (The Linux User's Guide Verso Beta 1)
sem cuspir mensagens de erro. Python no to indulgente. Captulos posteriores faro mais sugestes
Se o seu programa tiver um nico erro de sintaxe em algum

Captulo 1: O caminho do programa #15


Como pensar como um cientista da Computao usando Python

sobre depurao e outras prticas de programao. redundncia nas linguagens naturais, o que
freqentemente as torna prolixas. As
linguagens formais so menos redundantes e
1.4 Linguagens naturais e linguagens formais mais concisas.
literalidade As linguagens naturais esto cheias de
Linguagens naturais so as linguagens que as pessoas falam, expresses idiomticas e metforas. Se eu
como o portugus, o ingls e o espanhol. Elas no foram digo "Caiu a ficha", possvel que no exista
projetadas pelas pessoas (muito embora as pessoas tentem ficha nenhuma, nem nada que tenha cado.
colocar alguma ordem nelas); elas evoluram naturalmente. Nas linguagens formais, no h sentido
ambguo.
Linguagens formais so linguagens que foram Pessoas que crescem falando uma linguagem
projetadas por pessoas, para aplicaes especficas. Por natural -- ou seja, todo mundo - muitas vezes tm dificuldade
exemplo, a notao que os matemticos usam uma de se acostumar com uma linguagem formal. De certa
linguagem formal, que particularmente boa em denotar maneira, a diferena entre linguagens formais e naturais
relaes entre nmeros e smbolos. Os qumicos usam uma como a diferena entre poesia e prosa, porm mais acentuada:
linguagem formal para representar a estrutura qumica das
molculas. E, mais importante:
poesia As palavras so usadas pela sua sonoridade,
Linguagens de programao so linguagens alm de seus sentidos, e o poema como um
formais que foram desenvolvidas para expressar todo cria um efeito ou uma reao emocional.
computaes. A ambigidade no apenas freqente, mas na
maioria das vezes, proposital.
As linguagens formais tendem a ter regras
estritas quanto sintaxe. Por exemplo, 3 + 3 = 6 uma prosa O sentido literal das palavras mais
expresso matemtica sintaticamente correta, mas 3=+6$ no importante, e a estrutura contribui mais para o
. H2O um nome qumico sintaticamente correto, mas 2Zz significado. A prosa mais fcil de analisar do
no . que a poesia, mas ainda muitas vezes
ambgua.
As regras de sintaxe so de dois tipos, um
relacionado aos tokens, outro estrutura. "Tokens" so os programas O significado de um programa de computador
elementos bsicos da linguagem, como as palavras, nmeros, exato e literal, e pode ser inteiramente
e elementos qumicos. Um dos problemas com 3=+6$ que $ entendido pela anlise de seus tokens e de sua
no um token vlido em linguagem matemtica (pelo menos estrutura.
at onde sabemos). Do mesmo modo, 2Zz invlida porque Aqui vo algumas sugestes para a leitura de
no existe nenhum elemento cuja abreviatura seja Zz. programas (e de outras linguagens formais). Primeiro, lembre-
O segundo tipo de erro de sintaxe est se de que linguagens formais so muito mais densas do que
relacionado estrutura de uma expresso -- quer dizer, ao linguagens naturais, por isso, mais demorado l-las. A
modo como os tokens esto arrumados. A expresso 3=+6$ estrutura, tambm, muito importante, logo, geralmente no
estruturalmente invlida, porque voc no pode colocar um uma boa idia ler de cima para baixo, da esquerda para a
sinal de "mais" imediatamente aps um sinal de "igual". Do direita. Em vez disso, aprenda a analisar o programa na sua
mesmo modo, frmulas moleculares devem ter ndices cabea, identificando os tokens e interpretando a estrutura.
subscritos colocados depois do nome do elemento, no antes. Finalmente, os detalhes so importantes. Pequenas coisas,
como, erros ortogrficos e m pontuao, com as quais voc
Faa este exerccio: crie o que parea ser uma pode se safar nas linguagens naturais, podem fazer uma
frase bem estruturada em portugus com "tokens" grande diferena em uma linguagem formal.
irreconhecveis dentro dela. Depois escreva outra frase com
todos os "tokens" vlidos, mas com uma estrutura invlida.
Quando voc l uma frase em portugus ou 1.5 O primeiro programa
uma expresso em uma linguagem formal, voc tem de
imaginar como a estrutura da frase (embora, em uma Tradicionalmente, o primeiro programa escrito
linguagem natural, voc faa isso inconscientemente). Este em uma nova linguagem de programao chamado de "Al,
processo chamado parsing (anlise sinttica). Mundo!" porque tudo que ele faz apresentar as palavras
Por exemplo, quando voc ouve a frase, "Caiu a "Al, Mundo!". Em Python, ele assim:
ficha", entende que "a ficha" o sujeito e "caiu" o verbo. print "Al, Mundo!"
Uma vez que voc analisou a frase, consegue entender o seu
significado, ou a semntica da frase. Assumindo que voc Isso um exemplo de um comando print, que,
saiba o que uma ficha e o que significa cair, voc entender na realidade, no "imprime" nada em papel. Ele apresenta o
o sentido geral dessa frase. valor na tela. Neste caso, o resultado so as palavras:
Muito embora as linguagens formais e as Al, Mundo!
naturais tenham muitas caractersticas em comum -- tokens, As aspas no programa marcam o comeo e o
estrutura, sintaxe e semntica -- existem muitas diferenas: fim do valor; elas no aparecem no resultado final.
ambigidade As linguagens naturais esto cheias de Algumas pessoas julgam a qualidade de uma
ambigidades, que as pessoas contornam linguagem de programao pela simplicidade do programa
usando pistas contextuais e outras "Al, Mundo!". Por esse padro, Python se sai to bem
informaes. J as linguagens formais so quanto possvel.
desenvolvidas para serem quase ou
totalmente desprovidas de ambigidade, o
que significa que qualquer expresso tem 1.6 Glossrio
precisamente s um sentido,
independentemente do contexto.
soluo de O processo de formular um problema,
redundncia Para compensar a ambigidade e reduzir problemas encontrar uma soluo e expressar esta
mal-entendidos, emprega-se muita

Captulo 1: O caminho do programa #16


Como pensar como um cientista da Computao usando Python

(problem soluo. (algorithm) categoria de problemas.


solving)
bug Erro em um programa.
linguagem de Uma linguagem de programao como
alto nvel (high- Python: projetada para ser fcil para os depurao O processo de encontrar e remover
level language) seres humanos a utilizarem. (debugging) qualquer um dos trs tipos de erros de
programao.
linguagem de Uma linguagem de programao que
baixo nvel (low- concebida para ser fcil para um sintaxe (syntax) A estrutura de um programa.
level language) computador, tal como a linguagem de erro de sintaxe Erro em um programa, que torna
mquina ou a linguagem montagem (syntax error) impossvel a anlise sinttica (logo,
(assembly language) tambm impossvel a interpretao).
portabilidade Propriedade que um programa tem, de erro em tempo Erro que no ocorre at que o programa
(portability) rodar em mais de um tipo de de execuo seja executado, mas que impede que o
computador. (runtime error) programa continue.
interpretar Executar um programa escrito em uma exceo Um outro nome para um erro em tempo
(interpret) linguagem de alto nvel, traduzindo-o (exception) de execuo ou erro de runtime.
uma linha de cada vez.
erro de Erro em um programa, que o leva a fazer
compilar Traduzir todo um programa escrito em semntica algo diferente do que pretendia o
(compile) uma linguagem de alto nvel para uma de (semantic error) programador.
baixo nvel de um s vez, em preparao
para uma execuo posterior. semntica O significado de um programa.
cdigo fonte Um programa em uma linguagem de alto (semantics)
(source code) nvel, antes de ter sido compilado. linguagem Qualquer lngua falada pelos seres
natural (natural humanos que tenha evoludo
cdigo objeto A sada do compilador, depois que ele language) naturalmente.
(object code) traduziu o programa.
executvel Um outro nome para cdigo objeto que linguagem Qualquer linguagem desenvolvida pelas
(executable) est pronto para ser executado. formal (formal pessoas para propsitos especficos, tais
language) como, a representao de idias
script Um programa guardado em um arquivo matemticas ou programas de
(normalmente um que ser interpretado). computadores; todas as linguagens de
programao so linguagens formais.
programa Conjunto de instrues que especifica
(program) uma computao. tomo (token) Um elemento bsico da estrutura
sinttica de um programa, anlogo a uma
palavra em uma linguagem natural.
anlise sinttica Examinar um programa e analisar sua
(parse) estrutura sinttica.
comando print Instruo que leva o interpretador

Captulo 1: O caminho do programa #17


Como pensar como um cientista da Computao usando Python

(`print` Python a apresentar um valor na tela.


statement)

Captulo 1: O caminho do programa #18


Como pensar como um cientista da Computao usando Python

Captulo 2: Variveis, expresses e comandos

varivel um nome que se refere a um valor.


2.1 Valores e tipos
O comando de atribuio cria novas variveis e
O valor (por exemplo, letras e nmeros) uma das coisas d a elas valores:
fundamentais que um programa manipula. Os valores que j >>> mensagem = "E a, Doutor?"
vimos at agora foram o 2 (como resultado, quando
adicionamos 1 + 1) e "Al, Mundo!". >>> n = 17
>>> pi = 3.14159
Esses valores pertencem a tipos diferentes: 2 Este exemplo faz trs atribuies. A primeira
um inteiro, e "Al, Mundo!" uma string, assim chamada atribui a string "E a, Doutor?" a uma nova varivel chamada
porque "string", em ingls, quer dizer seqncia, srie, cadeia mensagem. A segunda d o valor inteiro 17 a n, e a terceira
(de caracteres), ou neste caso, "srie de letras". Voc (e o atribui o nmero de ponto flutuante 3.14159 varivel
interpretador) consegue identificar strings porque elas chamada pi.
aparecem entre aspas.
Uma maneira comum de representar variveis
O comando print tambm funciona com no papel escrever o nome delas com uma seta apontando
inteiros: para o valor da varivel. Esse tipo de figura chamado de
>>> print 4
diagrama de estado porque mostra em que estado cada
varivel est (pense nisso como o estado de esprito da
4 varivel). O diagrama a seguir mostra o resultado das
Se voc estiver em dvida sobre qual o tipo de instrues de atribuio:
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 flutuante1:
>>> type(3.2) O comando print tambm funciona com
<type 'float'> variveis:
O que dizer de valores como "17" e "3.2"? Eles >>> print mensagem
parecem nmeros, mas esto entre aspas, como strings: E a, Doutor?
>>> type("17") >>> print n
<type 'string'> 17
>>> type("3.2") >>> print pi
<type 'string'> 3.14159
Eles so strings. Em cada um dos casos, o resultado o valor da
varivel. Variveis tambm tm tipo; novamente, podemos
Ao digitar um nmero grande, tentador usar perguntar ao interpretador quais so eles:
pontos entre grupos de trs dgitos, assim: 1.000.000. Isso no
funciona porque Python usa o ponto como separador decimal. >>> type(mensagem)
Usar a vrgula, como se faz em ingls, resulta numa expresso <type 'string'>
vlida, mas no no nmero que queramos representar: >>> type(n)
>>> print 1,000,000 <type 'int'>
1 0 0 >>> type(pi)
<type 'float'>
No nada do que se esperava! Python
interpreta 1,000,000 como uma tupla, algo que veremos no O tipo de uma varivel o tipo do valor ao qual
Captulo 9. Por hora, lembre-se apenas de no colocar vrgulas ela se refere.
nos nmeros.

2.3 Nomes de variveis e palavras reservadas


2.2 Variveis
Os programadores geralmente escolhem nomes significativos
Uma das caractersticas mais poderosas de uma linguagem de para suas variveis -- eles documentam para o qu a varivel
programao a habilidade de manipular variveis. Uma usada.
Nomes de variveis podem ser arbitrariamente
1 N.T.: Observe o uso de ponto no lugar da vrgula para longos. Eles podem conter tanto letras quanto nmeros, mas
separar a parte inteira da parte fracionria.

Captulo 2: Variveis, expresses e comandos #19


Como pensar como um cientista da Computao usando Python

tm de comear com uma letra. Embora seja vlida a comando, o interpretador avalia e exibe o resultado:
utilizao de letras maisculas, por conveno, no usamos.
Se voc o fizer, lembre-se de que maisculas e minsculas so >>> 1 + 1
diferentes. Bruno e bruno so variveis diferentes. 2
O caractere para sublinhado ( _ ) pode aparecer Embora expresses contenham valores,
em um nome. Ele muito utilizado em nomes com mltiplas variveis e operadores, nem toda expresso contm todos estes
palavras, tal como em meu_nome ou preco_do_cha_na_china. elementos. Um valor por si s considerado uma expresso,
do mesmo modo que uma varivel:
Se voc der a uma varivel um nome invlido,
causar um erro de sintaxe: >>> 17
17
>>> 76trombones = "grande parada" >>> x
SyntaxError: invalid syntax 2
>>> muito$ = 1000000 Avaliar uma expresso no exatamente a
SyntaxError: invalid syntax mesma coisa que imprimir um valor:
>>> class = "Ciencias da Computacao 101"
>>> mensagem = "E a, Doutor?"
SyntaxError: invalid syntax
>>> mensagem
76trombones invlida porque no comea com
uma letra. muito$ invlida porque contm um caractere 'E a, Doutor?'
ilegal, o cifro. Mas o que est errado com class? >>> print mensagem
E a, Doutor?
Ocorre que class uma das palavras Quando Python exibe o valor de uma expresso,
reservadas em Python. Palavras reservadas definem as regras usa o mesmo formato que voc usaria para entrar com o valor.
e a estrutura da linguagem e no podem ser usadas como No caso de strings, isso significa que as aspas so includas
nomes de variveis. [#]_. Mas o comando print imprime o valor da expresso, que,
Python tem 29 palavras reservadas: neste caso, o contedo da string.
and def exec if not return Num script, uma expresso sozinha um
assert del finally import or try
comando vlido, porm sem efeito. O script:
break elif for in pass while 17
class else from is print yield 3.2
continue except global lambda raise "Al, Mundo!"
Pode ser til ter essa lista mo. Se o 1 + 1
interpretador acusar erro sobre um de seus nomes de varivel no produz qualquer sada. Como voc mudaria
e voc no souber porqu, veja se o nome est na lista. o "script" para exibir os valores destas quatro expresses?

2.4 Comandos 2.6 Operadores e operandos


Um comando uma instruo que o interpretador Python Operadores so smbolos especiais que representam
pode executar. Vimos at agora dois tipos de comandos: de computaes como adio e multiplicao. Os valores que o
exibio (print) e de atribuio. operador usa so chamados operandos.
Quando voc digita um comando na linha de Todas as expresses seguintes so vlidas em
comando, o Python o executa e mostra o resultado, se houver Python e seus significados so mais ou menos claros:
um. O resultado de um comando print a exibio de um
valor. Comandos de atribuio no produzem um resultado 20+32 hora-1 hora*60+minuto minuto/60 5**2 \
visvel. (5+9)*(15-7)
Um script normalmente contm uma seqncia Em Python, os smbolos +, -, / e o uso de
de comandos. Se houver mais de um comando, os resultados parnteses para agrupamento tm o mesmo significado que em
aparecero um de cada vez, conforme cada comando seja matemtica. O asterisco (*) o smbolo para multiplicao e
executado. ** o smbolo para potenciao.
Por exemplo, o "script": Quando um nome de varivel aparece no lugar
de um operando, ele substitudo pelo valor da varivel, antes
print 1 da operao ser executada.
x = 2
Adio, subtrao, multiplicao e potenciao
print 2 fazem o que se espera, mas voc pode ficar surpreso com a
produz a sada: diviso. A operao seguinte tem um resultado inesperado:
1 >>> minuto = 59
2 >>> minuto/60
Novamente, o comando de atribuio no 0
produz sada. 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
2.5 Avaliando expresses inteira.
Quando ambos os operandos so inteiros, o
Uma expresso uma combinao de valores, variveis e resultado tem de ser tambm um inteiro e, por conveno, a
operadores. Se voc digitar uma expresso na linha de diviso inteira sempre arredonda para baixo, mesmo em casos

Captulo 2: Variveis, expresses e comandos #20


Como pensar como um cientista da Computao usando Python

como este, em que o inteiro seguinte est muito prximo: como 4*3 equivale a 4+4+4, no de estranhar que "Legal"*3
seja o mesmo que "Legal"+"Legal"+"Legal". Por outro lado,
>>> minuto*100/60 uma diferena significativa separa concatenao e repetio de
98 adio e multiplicao. Voc saberia mencionar uma
De novo, o resultado arredondado para baixo, propriedade da adio e da multiplicao que no ocorre na
mas agora pelo menos a resposta aproximadamente correta. concatenao e na repetio?
A alternativa usar a diviso em ponto flutuante, o que
veremos no captulo 3.
2.9 Composio
2.7 Ordem dos operadores At agora, vimos os elementos de um programa -- variveis,
expresses, e instrues ou comandos -- isoladamente, sem
Quando mais de um operador aparece em uma expresso, a mencionar como combin-los.
ordem de avaliao depende das regras de precedncia.
Python segue as mesmas regras de precedncia para seus linguagens deUma das caractersticas mais prticas das
operadores matemticos que a matemtica. O acrnimo pequenos blocosprogramao a possibilidade de pegar
e combin-los numa composio. Por
PEMDAS uma maneira prtica de lembrar a ordem das exemplo, ns sabemos como somar nmeros e sabemos como
operaes: exibi-los; acontece que podemos fazer as duas coisas ao
Parnteses tm a mais alta precedncia e podem ser mesmo tempo:
usados para forar uma expresso a ser avaliada na >>> print 17 + 3
ordem que voc quiser. J que expresses entre
parnteses so avaliadas primeiro, 2 * (3-1) 4, e 20
(1+1)**(5-2) 8. Voc tambm pode usar parnteses Na realidade, a soma tem que acontecer antes da
para tornar uma expresso mais fcil de ler, como em impresso, assim, as aes no esto na realidade acontecendo
(minuto * 100) / 60, ainda que isso no altere o ao mesmo tempo. O ponto que qualquer expresso
resultado. envolvendo nmeros, strings, e variveis pode ser usada
dentro de um comando print. Voc j tinha visto um exemplo
Exponenciao ou potenciao tem a prxima disto:
precedncia mais alta, assim 2**1+1 3 e no 4, e
3*1**3 3 e no 27. print "Nmero de minutos desde a meia-noite: ", \
Multiplicao e Diviso tm a mesma precedncia, hora*60+minuto
que mais alta do que a da Adio e da Subtrao, Esta possibilidade pode no parecer muito
que tambm tm a mesma precedncia. Assim 2*3-1 impressionante agora, mas voc ver outros exemplos em que
d 5 em vez de 4, e 2/3-1 -1, no 1 (lembre-se de a composio torna possvel expressar computaes
que na diviso inteira, 2/3=0). complexas de modo limpo e conciso.
Operadores com a mesma precedncia so avaliados Ateno: Existem limites quanto ao lugar onde
da esquerda para a direita. Assim, na expresso voc pode usar certos tipos de expresso. Por exemplo, o lado
minuto*100/60, a multiplicao acontece primeiro, esquerdo de um comando de atribuio tem que ser um nome
resultando em 5900/60, o que se transforma de varivel, e no uma expresso. Assim, o seguinte no
produzindo 98. Se as operaes tivessem sido vlido: minuto+1 = hora.
avaliadas da direita para a esquerda, o resultado
poderia ter sido 59*1, que 59, que est errado.
2.11 Glossrio
2.8 Operaes com strings valor (value) Um nmero ou string (ou outra coisa que
ainda vamos conhecer) que pode ser
De maneira geral, voc no pode executar operaes atribuda a uma varivel ou computada em
matemticas em strings, ainda que as strings se paream com uma expresso.
nmeros. O que segue invlido (assumindo que mensagem
do tipo string): tipo (type) Um conjunto de valores. O tipo de um
valor determina como ele pode ser usado
mensagem-1 "Al"/123 mensagem*"Al" "15"+2 em expresses. At agora, os tipos vistos
Interessante o operador +, que funciona com so: inteiros (tipo int), nmeros em ponto-
strings, embora ele no faa exatamente o que voc poderia flutuante (tipo float) e strings (tipo string).
esperar. Para strings, o operador + representa concatenao, ponto- Formato para representar nmeros que
que significa juntar os dois operandos ligando-os pelos flutuante possuem partes fracionrias.
extremos. Por exemplo: (floating-point)
fruta = "banana" varivel Nome que se refere a um valor.
assada = " com canela" (variable)
print fruta + assada
A sada deste programa banana com canela. O comando Trecho de cdigo que representa uma
espao antes da palavra com parte da string e necessrio (statement) instruo ou ao. At agora, os comandos
para produzir o espao entre as strings concatenadas. vistos foram de atribuio e exibio.

O operador * tambm funciona com strings; ele atribuio Comando que atribui um valor a uma
realiza repetio. Por exemplo, "Legal"*3 (assignment) varivel.
"LegalLegaLegal". Um dos operadores tem que ser uma diagrama de Representao grfica de um conjunto de
string; o outro tem que ser um inteiro. estado (state variveis e os valores aos quais elas se
diagram) referem.
Por um lado, esta interpretao de + e * faz
sentido pela analogia entre adio e multiplicao. Assim

Captulo 2: Variveis, expresses e comandos #21


Como pensar como um cientista da Computao usando Python

palavra-chave Palavra reservada usada pelo compilador


(keyword) para analisar o programa; voc no pode
usar palavras-chave como if, def, e while
como nomes de variveis.
operador Smbolo especial que representa uma
(operator) computao simples, como adio,
multiplicao ou concatenao de strings.
operando Um dos valores sobre o qual o operador
(operand) opera.
expresso Combinao de variveis, operadores e
(expression) valores, que representa um resultado nico.
avaliar Simplificar uma expresso atravs da
(evaluate) realizao de operaes, para produzir um
valor nico.
diviso inteira Operao que divide um inteiro por outro e
(integer resulta em um inteiro. A diviso inteira
division) resulta no nmero de vezes que o
numerador divisvel pelo denominador e
descarta qualquer resto.
regras de O conjunto de regras que governa a ordem
precedncia em que expresses envolvendo mltiplos
(rules of operadores e operandos so avaliadas.
precedence)
concatenar Juntar dois operandos lado a lado.
(concatenate)
composio Habilidade de combinar expresses e
(composition) comandos simples em expresses e
comandos compostos, de forma a
representar computaes complexas de
forma concisa.
comentrio Informao em um programa dirigida a
(comment) 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 #22


Como pensar como um cientista da Computao usando Python

Captulo 3: Funes

'32'
3.1 Chamadas de funes >>> str(3.14149)
'3.14149'
Voc j viu um exemplo de uma chamada de funo:
Pode parecer curioso que Python faa distino
>>> type('32') entre o valor inteiro 1 e o valor em ponto flutuante 1.0. Eles
<type 'str'>
podem representar o mesmo nmero, mas pertencem a tipos
diferentes. A razo que eles so representados de modo
O nome da funo type e ela exibe o tipo de diferente dentro do computador.
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. 3.3 Coero entre tipos
Em vez de imprimir um valor de retorno,
podemos atribui-lo a uma varivel: Agora que podemos converter entre tipos, temos outra
maneira de lidar com a diviso inteira. Voltando ao exemplo
>>> bia = type('32') do captulo anterior, suponha que queiramos calcular a frao
>>> print bia de hora que j passou. A expresso mais bvia, minuto / 60,
<type 'str'>
faz aritmtica inteira, assim, o resultado sempre 0, mesmo
aos 59 minutos passados da hora.
Como outro exemplo, a funo id recebe um
valor ou uma varivel e retorna um inteiro, que atua como um Uma soluo converter minuto para ponto
identificador nico para aquele valor: flutuante e fazer a diviso em ponto flutuante:
>>> id(3) >>> minuto = 59
134882108 >>> float(minuto) / 60
>>> bia = 3 0.983333333333
>>> bia(beth) Opcionalmente, podemos tirar vantagem das
134882108 regras de converso automtica entre tipos, chamada de
Todo valor tem um id, que um nmero nico coero de tipos. Para os operadores matemticos, se
relacionado ao local onde ele est guardado na memria do qualquer operando for um float, o outro automaticamente
computador. O id de uma varivel o id do valor a qual ela se convertido para float:
refere. >>> minuto = 59
>>> minuto / 60.0
0.983333333333
3.2 Converso entre tipos Fazendo o denominador um float, foramos o
Python a fazer a diviso em ponto flutuante.
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:
3.4 Funes matemticas
>>> int('32')
32 Em matemtica, voc provavelmente j viu funes como
>>> int('Al') seno (sin) e log, e aprendeu a resolver expresses como
ValueError: invalid literal for int() : Al sin(pi/2) e log(1/x). Primeiro voc resolve e expresso entre
parnteses (o argumento). Por exemplo, pi/2
int tambm pode converter valores em ponto aproximadamente 1,571, e 1/x 0.1 (se x for 10,0).
flutuante para inteiro, mas lembre que isso trunca a parte
fracionria: A voc avalia a funo propriamente dita, seja
procurando numa tabela ou realizando vrios clculos. O sin
>>> int(3.99999) de 1,571 1 e o log de 0,1 -1 (assumindo que log indica o
3 logaritmo na base 10).
>>> int(-2.3)
-2
Este processo pode ser aplicado repetidamente
para avaliar expresses mais complicadas, como
A funo float converte inteiros e strings em log(1/sin(pi/2)). Primeiro voc avalia o argumento na funo
nmeros em ponto flutuante: mais interna, depois avalia a funo e assim por diante.
>>> float(32) Python tem um mdulo matemtico que prov a
32.0 maioria das funes matemticas mais familiares. Um mdulo
>>> float('3.14159') um arquivo que contm uma coleo de funes
3.14159 relacionadas agrupadas juntas.
Finalmente, a funo str converte para o tipo Antes de podermos usar as funes contidas em
string: um mdulo, temos de import-lo:
>>> str(32) >>> import math

Captulo 3: Funes #23


Como pensar como um cientista da Computao usando Python

Para chamar uma das funes, temos que lista de parmetros especifica que informao, se houver
especificar o nome do mdulo e o nome da funo, separados alguma, voc tem que fornecer para poder usar a nova funo.
por um ponto. Esse formato chamado de notao de ponto:
Uma funo pode ter quantos comandos forem
>>> decibel = math.log10(17.0) necessrios, mas eles precisam ser endentados a partir da
>>> angulo = 1.5 margem esquerda. Nos exemplos deste livro, usaremos uma
>>> altura = math.sin(angulo)
endentao de dois espaos.
A primeira instruo atribui a decibel o As primeiras funes que vamos mostrar no
logaritmo de 17 na base 10. Existe tambm uma funo tero parmetros, ento, a sintaxe ter esta aparncia:
chamada log, que pega o logaritmo na base e.
def novaLinha():
A terceira instruo encontra o seno do valor da print
varivel angulo. sin e as outras funes trigonomtricas (cs,
tan, etc.) recebem argumentos em radianos. Para converter de Esta funo chamada de novaLinha. Os
graus em radianos, divida por 360 e multiplique por 2*pi. Por parnteses vazios indicam que ela no tem parmetros.
exemplo, para encontrar o seno de 45 graus, primeiro calcule Contm apenas um nico comando, que gera como sada um
o ngulo em radianos e depois ache o seno: caractere de nova linha (isso o que acontece quando voc
usa um comando print sem qualquer argumento).
>>> graus = 45
A sintaxe para a chamada desta nova funo a
>>> angulo = graus * 2 * math.pi / 360.0 mesma sintaxe para as funes nativas:
>>> math.sin(angulo)
0.707106781187 print 'Primeira Linha.'
A constante pi tambm parte do mdulo math. novaLinha()
Se voc sabe geometria, pode checar o resultado anterior print 'Segunda Linha.'
comparando-o com a raiz quadrada de dois dividido por dois: A sada deste programa :
>>> math.sqrt(2) / 2.0 Primeira Linha.
0.707106781187
Segunda Linha.
Observe o espao extra entre as duas linhas. E
3.5 Composio se quisssemos mais espao entre as linhas? Poderamos
chamar a mesma funo repetidamente:
Do mesmo modo como nas funes matemticas, as funes print 'Primeira Linha.'
do Python podem ser compostas, o que significa que voc novaLinha()
pode usar uma expresso como parte de outra. Por exemplo, novaLinha()
voc pode usar qualquer expresso como um argumento para
uma funo: novaLinha()
print 'Segunda Linha.'
>>> x = math.cos(angulo + pi/2) Ou poderamos escrever uma nova funo
Esta instruo toma o valor de pi, divide-o por chamada tresLinhas, que produzisse trs novas linhas:
2, e soma o resultado ao valor de angulo. A soma ento
passada como um argumento para a funo cos. def tresLinhas() :
novaLinha()
Voc tambm pode pegar o resultado de uma novaLinha()
funo e pass-lo como um argumento para outra:
novaLinha()
>>> x = math.exp(math.log(10.0))
Esta instruo encontra o logaritmo base e de 10 print 'Primeira Linha.'
e ento eleva e quela potncia. O resultado atribudo a x. tresLinhas()
print 'Segunda Linha.'
Esta funo contm trs comandos, todos com
3.6 Adicionando novas funes 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.
At aqui, temos utilizado somente as funes que vm com
Python, mas tambm possvel adicionar novas funes. Criar Algumas coisas que devem ser observadas sobre
novas funes para resolver seus prprios problemas uma este programa:
das coisas mais teis de uma linguagem de programao de
propsito geral. 1. Voc pode chamar o mesmo procedimento
repetidamente. Isso muito comum, alm de til.
No contexto de programao, funo uma
seqncia nomeada de instrues ou comandos, que realizam 2. Voc pode ter uma funo chamando outra funo;
uma operao desejada. Esta operao especificada numa neste caso tresLinhas chama novaLinha.
definio de funo. At agora, as funes que usamos neste
livro so pr-definidas e suas definies no foram Pode no estar claro, at agora, de que vale o
apresentadas. Isso demonstra que podemos usar funes sem esforo de criar novas funes - existem vrias razes, mas
ter que nos preocupar com os detalhes de suas definies. este exemplo demonstra duas delas:
A sintaxe para uma definio de funo : Criar uma nova funo permite que voc coloque
nome em um grupo de comandos. As funes podem
def NOME( LISTA DE PARAMETROS ) : simplificar um programa ao ocultar uma computao
COMANDOS complexa por trs de um simples comando cujo
nome pode ser uma palavra em portugus, em vez de
Voc pode usar o nome que quiser para as algum cdigo misterioso.
funes que criar, exceto as palavras reservadas do Python. A

Captulo 3: Funes #24


Como pensar como um cientista da Computao usando Python

Criar uma nova funo pode tornar o programa lembra que uma funo pode chamar outra. Enquanto estiver
menor, por eliminar cdigo repetido. Por exemplo, no meio de uma funo, o programa poderia ter de executar os
um atalho para 'imprimir' nove novas linhas comandos em uma outra funo. Mas enquanto estivesse
consecutivas chamar tresLinhas trs vezes. executando esta nova funo, o programa poderia ter de
executar ainda outra funo!
Como exerccio, escreva uma funo chamada
noveLinhas que use tresLinhas para imprimir nove linhas Felizmente, Python adepto de monitorar a
em branco. Como voc poderia imprimir vinte e sete novas posio onde est, assim, cada vez que uma funo se
linhas? completa, o programa retoma de onde tinha parado na funo
que a chamou. Quando chega ao fim do programa, ele
termina.
3.7 Definies e uso Qual a moral dessa histria srdida? Quando
voc ler um programa, no o leia de cima para baixo. Em vez
Reunindo os fragmentos de cdigo da Seo 3.6, o programa disso, siga o fluxo de execuo.
completo fica assim:
def novaLinha() :
3.9 Parmetros e argumentos
print
Algumas das funes nativas que voc j usou requerem
def tresLinhas() : argumentos, aqueles valores que controlam como a funo faz
novaLinha() seu trabalho. Por exemplo, se voc quer achar o seno de um
novaLinha() nmero, voc tem que indicar qual nmero . Deste modo, sin
novaLinha() recebe um valor numrico como um argumento.
Algumas funes recebem mais de um
print 'Primeira Linha.' argumento. Por exemplo, pow recebe dois argumentos, a base
tresLinhas() e o expoente. Dentro da funo, os valores que lhe so
print 'Segunda Linha.' passados so atribudos a variveis chamadas parmetros.
Esse programa contm duas definies de Veja um exemplo de uma funo definida pelo
funes: novaLinha e tresLinhas. Definies de funes so usurio, que recebe um parmetro:
executadas como quaisquer outros comandos, mas o efeito
criar a nova funo. Os comandos dentro da definio da def imprimeDobrado(bruno):
funo no so executados at que a funo seja chamada, print bruno, bruno
logo, a definio da funo no gera nenhuma sada. Esta funo recebe um nico argumento e o
Como voc j deve ter imaginado, preciso atribui a um parmetro chamado bruno. O valor do parmetro
criar uma funo antes de poder execut-la. Em outras (a essa altura, no sabemos qual ser) impresso duas vezes,
palavras, a definio da funo tem que ser executada antes seguido de uma nova linha. Estamos usando bruno para
que ela seja chamada pela primeira vez. mostrar que o nome do parmetro deciso sua, mas claro que
melhor escolher um nome que seja mais ilustrativo.
Como exerccio, mova as ltimas trs linhas
deste programa para o topo, de modo que a chamada da A funo imprimeDobrado funciona para
funo aparea antes das definies. Rode o programa e veja qualquer tipo que possa ser impresso:
que mensagem de erro voc ter.
>>> imprimeDoobrado('Spam')
Tambm a ttulo de exerccio, comece com a Spam Spam
verso que funciona do programa e mova a definio de >>> imprimeDobrado(5)
novaLinha para depois da definio de tresLinhas. O que 5 5
acontece quando voc roda este programa?
>>> imprimeDobrado(3.14159)
3.14159 3.14159
Na primeira chamada da funo, o argumento
3.8 Fluxo de execuo uma string. Na segunda, um inteiro. Na terceira um float.
Para assegurar que uma funo esteja definida antes do seu As mesmas regras de composio que se
primeiro uso, preciso saber em que ordem os comandos so aplicam a funes nativas tambm se aplicam s funes
executados, o que chamado de fluxo de execuo. definidas pelo usurio, assim, podemos usar qualquer tipo de
expresso como um argumento para imprimeDobrado:
A execuo sempre comea com o primeiro
comando do programa. Os comandos so executados um de >>> imprimeDobrado('Spam'*4)
cada vez, pela ordem, de cima para baixo. SpamSpamSpamSpam SpamSpamSpamSpam
>>> imprimeDobrado(math.cos(math.pi))
As definies de funo no alteram o fluxo de
execuo do programa, mas lembre-se que comandos dentro -1.0 -1.0
da funo no so executados at a funo ser chamada. Como acontece normalmente, a expresso
Embora no seja comum, voc pode definir uma funo avaliada antes da execuo da funo, assim imprimeDobrado
dentro de outra. Neste caso, a definio mais interna no imprime SpamSpamSpamSpam SpamSpamSpamSpam em
executada at que a funo mais externa seja chamada. vez de 'Spam'*4 'Spam'*4.
Chamadas de funo so como um desvio no Como exerccio, escreva um chamada a
fluxo de execuo. Em vez de ir para o prximo comando, o imprimeDobrado que imprima 'Spam'*4 'Spam'*4. Dica:
fluxo salta para a primeira linha da funo chamada, executa strings podem ser colocadas tanto entre aspas simples
todos os comandos l e ento volta atrs para retomar de onde quanto duplas e o tipo de aspas que no for usado para
havia deixado. envolver a string pode ser usado dentro da string, como
parte dela.
Parece muito simples, at a hora em que voc

Captulo 3: Funes #25


Como pensar como um cientista da Computao usando Python

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'); A ordem da pilha mostra o fluxo de execuo.
aqui, em imprimeDobrado, chamamos a todo mundo de imprimeDobrado foi chamado por concatDupla, e
bruno. 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__.
3.10 Variveis e parmetros so locais
Cada parmetro se refere ao mesmo valor que o
Quando voc cria uma varivel local dentro de uma funo, seu argumento correspondente. Assim, parte1 tem o mesmo
ela s existe dentro da funo e voc no pode us-la fora de valor de canto1, parte2 tem o mesmo valor de canto2 e bruno
l. Por exemplo: tem o mesmo valor de concat.

def concatDupla(parte1, parte2)


Se um erro acontece durante uma chamada de
funo, Python imprime o nome da funo, e o nome da
concat = parte1 + parte2 funo que a chamou, e o nome da funo que chamou a que
imprimeDobrado(concat) chamou, percorrendo todo o caminho de volta a __main__.
Esta funo recebe dois argumentos, concatena-
os, e ento imprime o resultado duas vezes. Podemos chamar Por exemplo, se tentssemos acessar concat de
a funo com duas strings: dentro de imprimeDobrado, teramos um NameError:

>>> canto1 = 'Pie Jesu domine, ' Traceback (innermost last):


>>> canto2 = 'dona eis requiem. ' File "teste.py", line 13, in __main__
>>> concatDupla(canto1, canto2) concatDupla(canto1, canto2)
Pie Jesu domine, Dona eis requiem. Pie Jesu domine, \ File "teste.py", line 5, in concatDupla
Dona eis requiem. imprimeDobrado(concat)
File "teste.py", line 9, in imprimeDobrado
Quando a funo concatDupla termina, a
varivel concat destruda. Se tentarmos imprimi-la, teremos print concat
um erro: NameError: concat
Esta lista de funes chamada de traceback.
>>> print concat Ela mostra em qual arquivo de programa o erro ocorreu, em
NameError: concat que linha, e quais funes estavam sendo executadas naquele
Parmetros so sempre locais. Por exemplo, momento. Mostra tambm a linha de cdigo que causou o
fora da funo imprimeDobrado, no existe alguma coisa erro.
chamada bruno. Se voc tentar utiliz-la, Python vai reclamar.
Note a similaridade entre o traceback e o
diagrama da pilha; no coincidncia.
3.11 Diagramas da pilha
3.12 Funes com resultados
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, A essa altura, voc deve ter percebido que algumas das
mas tambm a funo qual cada varivel pertence. funes que estamos usando, tais como as funes
matemticas, produzem resultados. Outras funes, como
Cada funo representada por um frame novaLinha, executam uma ao, mas no retornam um valor.
(quadro). Um frame uma caixa com o nome de uma funo O que levanta algumas questes:
ao lado dela e os parmetros e variveis da funo dentro dela.
O diagrama de pilha para o exemplo anterior tem a seguinte 1. O que acontece se voc chama uma funo e no faz
aparncia: 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.

Captulo 3: Funes #26


Como pensar como um cientista da Computao usando Python

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 Comando que executa uma funo.


funo Consiste do nome da funo seguido de
(function call) uma lista de argumentos entre parnteses.
argumento Valor fornecido a uma funo quando ela
(argument) chamada. Este valor atribudo ao
parmetro correspondente na funo.
valor de O resultado da funo. Se uma chamada
retorno (return de funo usada como expresso, o
value) valor de retorno o valor da expresso.
converso de Comando explcito que pega um valor de
tipo (type um tipo e devolve o valor correspondente
conversion) em outro tipo.
coercividade de Uma converso de tipo que ocorre
tipo (type automaticamente, de acordo com as regras
coercion) de coercividade do Python.
mdulo Arquivo que contm uma coleo de
(module) funes e classes relacionadas entre si.
notao de A sintaxe para chamar uma funo que
ponto (dot est em outro mdulo, especificando o
notation) nome do mdulo, seguido por um ponto
(.) e o nome da funo.
funo Seqncia de comandos nomeada, que
(function) realiza alguma tarefa til. As funes
podem ou no receber parmetros e
podem ou no retornar valores.
definio de Comando que cria uma nova funo,
funo especificando seu nome, parmetros e
(function comandos que ela executa.
definition)
fluxo de A ordem na qual os comandos so
execuo (flow executados durante a execuo do
of execution) programa.
parmetro Nome usado numa funo para referir-se
(parameter) ao valor passado como argumento.
varivel local Varivel definida dentro da funo. Uma
(local variable) varivel local s pode ser usada dentro da
funo onde foi definida.
diagrama da Representao grfica da pilha de funes,
pilha (stack suas variveis e os valores aos quais elas
diagram) 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 #27


Como pensar como um cientista da Computao usando Python

Captulo 4: Condicionais e recursividade

4.1 O operador mdulo 4.3 Operadores lgicos


O operador mdulo trabalha com inteiros (e expresses que Existem trs operadores lgicos: and, or, not (e, ou, no). A
tm inteiros como resultado) e produz o resto da diviso do semntica (significado) destes operadores similar aos seus
primeiro pelo segundo. Em Python, o operador mdulo um significados em ingls (ou portugus). Por exemplo, x > 0 and
smbolo de porcentagem (%). A sintaxe a mesma que a de x < 10 verdadeiro somente se x for maior que 0 e menor que
outros operadores: 10.
>>> quociente = 7 / 3 n%2 == 0 or n%3 == 0 verdadeiro se qualquer
>>> print quociente das condies for verdadeira, quer dizer, se o nmero n for
2
divisvel por 2 ou por 3.
>>> resto = 7 % 3 Finalmente, o operador lgico not nega uma
>>> print resto expresso booleana, assim, not(x > y) verdadeiro se (x > y)
1 for falso, quer dizer, se x for menor ou igual a y.
Ento, 7 dividido por 3 2 e o resto 1. A rigor, os operandos de operadores lgicos
deveriam ser expresses booleanas, mas Python no muito
O operador mdulo se revela
surpreendentemente til. Por exemplo, voc pode checar se rigoroso. Qualquer nmero diferente de zero interpretado
um nmero divisvel por outro - se x % y d zero, ento x como verdadeiro (True):
divisvel por y. >>> x = 5
Voc tambm pode extrair o algarismo ou >>> x and 1
algarismos mais direita de um nmero. Por exemplo, x % 10 1
resulta o algarismo mais direita de x (na base 10). >>> y = 0
Similarmente, x % 100 resulta nos dois dgitos mais direita. >>> y and 1
0
Em geral, esse tipo de coisa no considerado
4.2 Expresses booleanas de bom estilo. Se voc precisa comparar um valor com zero,
deve faz-lo explicitamente.
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 4.4 Execuo condicional
valor 0.
O operador == compara dois valores e produz Para poder escrever programas teis, quase sempre
uma expresso booleana: precisamos da habilidade de checar condies e mudar o
comportamento do programa de acordo com elas. As
>>> 5 == 5 instrues condicionais nos do essa habilidade. A forma
True mais simples a instruo if (se):
>>> 5 == 6
if x > 0
False
print "x positivo"
No primeiro comando, os dois operadores so
iguais, ento a expresso avalia como True (verdadeiro); no A expresso booleana depois da instruo if
segundo comando, 5 no igual a 6, ento temos False (falso). chamada de condio. Se ela verdadeira (true), ento a
instruo endentada executada. Se no, nada acontece.
O operador == um dos operadores de
comparao; os outros so: Assim como outras instrues compostas, a
instruo if constituda de um cabealho e de um bloco de
x != y # x diferente de y instrues:
x > y # x maior que y CABECALHO:
x < y # x menor que y PRIMEIRO COMANDO
x >= y # x maior ou igual a y ...
x <= y # x menor ou igual a y ULTIMO COMANDO
Embora esses operadores provavelmente sejam O cabealho comea com uma nova linha e
familiares a voc, os smbolos em Python so diferentes dos termina com dois pontos (:). Os comandos ou instrues
smbolos da matemtica. Um erro comum usar um sinal de endentados que seguem so chamados de bloco. A primeira
igual sozinho (=) em vez de um duplo (==). Lembre-se de que instruo no endentada marca o fim do bloco. Um bloco de
= um operador de atribuio e == um operador de comandos dentro de um comando composto ou instruo
comparao. Tambm no existem coisas como =< ou =>. 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

Captulo 4: Condicionais e recursividade #28


Como pensar como um cientista da Computao usando Python

corpo sem nenhuma instruo (usualmente, como um uma delas verdadeira, o ramo correspondente executado, e
delimitador de espao para cdigo que voc ainda no a instruo termina. Mesmo que mais de uma condio seja
escreveu). Nesse caso, voc pode usar o comando pass, que verdadeira, apenas o primeiro ramo verdadeiro executa.
no faz nada.
Como exerccio, coloque os exemplos acima em
funes chamadas comparar(x, y) e executar(escolha).
4.5 Execuo alternativa
4.7 Condicionais aninhados
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: Um condicional tambm pode ser aninhado dentro de outra.
Poderamos ter escrito o exemplo tricotmico (dividido em
if x % 2 == 0: trs) como segue:
print x, " par"
if x == y:
else:
print x, "e", y, "so iguais"
print x, " impar"
else:
Se o resto da diviso de x por 2 for 0, ento if x < y:
sabemos que x par, e o programa exibe a mensagem para
esta condio. Se a condio falsa, o segundo grupo de print x, " menor que", y
instrues executado. Desde que a condio deva ser else:
verdadeira (true) ou falsa (false), precisamente uma das print x, " maior que", y
alternativas vai ser executada. As alternativas so chamadas O condicional mais externo tem dois ramos. O
ramos (branches), porque existem ramificaes no fluxo de primeiro ramo contm uma nica instruo de sada. O
execuo. segundo ramo contm outra instruo if, que por sua vez tem
Por sinal, se voc precisa checar a paridade de dois ramos. Os dois ramos so ambos instrues de sada,
nmeros com freqncia, pode colocar este cdigo dentro de embora pudessem conter instrues condicionais tambm.
uma funo: Embora a endentao das instrues torne a
def imprimeParidade(x):
estrutura aparente, condicionais aninhados tornam-se difceis
de ler rapidamente. Em geral, uma boa idia evitar o
if x % 2 == 0: aninhamento quando for possvel.
print x, " par"
else: Operadores lgicos freqentemente fornecem
print x, " impar"
uma maneira de simplificar instrues condicionais aninhadas.
Por exemplo, podemos reescrever o cdigo a seguir usando
Para qualquer valor de x, imprimeParidade uma nica condicional:
exibe uma mensagem apropriada. Quando voc a chama, pode
fornecer uma expresso de resultado inteiro como um if 0 < x:
argumento: if x < 10:
>>> imprimeParidade(17) print "x um nmero positivo de um s
algarismo."
>>> imprimeParidade(y+1)
A instruo print executada somente se a
fizermos passar por ambos os condicionais, ento, podemos
usar um operador and:
4.6 Condicionais encadeados if 0 < x and x < 10:
print "x um nmero positivo de um s algarismo."
s vezes existem mais de duas possibilidades e precisamos de
mais que dois ramos. Uma condicional encadeada uma Esses tipos de condio so comuns, assim,
maneira de expressar uma computao dessas: Phython prov uma sintaxe alternativa que similar notao
matemtica:
if x < y:
if 0 < x < 10:
print x, " menor que", y
print "x um nmero positivo de um s algarismo."
elif x > y:
print x, " maior que", y
else:
print x, "e", y, "so iguais" 4.8 A instruo return
elif uma abreviao de "else if" ("ento se").
De novo, precisamente um ramo ser executado. No existe O comando return permite terminar a execuo de uma funo
limite para o nmero de instrues elif, mas se existir uma antes que ela alcance seu fim. Uma razo para us-lo se voc
instruo else ela tem que vir por ltimo: detectar uma condio de erro:
if escolha == 'A': import math
funcaoA()
elif escolha == 'B': def imprimeLogaritmo(x):
funcaoB() if x <= 0:
elif escolha == 'C': print "Somente nmeros positivos, por favor."
funcaoC() return
else:
print "Escolha invlida." resultado = math.log(x)
Cada condio checada na ordem. Se a print "O log de x ", resultado
primeira falsa, a prxima checada, e assim por diante. Se A funo imprimeLogaritmo recebe um

Captulo 4: Condicionais e recursividade #29


Como pensar como um cientista da Computao usando Python

parmetro de nome x. A primeira coisa que ela faz checar se novaLinha()


x menor ou igual a 0, neste caso ela exibe uma mensagem de Muito embora isso funcione, no seria muito
erro e ento usa return para sair da funo. O fluxo de til se precisssemos gerar como sada 2 novas linhas, ou 106.
execuo imediatamente retorna ao ponto chamador, quer Uma alternativa melhor seria esta:
dizer, de onde a funo foi chamada, e as linhas restantes da
funo no so executadas. def nLinhas(n):
Lembre-se que para usar uma funo do mdulo if n > 0:
de matemtica, math, voc tem de import-lo. print
nLinhas(n-1)
Esse programa similar a contagemRegressiva;
4.9 Recursividade 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
J mencionamos que vlido uma funo chamar outra 1 + (n-1) que, se voc estudou lgebra direitinho, vem a ser
funo, e voc viu vrios exemplos disso. Mas ainda no o prprio n.
tnhamos dito que tambm vlido uma funo chamar a si
mesma. Talvez no seja bvio porque isso bom, mas trata-se O processo de uma funo chamando a si
de uma das coisas mais mgicas e interessantes que um mesma chamado de recursividade, e tais funes so ditas
programa pode fazer. Por exemplo, d uma olhada na seguinte recursivas.
funo:
def contagemRegressiva(n):
if n == 0: 4.10 Diagramas de pilha para funes recursivas
print "Fogo!"
else: Na Seo 3.11, usamos um diagrama de pilha para representar
o estado de um programa durante uma chamada de funo. O
print n mesmo tipo de diagrama pode ajudar a interpretar uma funo
contagemRegressiva(n-1) recursiva.
contagemRegressiva espera que o parmetro, n,
seja um inteiro positivo. Se n for 0, ela produz como sada a Toda vez que uma funo chamada, Python
palavra "Fogo!". De outro modo, ela produz como sada n e cria um novo quadro (frame) para a funo, que contm as
ento chama uma funo de nome contagemRegressiva -- ela variveis locais e parmetros da funo. Para uma funo
mesma -- passando n-1 como argumento. recursiva, ter que existir mais de um quadro na pilha ao
mesmo tempo.
O que acontece se chamarmos essa funo da
seguinte maneira: Esta figura mostra um diagrama de pilha para
contagemRegressiva, chamada com n = 3:
>>> 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: Como de costume, no topo da pilha est o
quadro para __main__. Ele est vazio porque nem criamos
3 qualquer varivel em __main__ nem passamos qualquer valor
2 para ele.
1 Os quatro quadros contagemRegressiva tm
Fogo! valores diferentes para o parmetro n. A parte mais em baixo
Como um segundo exemplo, d uma olhada na pilha, onde n=0, chamada de caso base. Ele no faz uma
novamente nas funes novaLinha e tresLinhas: chamada recursiva, ento no h mais quadros.
def novaLinha(): Como exerccio, desenhe um diagrama de pilha
print para nLinhas chamada com n=4.

def tresLinhas():
novaLinha()
novaLinha()

Captulo 4: Condicionais e recursividade #30


Como pensar como um cientista da Computao usando Python

>>> velocidade = input(deixa)


4.11 Recursividade infinita Qual... a velocidade de vo de uma andorinha?
De qual voc fala, uma andorinha Africana ou uma \
Se uma recursividade nunca chega ao caso base, ela prossegue Europia?
fazendo chamadas recursivas para sempre, e o programa
nunca termina. Isto conhecido como recursividade infinita, e SyntaxError: invalid syntax
geralmente no considerada uma boa idia. Aqui est um Para evitar esse tipo de erro, geralmente bom
programa mnimo com uma recursividade infinita: usar raw_input para pegar uma string e, ento, usar funes de
converso para converter para outros tipos.
def recursiva():
recursiva()
Na maioria dos ambientes de programao, um 4.13 Glossrio
programa com recursividade infinita na verdade no roda para
sempre. Python reporta uma mensagem de erro quando a
profundidade mxima de recursividade alcanada: operador Operador denotado por um smbolo de
mdulo porcentagem (%), que trabalha com
File "<stdin>", line 2, in recursiva (modulus inteiros e retorna o resto da diviso de um
(98 repetitions omitted) operator) nmero por outro.
File "<stdin>", line 2, in recursiva
RuntimeError: Maximum recursion depth exceeded
expresso Uma expresso que verdadeira ou falsa.
booleana
(boolean
Este traceback um pouco maior do que aquele expression)
que vimos no captulo anterior. Quando o erro ocorre, existem operador de Um dos operadores que compara dois
100 quadros recursiva na pilha! comparao valores: ==, !=, >, <, >=, e <=.
Como exerccio, escreva uma funo com (comparison
recursividade infinita e rode-a no interpretador Python. operator)
operador lgico Um dos operadores que combina
(logical expresses booleanas: and, or, e not.
operator)
4.12 Entrada pelo teclado
comando Comando que controla o fluxo de
Os programas que temos escrito at agora so um pouco crus, condicional execuo dependendo de alguma
no sentido de no aceitarem dados entrados pelo usurio. Eles (conditional condio.
simplesmente fazem a mesma coisa todas as vezes. statement)
Python fornece funes nativas que pegam condio A expresso booleana que determina qual
entradas pelo teclado. A mais simples chamada raw_input. (condition) bloco ser executado num comando
Quando esta funo chamada, o programa pra e espera que condicional.
o usurio digite alguma coisa. Quando o usurio aperta a tecla comando Comando que consiste de um cabealho e
Enter ou Return, o programa prossegue e a funo raw_input composto um corpo. O cabealho termina com um
retorna o que o usurio digitou como uma string: (compound dois-pontos (:). O corpo endentado em
>>> entrada = raw_input() statement) relao ao cabealho.
O que voc est esperando? bloco (block) Grupo de comandos consecutivos com a
>>> print entrada mesma endentao.
O que voc est esperando?
corpo (body) O bloco que se segue ao cabealho em
Antes de chamar raw_input, uma boa idia um comando composto.
exibir uma mensagem dizendo ao usurio o que ele deve
entrar. Esta mensagem uma deixa (prompt). Podemos suprir aninhamento Estrutura de programa dentro da outra,
uma deixa como um argumento para raw_input: (nesting) como um comando condicional dentro de
um bloco de outro comando condicional.
>>> nome = raw_input("Qual... o seu nome? ")
Qual... o seu nome? Arthur, Rei dos Bretes! recursividade O processo de chamar a prpria funo
>>> print nome
(recursion) que est sendo executada.
Arthur, Rei dos Bretes! caso base (base Bloco de comando condicional numa
Se esperamos que a entrada seja um inteiro, case) funo recursiva que no resulta em uma
podemos usar a funo input: chamada recursiva.
deixa = "Qual... a velocidade de vo de uma \ recurso infinita Funo que chama a si mesma
andorinha?\n" (infinite recursivamente sem nunca chegar ao caso
velocidade = input(deixa)
recursion) base. Aps algum tempo, uma recurso
infinita causa um erro de execuo.
Se o usurio digita uma string de nmeros, ela
convertida para um inteiro e atribuda a velocidade. deixa (prompt) Indicao visual que diz ao usurio que o
Infelizmente, se o usurio digitar um caractere que no seja programa est esperando uma entrada de
um nmero, o programa trava: dados.

Captulo 4: Condicionais e recursividade #31


Como pensar como um cientista da Computao usando Python

Captulo 5: Funes frutferas

terminar sem encontrar um comando return. Neste caso, o


5.1 Valores de retorno valor de retorno ser um valor especial chamado None:
Algumas das funes nativas do Python que temos usado, >>> print valorAbsoluto(0)
como as funes matemticas, produziram resultados. Chamar None
a funo gerou um novo valor, o qual geralmente atribumos Como exerccio, escreva uma funo compare
uma varivel ou usamos como parte de uma expresso: que retorne 1 se x > y, 0 se x == y e -1 se x < y.
e = math.exp(1.0)
altura = raio * math.sin(angulo)
Mas at agora, nenhuma das funes que ns 5.2 Desenvolvimento de programas
mesmos escrevemos retornou um valor.
Neste ponto, voc deve estar apto a olhar para funes
Neste captulo, iremos escrever funes que completas e dizer o que elas fazem. Tambm, se voc vem
retornam valores, as quais chamaremos de funes frutferas, fazendo os exerccios, voc escreveu algumas pequenas
ou funes que do frutos, na falta de um nome melhor. O funes. Conforme escrever funes maiores, voc pode
primeiro exemplo area, que retorna a rea de um crculo comear a ter mais dificuldade, especialmente com erros em
dado o seu raio: tempo de execuo (erros de runtime) ou erros semnticos.
import math Para lidar com programas de crescente
complexidade, vamos sugerir uma tcnica chamada
def area(raio): desenvolvimento incremental. A meta do desenvolvimento
temp = math.pi * raio**2 incremental evitar sees de depurao (debugging) muito
longas pela adio e teste de somente uma pequena quantidade
return temp de cdigo de cada vez.
J vimos a instruo return antes, mas em uma
funo frutfera a instruo return inclui um valor de retorno. Como exemplo, suponha que voc queira
Esta instruo significa: "Retorne imediatamente desta funo encontrar a distncia entre dois pontos, dados pelas
e use a expresso em seguida como um valor de retorno". A coordenadas (x1,y1) e (x2,y2). Pelo teorema de Pitgoras, a
expresso fornecida pode ser arbitrariamente complicada, de distncia :
modo que poderamos ter escrito esta funo de maneira mais
concisa:
distancia= x2 x12 y2y12
def area(raio): O primeiro passo considerar como deveria ser
return math.pi * raio**2 uma funo distancia em Python. Em outras palavras, quais
Por outro lado, variveis temporrias como so as entradas (parmetros) e qual a sada (valor de
temp muitas vezes tornam a depurao mais fcil. retorno)?
s vezes til ter mltiplos comandos return, Neste caso, os dois pontos so as entradas, os
um em cada ramo de uma condicional: quais podemos representar usando quatro parmetros. O valor
de retorno a distncia, que um valor em ponto flutuante.
def valorAbsoluto(x):
if x < 0: J podemos escrever um esboo da funo:
return -x def distancia(x1, y1, x2, y2):
else: return 0.0
return x Obviamente, esta verso da funo no computa
J que estes comandos return esto em ramos distncias; ela sempre retorna zero. Mas ela est
alternativos da condicional, apenas um ser executado. To sintaticamente correta, e vai rodar, o que significa que
logo um seja executado, a funo termina sem executar podemos test-la antes de torn-la mais complicada.
qualquer instruo ou comando subseqente.
Para testar a nova funo, vamos cham-la com
O cdigo que aparece depois de uma instruo valores hipotticos:
return, ou em qualquer outro lugar que o fluxo de execuo
jamais alcance, chamado cdigo morto (dead code). >>> distancia(1, 2, 4, 6)
0.0
Em uma funo frutfera, uma boa idia
assegurar que todo caminho possvel dentro do programa Escolhemos estes valores de modo que a
encontre uma instruo return. Por exemplo: distncia horizontal seja igual a 3 e a distncia vertical seja
igual a 4; deste modo, o resultado 5 (a hipotenusa de um
def valorAbsoluto(x): tringulo 3-4-5). Quando testamos uma funo, til
if x < 0: sabermos qual o resultado correto.
return -x Neste ponto, j confirmamos que a funo est
elif x > 0: sintaticamente correta, e podemos comear a adicionar linhas
return x de cdigo. Depois de cada mudana adicionada, testamos a
Este programa no est correto porque se x for funo de novo. Se um erro ocorre em qualquer ponto,
0, nenhuma das condies ser verdadeira, e a funo sabemos aonde ele deve estar: nas linhas adicionadas mais
recentemente.

Captulo 5: Funes frutferas #32


Como pensar como um cientista da Computao usando Python

Um primeiro passo lgico nesta computao parmetros. Registre cada estgio do desenvolvimento
encontrar as diferenas x2 - x1 e y2 - y1. Ns iremos guardar incremental conforme voc avance.
estes valores em variveis temporrias chamadas dx e dy e
imprimi-las:
def distancia(x1, y1, x2, y2): 5.3 Composio
dx = x2 - x1
dy = y2 - y1 Conforme voc poderia esperar agora, voc pode chamar uma
print "dx vale", dx funo de dentro de outra. Esta habilidade chamada de
print "dy vale", dy composio.
return 0.0 Como um exemplo, vamos escrever uma funo
Se a funo estiver funcionando, as sadas que recebe dois pontos, o centro de um crculo e um ponto em
devero ser 3 e 4. Se assim, sabemos que a funo est seu permetro, e calcula a rea do crculo.
recebendo os parmetros corretos e realizando a primeira
computao corretamente. Se no, existem poucas linhas para Assuma que o ponto do centro est guardado
checar. nas variveis xc e yc, e que o ponto do permetro est nas
variveis xp e yp. O primeiro passo encontrar o raio do
Em seguida, computaremos a soma dos crculo, o qual a distncia entre os dois pontos. Felizmente,
quadrados de dx e dy: temos uma funo, distancia, que faz isto:
def distancia(x1, y1, x2, y2): Raio = distancia(xc, yc, xp, yp)
dx = x2 - x1 O segundo passo encontrar a rea de um
dy = y2 - y1 crculo com o raio dado e retorn-la:
dquadrado = dx**2 + dy**2 resultado = area(raio)
print "dquadrado vale: ", dquadrado return resultado
return 0.0
Juntando tudo numa funo, temos:
Note que removemos os comandos print que
havamos escrito no passo anterior. Cdigo como este def area2(xc, yc, xp, yp):
chamado de andaime porque ajuda a escrever o programa, raio = distancia(xc, yc, xp, yp)
mas no parte do produto final. resultado = area(raio)
De novo, ns vamos rodar o programa neste return resultado
estgio e checar a sada (que deveria ser 25). Chamamos esta funo de area2 para
distinguir da funo area, definida anteriormente. S pode
Finalmente, se ns tnhamos importado o existir uma nica funo com um determinado nome em um
mdulo matemtico math, podemos usar a funo sqrt para determinado mdulo.
computar e retornar o resultado:
As variveis temporrias raio e resultado so
def distancia(x1, x2, y1, y2): teis para o desenvolvimento e para depurao (debugging),
dx = x2 - x1 mas uma vez que o programa esteja funcionando, podemos
dy = y2 - y1 torn-lo mais conciso atravs da composio das chamadas de
dquadrado = dx**2 + dy**2 funo:
resultado = math.sqrt(dquadrado) def area2(xc, yc, xp, yp):
return resultado return area(distancia(xc, yc, xp, yp))
Se isto funcionar corretamente, voc conseguiu. Como exerccio, escreva uma funo
Caso contrrio, talvez fosse preciso imprimir (exibir) o valor inclinacao(x1, y1, x2, y2) que retorne a inclinao (ou
de resultado antes da instruo return. coeficienteAngular?) de uma linha dados os pontos (x1, y1) e
Enquanto for iniciante, voc deve acrescentar (x2, y2). Depois use esta funo em uma funo chamada
apenas uma ou duas linhas de cdigo de cada vez. Conforme cortaY(x1, y1, x2, y2) que retorne a interseo da linha com o
ganhar mais experincia, voc se ver escrevendo e depurando eixo y, dados os pontos (x1, y1) e (x2, y2).
pedaos maiores. De qualquer modo, o processo de
desenvolvimento incremental pode poupar um bocado de
tempo de depurao. 5.4 Funes booleanas
Os aspectos chave do processo so:
Funes podem retornar valores booleanos, o que muitas
1. Comece com um programa que funciona e faa vezes conveniente por ocultar testes complicados dentro de
pequenas mudanas incrementais. Em qualquer ponto funes. Por exemplo:
do processo, se houver um erro, voc saber
exatamente onde ele est. def ehDivisivel(x, y):
2. Use variveis temporrias para manter valores If x % y == 0:
intermedirios de modo que voc possa exibi-los e return True # verdadeiro (true), divisvel
chec-los. else:
return False # falso (false), no divisvel
3. Uma vez que o programa funcione, voc pode querer
remover algum cdigo muleta, ou andaime O nome desta funo ehDivisivel ("
(scaffolding) ou consolidar mltiplos comandos divisvel"). comum dar a uma funo booleana nomes que
dentro de expresses compostas, mas somente se isto soem como perguntas sim/no. ehDivisivel retorna ou True ou
no tornar o programa difcil de ler. False para indicar se x ou no divisvel por y.
Como um exerccio, use o desenvolvimento Podemos tornar a funo mais concisa se
incremental para escrever uma funo chamada hipotenusa tirarmos vantagem do fato de a condio da instruo if ser ela
que retorna a medida da hipotenusa de um tringulo mesma uma expresso booleana. Podemos retorn-la
retngulo dadas as medidas dos dois catetos como diretamente, evitando totalmente o if:

Captulo 5: Funes frutferas #33


Como pensar como um cientista da Computao usando Python

def ehDivisivel(x, y): def fatorial(n):


return x % y == 0 Se acontece de o argumento ser 0, tudo o que
Esta sesso mostra a nova funo em ao: temos de fazer retornar 1:
>>> ehDivisivel(6, 4) def fatorial(n):
False if n == 0:
>>> ehDivisivel(6, 3) return 1
True Por outro lado, e esta a parte interessante,
Funes booleanas so freqentemente usadas temos que fazer uma chamada recursiva para encontrar o
em comandos condicionais: fatorial de n-1 e ento multiplic-lo por n:
if ehDivisivel(x, y): def fatorial(n):
print "x divisvel por y" if n == 0:
else: return 1
print "x no divisvel por y" else:
recursivo = fatorial(n-1)
Mas a comparao extra desnecessria.
resultado = n * recursivo
Como exerccio, escreva uma funo return resultado
estaEntre(x, y, z) que retorne True se y < x < z ou False se O fluxo de execuo para este programa
no. 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
5.5 Mais recursividade calculamos o fatorial de n-1 ...
At aqui, voc aprendeu apenas um pequeno subconjunto da J que 2 no 0, tomamos o segundo ramo e
linguagem Python, mas pode ser que te interesse saber que calculamos o fatorial de n-1 ...
este pequeno subconjunto uma linguagem de programao J que 1 no 0, tomamos o segundo ramo e
completa, o que significa que qualquer coisa que possa ser calculamos o fatorial de n-1 ...
computada pode ser expressa nesta linguagem. Qualquer
programa j escrito pode ser reescrito usando somente os J que 0 0, tomamos o primeiro ramo e
aspectos da linguagem que voc aprendeu at agora retornamos 1 sem fazer mais qualquer chamada recursiva.
(usualmente, voc precisaria de uns poucos comandos para
controlar dispositivos como o teclado, mouse, discos, etc., mas O valor retornado (1) multiplicado por n, que
isto tudo). 1, e o resultado retornado.
Provar esta afirmao um exerccio nada O valor retornado (1) multiplicado por n, que
trivial, que foi alcanado pela primeira vez por Alan Turing, 2, e o resultado retornado.
um dos primeiros cientistas da computao (algum poderia
dizer que ele foi um matemtico, mas muitos dos primeiros O valor retornado (2) multiplicado por n, que
cientistas da computao comearam como matemticos). Por 1, e o resultado, 6, se torna o valor de retorno da chamada de
isso, ficou conhecido como Tese de Turing. Se voc fizer um funo que iniciou todo o processo.
curso em Teoria da Computao, voc ter chance de ver a Eis o diagrama de pilha para esta seqncia de
prova. chamadas de funo:
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:
Os valores de retorno so mostrados sendo
0! = 1 passados de volta para cima da pilha. Em cada quadro, o valor
n! = n.(n-1)! de retorno o valor de resultado, o qual o produto de n por
recursivo.
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")
5.6 Voto de confiana (Leap of faith)
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. Seguir o fluxo de execuo uma maneira de ler programas,
mas que pode rapidamente se transformar em um labirinto.
Se voc pode escrever uma definio recursiva Uma alternativa o que chamamos de "voto de confiana".
de alguma coisa, voc geralmente pode escrever um programa Quando voc tem uma chamada de funo, em vez de seguir o
em Python para execut-la. O primeiro passo decidir quais fluxo de execuo, voc assume que a funo funciona
so os parmetros para esta funo. Com pouco esforo, voc corretamente e retorna o valor apropriado.
dever concluir que fatorial recebe um nico parmetro:

Captulo 5: Funes frutferas #34


Como pensar como um cientista da Computao usando Python

De fato, voc est agora mesmo praticando este RuntimeError: Maximum recursion depth exceeded
voto de confiana ao usar as funes nativas. Quando voc Parece um caso de recursividade infinita. Mas o
chama math.cos ou math.exp, voc no examina a que ser que de fato? Existe um caso base -- quando n == 0.
implementao destas funes. Voc apenas assume que elas O problema que o valor de n nunca encontra o caso base.
funcionam porque as pessoas que escreveram as bibliotecas
nativas eram bons programadores. Na primeira chamada recursiva, o valor de n
0.5. Na prxima, ele igual a -0.5. Da em diante, ele se torna
O mesmo tambm verdade quando voc cada vez menor, mas jamais ser 0.
chama uma de suas prprias funes. Por exemplo, na Seo
5.4, escrevemos a funo chamada ehDivisivel que determina Temos ento duas alternativas. Podemos tentar
se um nmero divisvel por outro. Uma vez que nos generalizar a funo fatorial para que funcione com nmeros
convencemos que esta funo est correta -- ao testar e em ponto flutuante, ou fazemos fatorial realizar a checagem
examinar o cdigo -- podemos usar a funo sem examinar o de tipo de seus parmetros. A primeira chamada funo
cdigo novamente. gamma e est um pouco alm do escopo deste livro. Sendo
assim, ficaremos com a segunda.
O mesmo tambm verdadeiro para programas
recursivos. Quando voc tem uma chamada recursiva, em vez Podemos usar type para comparar o tipo do
de seguir o fluxo de execuo, voc poderia assumir que a parmetro com o tipo de um valor inteiro conhecido (como 1).
chamada recursiva funciona (produz o resultado correto) e Ao mesmo tempo em que fazemos isto, podemos nos
ento perguntar-se, "Assumindo que eu possa encontrar o certificar tambm de que o parmetro seja positivo:
fatorial de n-1, posso calcular o fatorial de n?" Neste caso,
claro que voc pode, multiplicando por n. def fatorial (n):
if type(n) != type(1):
Naturalmente, um pouco estranho que uma print "Fatorial somente definido para
funo funcione corretamente se voc ainda nem terminou de
escrev-la, mas por isso que se chama voto de confiana! inteiros."
return -1
elif n < 0:
print "Fatorial somente definido para inteiros\
5.7 Mais um exemplo positivos."
return -1
No exemplo anterior, usamos variveis temporrias para elif n ==0:
explicitar (spell out XXX) os passos e tornar o cdigo mais
fcil de depurar, mas poderamos ter economizado algumas return 1
linhas: else:
return n * fatorial(n-1)
def fatorial(n):
Agora temos trs casos base. O primeiro pega os
if n == 0: no-inteiros. O segundo pega os inteiros negativos. Em ambos
return 1 os casos, o programa exibe uma mensagem de erro e retorna
else: um valor especial, -1, para indicar que alguma coisa saiu
return n * fatorial(n-1) errada:
De agora em diante, tenderemos a utilizar um >>> fatorial ("Fred")
formato mais conciso, mas recomendamos que voc use a Fatorial somente definido para inteiros.
verso mais explcita enquanto estiver desenvolvendo cdigo.
Quando ele estiver funcionando, voc pode enxug-lo se -1
estiver se sentindo inspirado. >>> fatorial (-2)
Fatorial somente definido para inteiros positivos.
Depois de fatorial, o exemplo mais comum de
uma funo matemtica definida recursivamente fibonacci, a -1
qual tem a seguinte definio: Se passarmos pelas duas checagens, ento
saberemos que n um inteiro positivo, e poderemos provar
fibonacci(0) = 1 que a recursividade encontra seu trmino.
fibonacci(1) = 1
Este programa demonstra um padro (pattern)
fibonacci(n) = fibonacci(n-1) + fibonacci(n-2); chamado s vezes de guardio. As duas primeiras
Traduzido em Python, parecer assim: condicionais atuam como guardis, protegendo o cdigo que
vem em seguida de valores que poderiam causar um erro. Os
def fibonacci(n): guardies tornam possvel garantir a correo do cdigo.
if n == 0 or n == 1:
return 1
else:
5.9 Glossrio
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. funo frutfera Uma funo que produz um valor de
Mas, de acordo com o voto de confiana, se voc assume que (fruitful function) retorno.
as duas chamadas recursivas funcionam corretamente, ento valor de retorno O valor entregue como resultado de uma
claro que voc ter o resultado correto ao junt-las. (return value) chamada de funo.
varivel Uma varivel usada para guardar um
temporria valor intermedirio em um clculo
5.8 Checagem de tipos (temporary complexo.
variable)
O que acontece se chamamos fatorial e damos a ela 1.5 como
argumento?: cdigo morto Parte de um programa que nunca pode
(dead code) ser executada, muitas vezes por que ela
>>> fatorial (1.5) aparece depois de uma instruo return.

Captulo 5: Funes frutferas #35


Como pensar como um cientista da Computao usando Python

None Um valor especial em Python, retornado


por funes que no possuem uma
instruo return ou tm uma instruo
return sem argumento.
desenvolvimento Uma estratgia de desenvolvimento de
incremental programas que evita a depurao ao
(incremental adicionar e testar somente uma pequena
development) quantidade de cdigo de cada vez.
andaime Cdigo usado durante o
(scaffolding) desenvolvimento do programa, mas que
no faz parte do produto final.
guardio Uma condio que checa e manipula
(guardian) circunstncias que poderiam causar um
erro.

Captulo 5: Funes frutferas #36


Como pensar como um cientista da Computao usando Python

Captulo 6: Iterao

Vimos dois programas, nLinhas e


6.1 Reatribuies contagemRegressiva, que usam recursividade (recurso) para
fazer a repetio, que tambm chamada iterao. Porque a
Como voc talvez j tenha descoberto, permitido fazer mais iterao muito comum, Python tem vrias caractersticas
de uma atribuio mesma varivel. Uma nova atribuio faz para torn-la mais fcil. A primeira delas em que vamos dar
uma varivel existente referir-se a um novo valor (sem se uma olhada o comando while.
referir mais ao antigo).:
Aqui est como fica contagemRegressiva com
bruno = 5 um comando while:
print bruno, def contagemRegressiva(n):
bruno = 7 while n > 0:
print bruno print n
A sada deste programa 5 7, porque na n = n-1
primeira vez que bruno impresso, seu valor 5 e na segunda print "Fogo!"
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. Desde que removemos a chamada recursiva,
Veja uma reatribuio em um diagrama de esta funo no recursiva.
estado: 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.
Com a reatribuio torna-se ainda mais 2. Se a condio for falsa (0), saia do comando while e
importante distinguir entre uma operao de atribuio e um continue a execuo a partir do prximo comando.
comando de igualdade. Como Python usa o sinal de igual ( = )
para atribuio, existe a tendncia de lermos um comando 3. Se a condio for verdadeira (1), execute cada um
como a = b como um comando de igualdade. Mas no ! dos comandos dentro do corpo e volte ao passo 1.
Em primeiro lugar, igualdade comutativa e O corpo consiste de todos os comandos abaixo
atribuio no . Por exemplo, em matemtica, se a = 7 ento do cabealho, com a mesma endentao.
7 = a. Mas em Python, o comando a = 7 permitido e 7 = a Este tipo de fluxo chamado de um loop (ou
no . lao) porque o terceiro passo cria um "loop" ou um lao de
Alm disso, em matemtica, uma expresso de volta ao topo. Note que se a condio for falsa na primeira vez
igualdade sempre verdadeira. Se a = b agora, ento, a ser que entrarmos no loop, os comandos dentro do loop jamais
sempre igual a b. Em Python, um comando de atribuio pode sero executados.
tornar duas variveis iguais, mas elas no tm que permanecer O corpo do loop poderia alterar o valor de uma
assim: ou mais variveis de modo que eventualmente a condio se
a = 5
torne falsa e o loop termine. Se no for assim, o loop se
repetir para sempre, o que chamado de um loop infinito.
b = a # a e b agora so iguais Uma fonte de diverso sem fim para os cientistas da
b = 3 # a e b no so mais iguais computao a observao de que as instrues da
A terceira linha muda o valor de a mas no embalagem de shampoo, "Lave, enxge, repita" um loop
muda o valor de b, ento, elas no so mais iguais. (Em infinito.
algumas linguagens de programao, um smbolo diferente
usado para atribuio, como <- ou :=, para evitar confuso.) No caso de contagemRegressiva, podemos
provar que o loop terminar porque sabemos que o valor de n
Embora a reatribuio seja freqentemente til, finito, e podemos ver que o valor de n diminui dentro de
voc deve us-la com cautela. Se o valor das variveis muda cada repetio (iterao) do loop, ento, eventualmente
freqentemente, isto pode fazer o cdigo difcil de ler e de chegaremos ao 0. Em outros casos, isto no to simples de
depurar. afirmar:
def sequencia(n):
while n != 1:
6.2 O comando while print n,
if n%2 == 0: # n par
Os computadores so muito utilizados para automatizar tarefas n = n/2
repetitivas. Repetir tarefas idnticas ou similares sem cometer else: # n impar
erros uma coisa que os computadores fazem bem e que as
pessoas fazem poorly. n = n*3+1

Captulo 6: Iterao #37


Como pensar como um cientista da Computao usando Python

A condio para este loop n != 1, ento o loop 1.0 0.0


vai continuar at que n seja 1, o que tornar a condio falsa. 2.0 0.69314718056
Dentro de cada repetio (iterao) do loop, o 3.0 1.09861228867
programa gera o valor de n e ento checa se ele par ou 4.0 1.38629436112
impar. Se ele for par, o valor de n dividido por 2. Se ele for 5.0 1.60943791243
impar, o valor substitudo por n*3+1. Por exemplo, se o 6.0 1.79175946923
valor inicial (o argumento passado para seqncia) for 3, a 7.0 1.94591014906
seqncia resultante ser 3, 10, 5, 16, 8, 4, 2, 1.
8.0 2.07944154168
J que n s vezes aumenta e s vezes diminui, 9.0 2.19722457734
no existe uma prova bvia de que n jamais venha a alcanar Se estes valores parecem odd, lembre-se que a
1, ou de que o programa termine. Para alguns valores funo log usa a base e. J que potncias de dois so to
particulares de n, podemos provar o trmino. Por exemplo, se importantes em cincia da computao, ns freqentemente
o valor inicial for uma potncia de dois, ento o valor de n temos que achar logaritmos referentes base 2. Para fazermos
ser par dentro de cada repetio (iterao) do loop at que isso, podemos usar a seguinte frmula:
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! Alterando o comando de sada para:
Como um exerccio, reescreva a funo nLinhas print x, '\t', math.log(x)/math.log(2.0)
da seo 4.9 usando iterao em vez de recurso. o que resultar em:
1.0 0.0
2.0 1.0
6.3 Tabelas 3.0 1.58496250072
4.0 2.0
Uma das coisas para qual os loops so bons para gerar dados 5.0 2.32192809489
tabulares. Antes que os computadores estivessem readily
disponveis, as pessoas tinham que calcular logaritmos, senos, 6.0 2.58496250072
cossenos e outras funes matemticas mo. Para tornar isto 7.0 2.80735492206
mais fcil, os livros de matemtica continham longas tabelas 8.0 3.0
listando os valores destas funes. Criar as tabelas era 9.0 3.16992500144
demorado e entediante, e elas tendiam a ser cheias de erros.
Podemos ver que 1, 2, 4 e 8 so potncias de
Quando os computadores entraram em cena, dois porque seus logaritmos na base 2 so nmeros redondos.
uma das reaes iniciais foi "Isto timo! Podemos usar Se precisssemos encontrar os logaritmos de outras potncias
computadores para geras as tabelas, assim no haver erros." de dois, poderamos modificar o programa deste modo:
Isto veio a se tornar verdade (na maioria das vezes) mas
shortsighted. Rapidamente, porm, computadores e x = 1.0
calculadoras tornaram-se to pervasivos que as tabelas ficaram while x < 100.0:
obsoletas. print x, '\t', math.log(x)/math.log(2.0)
x = x * 2.0
Bem, quase. Para algumas operaes, os
computadores usam tabelas de valores para conseguir uma Agora, em vez de somar algo a x a cada iterao
resposta aproximada e ento realizar clculos para melhorar a do loop, o que resulta numa seqncia aritmtica, ns
aproximao. Em alguns casos, tm havido erros nas tabelas multiplicamos x por algo, resultando numa seqncia
underlying, o caso mais famoso sendo o da tabela usada pelo geomtrica. O resultado :
processador Pentium da Intel para executar a diviso em
ponto-flutuante. 1.0 0.0
2.0 1.0
Embora uma tabela de logaritmos no seja mais 4.0 2.0
to til quanto j foi um dia, ela ainda d um bom exemplo de 8.0 3.0
iterao. O seguinte programa gera uma seqncia de valores
na coluna da esquerda e seus respectivos logaritmos na coluna 16.0 4.0
da direita: 32.0 5.0
64.0 6.0
x = 1.0 Por causa do caractere de tabulao entre as
while x < 10.0: colunas, a posio da segunda coluna no depende do nmero
print x, '\t', math.log(x) de dgitos na primeira coluna.
x = x + 1.0
Tabelas de logaritmos podem no ser mais teis,
A string '\t' representa um caracterde mas para cientistas da computao, conhecer as potncias de
tabulao. dois !
Conforme caracteres e strings vo sendo Como um exerccio, modifique este programa
mostrados na tela, um ponteiro invisvel chamado cursor de modo que ele produza as potncias de dois acima de 65.535
marca aonde aparecer o prximo caractere. Depois de um (ou seja, 216). Imprima e memorize-as.
comando print, o cursor normalmente vai para o incio de uma
nova linha. O caractere de barra invertida em '\t' indica o
incio de uma seqncia de escape. Seqncias de escape so
O caractere de tabulao desloca o cursor para a usadas para representar caracteres invisveis como de
direita at que ele encontre uma das marcas de tabulao. tabulao e de nova linha. A seqncia \n representa uma nova
Tabulao til para fazer colunas de texto line up, como na linha.
sada do programa anterior:

Captulo 6: Iterao #38


Como pensar como um cientista da Computao usando Python

Uma seqncia de escape pode aparecer em Se chamarmos esta funo com o argumento 2,
qualquer lugar em uma string; no exemplo, a seqncia de teremos a mesma sada que antes. Com o argumento 3, a sada
escape de tabulao a nica coisa dentro da string. :
Como voc acha que se representa uma barra 3 6 9 12 15 18
invertida em uma string? Com o argumento 4, a sada :
Como um exerccio, escreva um nica string 4 8 12 16 20 24
que
Agora voc provavelmente pode adivinhar
produza como imprimir uma tabela de multiplicao - chamando
esta imprimeMultiplos repetidamente com argumentos diferentes.
sada.
De fato, podemos usar um outro loop:
i = 1
while i <= 6:
6.4 Tabelas de duas dimenses (ou bi-dimensionais) imprimeMultiplos(i)
i = i + 1
Uma tabela de duas dimenses uma tabela em que voc l o Note o quanto este loop parecido com aquele
valor na interseo entre uma linha e uma coluna. Uma tabela dentro de imprimeMultiplos. Tudo o que fiz foi substituir o
de multiplicao um bom exemplo. Digamos que voc comando print pela chamada funo.
queira imprimir uma tabela de multiplicao de 1 a 6.
A sada deste programa uma tabela de
Uma boa maneira de comear escrever um multiplicao:
loop que imprima os mltiplos de 2, todos em uma linha:
1 2 3 4 5 6
i = 1 2 4 6 8 10 12
while i <= 6: 3 6 9 12 15 18
print 2*i, ' ', 4 8 12 16 20 24
i = i + 1 5 10 15 20 25 30
print 6 12 18 24 30 36
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 6.6 Mais encapsulamento
repetio (iterao) do loop, mostrado o valor de 2*i,
seguido de trs espaos. Para demonstrar de novo o encapsulamento, vamos pegar o
cdigo do final da seo 6.5 e acondicion-lo, envolv-lo em
De novo, a vrgula no comando print suprime a uma funo:
nova linha. Depois que o loop se completa, o segundo
comando print inicia uma nova linha. def imprimeTabMult():
A sada do programa : i = 1
while i <= 6:
2 4 6 8 10 12 imprimeMultiplos(i)
At aqui, tudo bem. O prximo passo i = i + 1
encapsular e generalizar. Este processo um plano de desenvolvimento
comum. Ns desenvolvemos cdigo escrevendo linhas de
cdigo fora de qualquer funo, ou digitando-as no
6.5 Encapsulamento e generalizao interpretador. Quando temos o cdigo funcionando, extramos
ele e o embalamos em uma funo.
Encapsulamento o processo de wrapping um pedao de Este plano de desenvolvimento
cdigo em uma funo, permitindo que voc tire vantagem de particularmente til se voc no sabe, quando voc comea a
todas as coisas para as quais as funes so boas. Voc j viu escrever, como dividir o programa em funes. Esta tcnica
dois exemplos de encapsulamento: imprimeParidade na seo permite a voc projetar enquanto desenvolve.
4.5; e eDivisivel na seo 5.4
Generalizao significa tomar algo que
especfico, tal como imprimir os mltiplos de 2, e torn-lo 6.7 Variveis locais
mais geral, tal como imprimir os mltiplos de qualquer inteiro.
Esta funo encapsula o loop anterior e Voc pode estar pensando como podemos utilizar a mesma
generaliza-o para imprimir mltiplos de n: varivel, i, em ambos, imprimeMultiplos e imprimeTabMult.
Isto no causaria problemas quando uma das funes mudasse
def imprimeMultiplos(n): o valor da varivel?
i = 1 A resposta no, porque o i em
while i <= 6: imprimeMultiplos e o i em imprimeTabMult no so a mesma
print n*i, '\t ', varivel.
i = i + 1
Variveis criadas dentro de uma definio de
print funo so locais; voc no pode acessar uma varivel local
Para encapsular, tudo o que tivemos que fazer de fora da funo em que ela "mora". Isto significa que voc
foi adicionar a primeira linha, que declara o nome de uma livre para ter mltiplas variveis com o mesmo nome, desde
funo e sua lista de parmetros. Para generalizar, tudo o que que elas no estejam dentro da mesma funo.
tivemos que fazer foi substituir o valor 2 pelo parmetro n.
O diagrama de pilha para este programa mostra

Captulo 6: Iterao #39


Como pensar como um cientista da Computao usando Python

que duas variveis chamadas i no so a mesma varivel. Elas def imprimeMultiplos(n, altura):
podem se referir a valores diferentes e alterar o valor de uma i = 1
no afeta outra. 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:
O valor de i em imprimeTabMult vai de 1 a 6. 1 2 3 4 5 6 7
No diagrama, i agora 3. Na prxima iterao do loop i ser 2 4 6 8 10 12 14
4. A cada iterao do loop, imprimeTabMult chama 3 6 9 12 15 18 21
imprimeMultiplos com o valor corrente de i como argumento.
O valor atribudo ao parmetro n. 4 8 12 16 20 24 28
5 10 15 20 25 30 35
Dentro de imprimeMultiplos, o valor de i vai de 6 12 18 24 30 36 42
1 a 6. No diagrama, i agora 2. Mudar esta varivel no tem 7 14 21 28 35 42 49
efeito sobre o valor de i em imprimeTabMult.
Quando voc generaliza uma funo
comum e perfeitamente legal ter variveis apropriadamente, voc muitas vezes tem um programa com
locais diferentes com o mesmo nome. Em particular, nomes capacidades que voc no planejou. Por exemplo, voc pode
como i e j so muito usados para variveis de controle de ter notado que, porque ab = ba, todas as entradas na tabela
loop. Se voc evitar utiliz-los em uma funo s porque voc aparecem duas vezes. Voc poderia economizar tinta
j os usou em outro lugar, voc provavelmente tornar seu imprimindo somente a metade da tabela. Para fazer isso, voc
programa mais difcil de ler. tem que mudar apenas uma linha em imprimeTabMult. Mude:
imprimeTabMult(i, altura)
para:
6.8 Mais generalizao
imprimeTabMult(i, i)
Como um outro exemplo de generalizao, imagine que voc e voc ter:
precise de um programa que possa imprimir uma tabela de
multiplicao de qualquer tamanho, no apenas uma tabela de 1
seis por seis. Voc poderia adicionar um parmetro a 2 4
imprimeTabMult: 3 6 9
def imprimeTabMult(altura): 4 8 12 16
i = 1 5 10 15 20 25
while i <= altura: 6 12 18 24 30 36
imprimeMultiplos(i) 7 14 21 28 35 42 49
i = i + 1 Como um exerccio, trace a execuo desta
Ns substitumos o valor 6 pelo parmetro verso de imprimeTabMult e explique como ela funciona.
altura. Se chamarmos imprimeTabMult com o argumento 7,
ela mostra:
1 2 3 4 5 6
6.9 Funes
2 4 6 8 10 12
H pouco tempo mencionamos "todas as coisas para
3 6 9 12 15 18 as quais as funes so boas." Agora, voc pode estar
4 8 12 16 20 24 pensando que coisas exatamente so estas. Aqui esto
5 10 15 20 25 30 algumas delas:
6 12 18 24 30 36
Dar um nome para uma seqncia de comandos torna
7 14 21 28 35 42 seu programa mais fcil de ler e de depurar.
Isto bom, exceto que ns provavelmente
quereramos que a tabela fosse quadrada - com o mesmo Dividir um programa longo em funes permite que
nmero de linhas e colunas. Para fazer isso, adicionamos voc separe partes do programa, depure-as
outro parmetro a imprimeMultiplos para especificar quantas isoladamente, e ento as componha em um todo.
colunas a tabela deveria ter.
Funes facilitam tanto recurso quanto iterao.
S para confundir, chamamos este novo
parmetro de altura, demonstrando que diferentes funes Funes bem projetadas so freqentemente teis
podem ter parmetros com o mesmo nome (como acontece para muitos programas. Uma vez que voc escreva e
com as variveis locais). Aqui est o programa completo: depure uma, voc pode reutiliz-la.

Captulo 6: Iterao #40


Como pensar como um cientista da Computao usando Python

6.10 Glossrio

reatribuio quando mais de um valor atribudo a


(multiple mesma varivel durante a execuo do
assignment 1) programa.
iterao execuo repetida de um conjunto de
(iteration) 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 um lao em que a condio de interrupo
(infinite loop) nunca ser atingida.
corpo (body) o conjunto de comandos/instrues que
pertencem a um lao.
varivel de lao uma varivel usada como parte da
(loop variable) 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 um carcter especial que faz com que o
(newline) 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 um carcter de escape () seguido por um
escape (escape ou mais caracteres imprimveis, usados
sequence) para definir um carcter no imprimvel.
encapsular quando um programa grande e complexo
(encapsulate) dividido em componentes (como
funes) e estes so isolados um do outro
(pelo uso de variveis locais, por
exemplo).
generalizar quando algo que desnecessariamente
(generalize) 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 um processo definido para
desenvolviment desenvolvimento de um programa. Neste
o (development captulo, ns demonstramos um estilo de
plan) desenvolvimento baseado em escrever
cdigo para executar tarefas simples e
especficas, usando encapsulamento e
generalizao.

1 N.T.: O termo multiple assignment (ou atribuio mltipla)


usado com mais frequncia para descrever a sintaxe a = b
= c. Por este motivo optamos pelo termo reatribuio no
contexto da seo 6.1 desse captulo.

Captulo 6: Iterao #41


Como pensar como um cientista da Computao usando Python

Captulo 7: Strings

de comprimento:
7.1 Um tipo de dado composto
comprimento = len(fruta)
At aqui, vimos trs diferentes tipos de dado: int, float e ultima = fruta[comprimento-1]
string. Strings so qualitativamente diferentes dos outros dois Como alternativa, podemos usar ndices
tipos porque so feitas de pedaos menores - caracteres. negativos, os quais contam de trs pra frente os elementos da
string. A expresso fruta[-1] resulta a ltima letra, fruta[-2]
Tipos que consistem de pedaos menores so resulta a penltima (a segunda de trs para frente), e assim por
chamados tipos de dados compostos. Dependendo do que diante.
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
7.3 Travessia e o loop for
caractere de uma string.:
Vrias computaes envolvem o processamento de uma string
>>> fruta = "banana" um caractere de cada vez. Muitas vezes elas comeam com o
>>> letra = fruta[1] primeiro, selecionam um de cada vez, fazem alguma coisa
>>> print letra com ele, e continuam at o fim. Este padro de processamento
chamado uma travessia (traversal, com a idia de
A expresso fruta[1] seleciona o caractere "percorrimento"). Uma maneira de codificar uma travessia
nmero 1 de fruta. A varivel letra referencia ou refere-se ao com um comando while:
resultado da expresso. Quando exibimos letra, temos uma
surpresa: indice = 0
while indice < len(fruta):
a
letra = fruta[indice]
A primeira letra de "banana" no a. A menos
que voc seja um cientista da computao. Neste caso, voc print letra
deve entender a expresso dentro dos colchetes como um indice = indice + 1
deslocamento (offset,) a partir do comeo da string, e o Este loop percorre a string e exibe cada letra em
deslocamento da primeira letra zero. Assim, b a 0 ("zero- sua prpria linha. A condio do loop indice < len(fruta),
sima") letra de "banana", a a 1 ("um-sima", diferente de assim, quando ndice igual ao comprimento da string, a
primeira), e n a 2 ("dois-sima", diferente de segunda) letra. condio se torna falsa, e o corpo do loop no executado. O
ltimo caractere acessado aquele com o ndice len(fruta)-1,
Para pegar a primeira letra de uma string, voc que vem a ser o ltimo caractere da string.
simplesmente pe 0, ou qualquer expresso que resulte o valor
0, dentro dos colchetes: Como um exerccio, escreva uma funo que
tome uma string como argumento e devolva suas letras de
>>> letra = fruta[0] trs para frente, uma por linha.
>>> print letra
b Usar um ndice para percorrer um conjunto de
valores to comum que Python oferece uma sintaxe
A expresso entre colchetes chamada de alternativa simplificada - o loop for:
ndice. Um ndice especifica um membro de um conjunto
ordenado, neste caso o conjunto de caracteres da string. O for char in fruta:
ndice indica aquele membro que voc quer, da seu nome. Ele print char
pode ser qualquer expresso inteira.
A cada vez atravs do loop, o prximo caractere
da string atribudo varivel char. O loop continua at que
no reste mais caracteres.
7.2 Comprimento O exemplo seguinte mostra como usar
concatenao e um loop for para gerar uma srie abecedrio.
A funo len retorna o nmero de caracteres de uma string: "Abecedrio" se refere a uma srie ou lista na qual os
elementos aparecem em ordem alfabtica. Por exemplo, no
>>> fruta = "banana" livro de Robert McCloskey's Make Way for Ducklings, os
>>> len(fruta) nomes dos "ducklings" so Jack, Kack, Lack, Mack, Nack,
6 Ouack, Pack e Quack. O loop seguinte, produz como sada
Para pegar a ltima letra de uma string, voc aqueles nomes, em ordem:
pode ficar tentado a fazer alguma coisa assim:
prefixos = "JKLMNOPQ"
comprimento = len(fruta) sufixo = "ack"
ultima = fruta[comprimento] # ERRO!
No vai funcionar. Isto vai causar o seguinte for letra in prefixos:
erro em tempo de execuo (runtime error): IndexError: string print letra + sufixo
index out of range. (ErroDeIndice: ndice da string fora do A sada deste programa :
intervalo). A razo que no existe 6 letra em "banana". J
que comeamos a contar do zero, as seis letras so numeradas Jack
de 0 a 5. Para pegar o ltimo caractere, temos que subtrair 1 Kack

Captulo 7: Strings #42


Como pensar como um cientista da Computao usando Python

Lack else:
Mack print "Sim, ns no temos bananas!"
Nack Entretanto, voc deve atentar para o fato de que
Oack Pyhton no manipula letras maisculas e minsculas da
Pack mesma maneira que as pessoas o fazem. Todas as letras
Qack
maisculas vm antes das minsculas. Como resultado:
Naturalmente, esta sada no est cem por cento Sua palavra, Zebra, vem antes de banana.
certa porque "Ouack" e "Quack" esto escritos de maneira Uma maneira comum de resolver este problema
errada. converter as strings para um formato padro, seja todas
Como um exerccio, modifique o programa para minsculas, ou todas maisculas, antes de realizar a
corrigir este erro. comparao. Um problema mais difcil fazer o programa
perceber que zebras no so frutas.

7.4 Fatias de strings 7.6 Strings so imutveis


Um segmento de uma string chamado de uma fatia.
Selecionar uma fatia similar a selecionar um caractere: tentador usar o operador [] no lado esquerdo de uma
expresso de atribuio, com a inteno de alterar um
>>> s = "Pedro, Paulo e Maria" caractere em uma string. Por exemplo:
>>> print s[0:5] saudacao = "Al, mundo!"
Pedro saudacao[0] = 'E' # ERRO!
>>> print s[7:12] print saudacao
Paulo
Em vez de produzir a sada El, Mundo!, este
>>> print s[16:21] cdigo produz o erro em tempo de execuo (runtime error):
Maria TypeError: object doesn't support item assignment
O operador [n:m] retorna a parte da string do (ErroDeTipo: objeto no d suporte atribuio de item.)
"n-simo" caractere ao "m-simo" caractere, incluindo o
primeiro mas excluindo o ltimo. Este comportamento no Strings so imutveis, o que significa que voc
intuitivo; ele faz mais sentido se voc imaginar os ndices no pode mudar uma string que j existe. O melhor que voc
apontando para os intervalos entre os caracteres, como no pode fazer criar uma nova string que seja uma variao da
seguinte diagrama: 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.

Se voc omitir o primeiro ndice (antes dos dois 7.7 Uma funo find (encontrar)
pontos ":"), a fatia comea do incio da string. Se voc omitir
o segundo ndice, a fatia vai at o final da string. Assim: O que faz a seguinte funo?:
>>> fruta = "banana" def find(str, ch):
>>> fruta[:3] indice = 0
'ban' while indice < len(str):
>>> fruta[3:] if str[indice] == ch:
'ana' return indice
O que voc acha de s[:] significa? indice = indice + 1
return -1
Num certo sentido, find (encontrar) o oposto
7.5 Comparao de strings 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
O operador de comparao funciona com strings. Para ver se no encontrado, a funo retorna -1.
duas strings so iguais:
Este o primeiro exemplo que vemos de uma
if palavra == "banana": instruo return dentro de um loop. Se str[indice] == ch, a
print "Sim, ns no temos bananas!" funo retorna imediatamente, abandonando o loop
Outras operaes de comparao so teis para prematuramente.
colocar palavras em ordem alfabtica:
Se o caractere no aparece na string, ento o
if palavra < "banana": programa sai do loop normalmente e retorna -1.
print "Sua palavra," + palavra + ", vem antes de\ Este padro de computao s vezes chamado
banana." de travessia "eureka", porque to logo ele encontra (find) o
elif palavra > "banana": que est procurando, ele pode gritar "Eureka!" e parar de
print "Sua palavra," + palavra + ", vem depois \ procurar.
de banana." Como um exerccio, modifique a funo find

Captulo 7: Strings #43


Como pensar como um cientista da Computao usando Python

(encontrar) de modo que ela receba um terceiro parmetro, o Neste exemplo, a busca falha porque a letra b
ndice da string por onde ela deve comear sua procura. no aparece no intervalo entre 1 e 2 (no incluindo o 2) do
ndice.

7.8 Iterando e contando


7.10 Classificao de caracteres
O programa seguinte conta o nmero e vezes que a letra a
aparece em uma string: Muitas vezes til examinar um caractere e testar se ele
maisculo ou minsculo, ou se ele um caractere ou um
fruta = "banana" dgito. O mdulo string oferece vrias constantes que so teis
contador = 0 para esses propsitos.
for letra in fruta:
A string string.lowercase contm todas as letras
if letra == 'a' que o sistema considera como sendo minsculas.
contador = contador + 1 Similarmente, string.uppercase contm todas as letras
print contador maisculas. Tente o seguinte e veja o que voc obtm:
Este programa demonstra um outro padro de
computao chamado de contador. A varivel contador >>> print string.lowercase
inicializada em 0 e ento incrementada cada vez que um a >>> print string.uppercase
encontrado. (Incrementar o mesmo que aumentar em um; >>> print string.digits
o oposto de decrementar, e no tem relao com excremento, Ns podemos usar essas constantes e find
que um substantivo.) Quando se sai do loop, contador (encontrar) para classificar caracteres. Por exemplo, se
guarda o resultado - o nmero total de a's. find(lowercase, ch) retorna um valor outro que no -1, ento
ch deve ser minsculo:
Como um exerccio, encapsule este cdigo em
uma funo chamada contaLetras, e generalize-a de modo def eMinusculo(ch):
que possa aceitar uma string e uma letra como parmetros. return string.find(string.lowercase, ch) != -1
Como um segundo exerccio, reescreva esta Como uma alternativa, podemos tirar vantagem
funo de modo que em vez de percorrer a string, ela use a do operador in, que determina se um caractere aparece em
verso com trs parmetros de find (encontrar) da seo uma string:
anterior.
def eMinusculo(ch):
return ch in string.lowercase
7.9 O mdulo string Ainda, como uma outra alternativa, podemos
usar o operador de comparao:
O mdulo string contm funes teis que manipulam strings. def eMinusculo(ch):
Conforme usual, ns temos que importar o mdulo antes que return 'a' <= ch <= 'z'
possamos utiliz-lo: Se ch estiver entre a e z, ele deve ser uma letra
>>> import string
minscula.
O mdulo string inclui uma funo chamada Como um exerccio, discuta que verso de
find (encontrar) que faz a mesma coisa que a funo que eMinusculo voc acha que ser a mais rpida. Voc pode
escrevemos. Para cham-la, temos que especificar o nome do pensar em outras razes alm da velocidade para preferir
mdulo e o nome da funo usando a notao de ponto.: uma em vez de outra?
>>> fruta = "banana" Outra constante definida no mdulo string pode
>>> indice = string.find(fruta, "a") te surpreender quando voc executar um print sobre ela:
>>> print indice >>> print string.whitespace
1 Caracteres de espaamento (ou espaos em
Este exemplo demonstra um dos benefcios dos branco) movem o cursor sem "imprimir" qualquer coisa. Eles
mdulos - eles ajudam a evitar colises entre nomes de criam os espaos em branco entre os caracteres visveis (pelo
funes nativas e nomes de funes definidas pelo usurio. menos numa folha de papel branco). A string constante
Usando a notao de ponto podemos especificar que verso de string.whitespace contm todos os caracteres de espaamento,
find (encontrar) ns queremos. incluindo espao, tabulao (\t) e nova linha (\n).
De fato, string.find mais generalizada que a Existem outras funes teis no mdulo string,
nossa verso. Primeiramente, ela pode encontrar substrings, mas este livro no pretende ser um manual de referncia. Por
no apenas caracteres: outro lado, Python Library Reference exatamente isto. Em
meio a uma abundante documentao, ele est disponvel no
>>> string.find("banana", "na") site da web do Python, www.python.org.
2
Alm disso, ela recebe um argumento adicional
que especifica o ndice pelo qual ela deve comear sua
procura: 7.11 Glossrio
>>> string.find("banana", "na", 3)
tipo de dado Um tipo de dado no qual o valor consiste de
4 composto componentes, ou elementos, que so eles
Ou ela pode receber dois argumentos adicionais (compound mesmos valores.
que especificam o intervalo de ndices: data type)
>>> string.find("bob", "b", 1, 2) travessia Iterar atravs dos elementos de um conjunto,
-1 (traverse) realizando uma operao similar em cada um

Captulo 7: Strings #44


Como pensar como um cientista da Computao usando Python

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

7.11 Glossrio2

tipo de dado Um tipo de dado em que os valores so


composto compostos de componentes, ou elementos,
(compound que podem ser tratados como valores
data type) separados.
atravessar Iterar atravs dos elementos definidos,
(traverse) 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 Um tipo de dado composto do qual
(mutable) elementos podem atribuir novos valores.
contador Uma varivel usada para contar alguma
(counter) coisa, geralmente iniciada em zero e
incrementada.
incremento Para aumentar o valor da varivel.
(increment)
decremento Para dimiuir o valor da varivel.
(decrement)
espao em Qualquer caractere que move o cursor sem
branco imprimir caracteres visveis. A constante
(whitespace) string.whitespace contm todos os
caracteres de espao em branco.

Captulo 7: Strings #45


Como pensar como um cientista da Computao usando Python

Captulo 8: Listas

Uma lista um conjunto ordenado de valores, onde cada valor


identificado por um ndice. Os valores que compem uma 8.2 Acessado elementos
lista so chamados elementos. Listas so similares a strings,
que so conjuntos ordenados de caracteres, com a diferena A sintaxe para acessar os elementos de uma lista a mesma
que os elementos de uma lista podem possuir qualquer tipo. que a sintaxe para acessar os caracteres de uma string XXX o
Listas e strings XXX e outras coisas que se comportam como operator colchete ([]). A expresso dentro dos colchetes
conjuntos ordenados XXX so chamados seqncias. especifica o ndice. Lembre-se que os ndices iniciam em 0:
>>> print numeros[0]
>>> numeros[1]= 5
8.1 Valores da lista
O operador colchete pode aparecer em qualquer
lugar em uma expresso. Quando ele aparece no lado
Existem vrias maneiras de criar uma nova lista; a mais esquerdo de uma atribuio, ele modifica um dos elementos
simples envolver os elementos em colchetes ([ e ]): em uma lista, de forma que o um-simo elemento de numeros,
>>> [10, 20, 30, 40]
que era 123, agora 5.
>>> ['spam', 'bungee', 'swallow'] Qualquer expresso inteira pode ser utilizada
O primeiro exemplo uma lista de quatro como um ndice:
inteiros. O segundo uma lista de trs strings. Os elementos
de uma lista no necessitam ser do mesmo tipo. A lista a >>> numeros[3-2]
seguir contm uma string, um valor float, um valor inteiro, e 5
mirabile dictu uma outra lista: >>> numeros[1.0]
TypeError: sequence index must be integer
>>> ['alo', 2.0, 5, [10,20]]
Se voc tentar ler ou escrever um elemento que
Uma lista dentro de outra lista dita estar no existe, voc recebe um erro de tempo de execuo
aninhada. (runtime error):
Listas que contm inteiros consecutivos so >>> numeros[2]=5
comuns, ento Python fornece uma maneira simples de cri-
los: IndexError: list assignment index out of range
Se um ndice possui um valor negativo, ele
>>> range(1,5) conta ao contrrio a partir do final da lista:
[1, 2, 3, 4]
>>> numeros[-1]
A funo range pega dois argumentos e devolve
uma lista que contm todos os inteiros do primeiro at o 5
segundo, incluindo o primeiro mas no incluindo o segundo! >>> numeros[-2]
17
Existem outras formas de range. Com um >>> numeros[-3]
argumento simples, ela cria uma lista que inicia em 0:
IndexError: list index out of range
>>> range(10) numeros[-1] o ltimo elemento da lista,
[0,1, 2, 3, 4, 5, 6, 7, 8, 9] numeros[-2] o penltimo e numeros[-3] no existe.
Se existe um terceiro argumento, ele especifica comum utilizar uma varivel de lao como um
o espao entre os valores sucessivos, que chamado de ndice da lista:
tamanho do passo. Este exemplo conta de 1 at 10 em passos
de 2: >>> cavaleiros = ['guerra', 'fome', 'peste', 'morte']
i = 0
>>> range(1, 10, 2)
while i < 4:
[1, 3, 5, 7, 9]
print cavaleiros[i]
Finalmente, existe uma lista especial que no
contm elementos. Ela chamada lista vazia, e sua notao 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.
Com todas estas formas de criar listas, seria Desta forma o corpo do lao executado somente quando i
decepcionante se no pudssemos atribuir valores de listas a 0, 1, 2 e 3.
variveis ou passar listas como parmetros a funes.
Felizmente, podemos. Em cada vez dentro do lao, a varivel i
utilizada como um ndice para a lista, exibindo o i-simo
>>> vocabulario = ['melhorar', 'castigar', \ elemento. Este padro de computao chamado de percurso
'defenestrar'] na lista.
>>> numeros = [17, 123]
>>> vazio = []
>>> print vocabulario, numeros, vazio 8.3 Comprimento da lista
['melhorar', 'castigar', 'defenestrar'] [17, 123] []
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

Captulo 8: Listas #46


Como pensar como um cientista da Computao usando Python

mudar, voc no precisar ir atravs de todo o programa Quase se l como Portugus: "For (para cada)
modificando todos os laos; eles funcionaro corretamente cavaleiro in (na lista de) cavaleiros, print (imprima o nome do)
para qualquer tamanho de lista: cavaleiro."
>>> cavaleiros = ['guerra', 'fome', 'peste', 'morte'] Qualquer expresso de lista pode ser utilizada
i = 0 num lao for:
while i < len(cavaleiros): >>> for numero in range(20):
print cavaleiros[i] if numero % 2 == 0:
i = i + 1 print numero
A ltima vez que o corpo do lao executado, i
len(cavaleiros) - 1, que o ndice do ltimo elemento. >>> for fruta in ["banana", "abacaxi", "laranja"]:
Quando i igual a len(cavaleiros), a condio falha e o corpo
no executado, o que uma boa coisa, porque print "Eu gosto de comer " + fruta + "s!"
len(cavaleiros) no um ndice legal. O primeiro exemplo exibe todos os nmeros
pares entre zero e dezenove. O segundo exemplo expressa o
Embora uma lista possa conter uma outra lista, a entusiasmo por vrias frutas.
lista aninhada ainda conta como um elemento simples. O
comprimento desta lista quatro:
>>> [`spam!', 1, ['Brie', 'Roquefort', \ 8.6 Operaes em listas
'Pol l Veq'], [1, 2 3]]
Como um exerccio, escreva um lao que O operador + concatena listas:
percorra a lista anterior e exiba o comprimento de cada
elemento. O que acontece se voc manda um inteiro para >>> a = [1, 2, 3]
len? >>> b = [4, 5, 6]
>>> c = a + b
>>> print c
8.4 Membros de uma lista [1, 2, 3, 4, 5, 6]
Similarmente, o operador * repete uma lista um
in um operador lgico que testa se um elemento membro nmero dado de vezes:
de uma seqncia. Ns o utilizamos na Seo 7.10 com
strings, mas ele tambm funciona com listas e outras >>> [0] * 4
seqncias: [0, 0, 0, 0]
>>> [1, 2, 3] * 3
>>> cavaleiros = ['guerra', 'fome', 'peste', 'morte'] [1, 2, 3, 1, 2, 3, 1, 2, 3]
>>> 'peste' in cavaleiros O primeiro exemplo repete [0] quatro vezes. O
True segundo exemplo repete a lista [1, 2, 3] trs vezes.
>>> 'depravao' in cavaleiros
False
Uma vez que 'peste' um membro da lista 8.7 Fatiamento de listas
cavaleiros, o operador in devolve verdadeiro. Uma vez que
depravao no est na lista, in devolve falso.
A operao de fatiamento que vimos na Seo 7.4 tambm
Podemos utilizar tambm o not em combinao funciona sobre listas:
com o in para testar se um elemento no um membro de uma
lista: >>> lista = ['a', 'b', 'c', 'd', 'e', 'f']
>>> lista[1:3]
>>> ``depravao`` not in cavaleiros ['b', 'c']
True >>> lista[:4]
['a', 'b', 'c', 'd']
>>> lista[3:]
8.5 Listas e laos for ['d', 'e', 'f']
>>> lista[:]
O lao for que vimos na Seo 7.3 tambm funciona com ['a', 'b', 'c', 'd', 'e', 'f']
listas. A sintaxe generalizada de um lao for :
for VARIVEL in LISTA:
CORPO 8.8 Listas so mutveis
Esta declarao equivalente a:
Diferente das strings, as listas so mutveis, o que significa
>>> i = 0 que podemos modificar seus elementos. Utilizando o operador
while i < len(LIST): colchete no lado esquerdo de uma atribuio, podemos
VARIABLE = LIST[i] atualizar um de seus elementos:
XXX BODY
>>> fruta = ["banana", "abacaxi", "laranja"]
i = i + 1
>>> fruta[0] = "abacate"
O lao for mais conciso porque podemos >>> fruta[-1] = "tangerina"
eliminar a varivel do lao, i. Aqui est o lao anterior escrito
com um`lao for: >>> print fruta
['abacate', 'abacaxi', 'tangerina']
>>> for cavaleiro in cavaleiros: Com o operador de fatiamento podemos
print cavaleiro atualizar vrios elementos de uma vez:

Captulo 8: Listas #47


Como pensar como um cientista da Computao usando Python

>>> lista = ['a', 'b', 'c', 'd', 'e', 'f'] se referem mesma coisa. Estas "coisas" possume nomes -
>>> lista[1:3] = ['x', 'y'] elas so chamadas objetos. Um objeto algo ao qual uma
>>> print lista
varivel pode se referenciar.
['a', 'x', 'y', 'd', 'e', 'f'] Todo objeto possui um identificador nico, que
Tambm podemos remover elementos de uma podemos obter com a funo id. Exibindo o identificador de a
lista atribuindo a lista vazia a eles: e b, podemos dizer se elas se referem ao mesmo objeto.
>>> lista = ['a', 'b', 'c', 'd', 'e', 'f'] >>> id(a)
>>> lista[1:3] = [] 135044008
>>> print lista >>> id(b)
['a', 'd', 'e', 'f'] 135044008
E podemos adicionar elementos a uma lista De fato, obtivemos o mesmo identificador duas
enfiando-os numa fatia vazia na posio desejada: vezes, o que significa que Python criou apenas uma string, e
tanto a quanto b se referem a ela.
>>> lista = ['a', 'd', 'f']
>>> lista[1:1] = ['b', 'c']
Interessantemente, listas se comportam de forma
diferente. Quando criamos duas listas, obtemos dois objetos:
>>> print lista
['a', 'b', 'c', 'd', 'f'] >>> a = [1, 2, 3]
>>> lista[4:4] = ['e'] >>> b = [1, 2, 3]
>>> print lista >>> id(a)
['a', 'b', 'c', 'd', 'e', 'f'] 135045528
>>> id(b)
135041704
8.9 Remoo em lista Ento o diagrama de estado fica assim:

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 e b possuem o mesmo valor mas no se
>>> a referem ao mesmo objeto.
['um', 'tres']
Como voc deveria esperar, del trata valores
negativos e causa erros de tempo de execuo se o ndice 8.11 Apelidos
estiver fora da faixa.
Voc tambm pode utilizar uma faixa como um Uma vez que variveis se referem a objetos, se atribuimos
ndice para del: uma varivel a uma outra, ambas as variveis se referem ao
mesmo objeto:
>>> lista = ['a', 'b', 'c', 'd', 'e', 'f']
>>> del lista[1:5] >>> a = [1, 2, 3]
>>> print lista >>> b = a
['a', 'f'] Neste caso, o diagrama de estado se parece com
Como de costume, fatias selecionam todos os isto:
elementos at, mas no incluindo, o segundo ndice.

8.10 Ojetos e valores


Se executamos estas declaraes de atribuio:
>>> a = "banana"
>>> b = "banana"
Uma vez que a lista possui dois nomes
diferentes, a e b, dizemos que ela est "apelidada" (aliased).
sabemos que a e b se referem a uma string com Mudanas feitas em um apelido afetam o outro nome:
as letras banana. Mas no podemos dizer se elas apontam para
a mesma string. >>> b[0] = 5
>>> print a
Existem dois possveis estados:
[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.
Em um caso, a e b se referem a duas coisas
diferentes que possuem o mesmo valor. No segundo caso, elas

Captulo 8: Listas #48


Como pensar como um cientista da Computao usando Python

que contm todos menos o primeiro elemento de uma


8.12 Clonando listas determinada lista:
Se queremos modificar uma lista e tambm manter uma cpia >>> def cauda(lista):
da original, preciamos ter condies de fazer uma cpia da return lista[1:]
prpria lista, no apenas uma referncia. Este processo Aqui est a maneira como ela utilizada:
algumas vezes chamado clonagem, para evitar a ambigidade
da palavra "cpia". >>> numeros = [1, 2, 3]
>>> resto = cauda(numeros)
A maneira mas fcil de clonar uma lista
utilizar o operador de fatia: >>> print resto
[2, 3]
>>> a = [1, 2, 3] Uma vez que o valor de retorno foi criado com
>>> b = a[:] o operador de fatia, ele uma nova lista. A criao de resto, e
>>> print b qualquer alterao subseqente a resto, no tem efeito sobre
[1, 2, 3] numeros.
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
8.14 Lista aninhadas
sem nos preocuparmos com``a``:
Uma lista aninhada uma lista que aparece como um
>>> b[0] = 5 elemento de uma outra lista. Nesta lista, o terceiro elemento
>>> print a uma lista aninhada:
[1, 2, 3] >>> lista = ["alo", 2.0, 5, [10, 20]]
Como exerccio, desenhe um diagrama de Se exibimos lista[3], obtemos [10, 20]. Para
estado para``a`` e b antes e depois desta mudana. extrairmos um elemento de uma lista aninhada, podemos agir
em duas etapas:
>>> elem = lista[3]
8.13 Lista como parmetro
>>> elem[0]
10
Passar uma lista como um argumento passa realmente uma
referncia lista, no uma cpia da lista. Por exemplo, a Ou podemos combin-las:
funo cabeca pega uma lista como parmetro e devolve a >>> lista[3][1]
cabea da lista, ou seja, seu primeiro elemento:
20
>>> def cabeca(lista): Os operadores colchete avaliam da esquerda
return lista[0] para a direita, ento a expresso pega o terceiro elemento de
Eis como ela utilizada: lista e extrai o primeiro elemento dela.
>>> numeros = [1, 2, 3]
>>> cabeca(numeros)
8.15 Matrizes
1
O parmetro lista e a varivel numeros so Listas aninhadas so freqentemente utilizadas para
apelidos para o mesmo objeto. O diagrama de estado se parece representar matrizes. Por exemplo, a matriz:
com isto:

poderia ser representada como:


>>> matriz = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Uma vez que o objeto compartilhado pelos matriz uma lista com trs elementos, onde
dois quadros, o desenhamos entre eles. cada elemento uma linha da matriz. Podemos selecionar uma
Se a funo modifica um parmetro da lista, a linha inteira da matriz da maneira habitual:
funo chamadora v a mudana. Por exemplo, >>> matriz[1]
removeCabeca remove o primeiro elemento da lista:
[4, 5, 6]
>>> def removecabeca(lista): Ou podemos extrair um nico elemento da
del lista[0] matriz utilinado a forma de duplo ndice:
Aqui est a maneira como ela utilizada: >>> matriz[1][1]
>>> numeros = [1, 2, 3] 5
>>> removeCabeca(numeros) O primeiro ndice seleciona a linha, e o segundo
>>> print numeros ndice seleciona a coluna. Embora esta maneira de representar
[2, 3] matrizes seja comum, ela no a nica possibilidade. Uma
pequena variao utilizar uma lista de colunas ao invs de
Se uma funo devolve uma lista, ela devolve uma lista de linhas.
uma referncia lista. Por exemplo, cauda devolve uma lista

Captulo 8: Listas #49


Como pensar como um cientista da Computao usando Python

Mais adiante veremos uma alternativa mais mesmo para qualquer string? Quando eles seriam diferentes?
radical utilizando um dicionrio.

8.17 Glossrio
8.16 Strings e listas
lista (list) Uma coleo denominada de objetos, onde
Duas das mais teis funes no mdulo string envolvem listas cada objeto identificado por um ndice.
de strings. A funo split (separar) quebra uma string em uma
lista de palavras. Por padro, qualquer nmero de caracteres ndice (index) Uma varivel inteira ou valor que indica um
espao em branco considerado um limite de uma palavra: elemento de uma lista.
>>> import string elemento Um dos valores em uma lista(ou outra
>>> poesia = "O orvalho no carvalho..." (element) seqncia). O operador colchete seleciona
>>> string.split(poesia) elementos de uma lista.
['O', 'orvalho', 'no', 'carvalho...'] seqncia Qualquer um dos tipos de dados que
Um argumento opcional chamado um (sequence) consiste de um conjunto ordenado de
delimitador pode ser utilizado para especificar qual caracter elementos, com cada elemento identificado
utilizar como limites da palavra. O exemplo a seguir utiliza a por um ndice.
string va:
lista aninhada Uma lista que um elemento de uma outra
>>> string.split(poesia, 'va') (nested list) lista.
['O or', 'lho no car', 'lho...'] percurso na O acesso seqencial de cada elemento em
Perceba que o delimitador no aparece na lista. lista (list uma lista.
traversal)
A funo join (juntar) o inverso de split. Ela
pega uma lista de strings e concatena os elementos com um objeto Um coisa a qual uma varivel pode se
espao entre cada par: (object) referir.
>>> lista = ['O', 'orvalho', 'no', 'carvalho...'] apelidos Mltiplas variveis que contm referncias
>>> string.join(lista) (aliases) ao mesmo objeto.
'O orvalho no carvalho...' clonar (clone) Criar um novo objeto que possui o mesmo
Como split, join recebe um delimitador que valor de um objeto existente. Copiar a
inserido entre os elementos: referncia a um objeto cria um apelido
(alias) mas no clona o objeto.
>>> string.join(lista, '_')
'O_orvalho_no_carvalho...' delimitador Um caracter uma string utilizados para
(delimiter) indicar onde uma string deveria ser
Como um execcio, descreva o relacionamento dividida(split).
entre string.join(string.split(poesia)) e poesia. Eles so o

Captulo 8: Listas #50


Como pensar como um cientista da Computao usando Python

Captulo 9: Tuplas

>>> temp = a
9.1 Mutabilidade e tuplas >>> a = b
>>> b = temp
At agora, voc tem visto dois tipos compostos: strings, que
so compostos de caracteres; e listas, que so compostas de Se voc tiver que fazer isso com frequncia, esta
elementos de qualquer tipo. Uma das diferenas que notamos abordagem se torna incmoda. Python fornece uma forma de
que os elementos de uma lista podem ser modificados, mas atribuio de tupla que resolve esse problema
os caracteres em uma string no. Em outras palavras, strings elegantemente:
so imutveis e listas so mutveis. >>> a, b = b, a
H um outro tipo em Python chamado tupla O lado esquedo uma tupla de variveis; o lado
(tuple) que similar a uma lista exceto por ele ser imutvel. direito uma tupla de valores. Cada valor atribudo sua
Sintaticamente, uma tupla uma lista de valores separados por respectiva varivel. Todas as expresses do lado direito so
vrgulas: avaliadas antes de qualquer das atribuies. Esta caracterstica
torna as atribuies de tupla bastante versteis.
>>> tupla = 'a', 'b', 'c', 'd', 'e'
Naturalmente, o nmero de variveis na
Embora no seja necessrio, convencional esquerda e o nmero
colocar tuplas entre parnteses: de valores na direita deve ser igual:

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


ValueError: unpack tuple of wrong size
Para criar uma tupla com um nico elemento,
temos que incluir uma vrgula final:
>>> t1 = ('a',)
>>> type(t1)
9.3 Tuplas como valores de retorno
<type 'tuple'>
Funes podem retornar tuplas como valor de retorno. Por
Sem a vrgula, Python entende ('a') como uma Exemplo, ns poderamos escrever uma funo que troca dois
string entre parnteses: parmetros entre si:
>>> t2 = ('a') def troca(x, y):
>>> type(t2) return y, x
<type 'string'> Ento ns poderamos atribuir o valor de retorno
Questes de sintaxe de lado, as operaes em para uma tupla com duas variveis:
tuplas so as mesmas operaes das listas. O operador ndice
seleciona um elemento da tupla. a, b = troca(a, b)
Neste caso, no existe uma grande vantagem em
>>> tupla = ('a', 'b', 'c', 'd', 'e') fazer de troca (swap) uma funo. De fato, existe um perigo
>>> tupla[0] em tentar encapsular troca, o qual a tentao de cometer o
'a' seguinte erro:
E o operador slice (fatia) seleciona uma "faixa"
(range) de elementos. def troca(x, y): # versao incorreta
x, y = y, x
>>> tupla[1:3] Se ns chamarmos esta funo desta forma:
('b', 'c')
Mas se tentarmos modificar um dos elementos troca(a, b)
de uma tupla, teremos um erro: ento a e x so apelidos para um mesmo valor.
Mudar x dentro da funo troca, faz com que x se referencie a
>>> tupla[0] = 'A' um valor diferente, mas sem efeito sobre a dentro de
TypeError: object doesn't support item assignment __main__. Do mesmo modo, a mudana em y no tem efeito
Naturalmente, mesmo que no possamos sobre b.
modificar os elementos de uma tupla, podemos substitu-la por Esta funo roda sem produzir uma mensagem
uma tupla diferente: de erro, mas ela no faz o que pretendemos. Este um
>>> tupla = ('A',) + tupla[1:]
exemplo de um erro semntico.
>>> tupla Como exerccio, desenhe um diagrama de
('A', 'b', 'c', 'd', 'e') estado pra esta funo de modo que voc possa ver porque
ela no funciona.

9.2 Atribuies de tupla


9.4 Nmeros aleatrios
De vez em quando, necessrio trocar entre si os valores de
duas variveis. Com operaes de atribuio convencionais, A maioria dos programas de computador fazem a mesma coisa
temos que utilizar uma varivel temporria. Por exemplo, para sempre que so executados, ento, podemos dizer que eles so
fazer a troca entre a e b: determinsticos. Determinismo em geral uma coisa boa, se

Captulo 9: Tuplas #51


Como pensar como um cientista da Computao usando Python

ns esperamos que um clculo d sempre o mesmo resultado. programa que divida a faixa de valores em intervalos e conte o
Entretanto, para algumas aplicaes queremos que o nmero de valores de cada intervalo.
computador se torne imprevisvel. Jogos so um exemplo
bvio, mas existem outros.
Fazer um programa realmente no- 9.6 Contando
determinstico se mostra no ser to fcil, mas existem
maneiras de faz-lo ao menos parecer no-determinstico. Uma boa maneira de abordar problemas como esse dividir o
Uma dessas maneiras gerar nmeros aleatrios e us-los problema em subproblemas, e encontrar um subproblema que
para determinar o resultado de um programa. Python tem uma se enquadre em um padro de soluo computacional que
funo nativa que gera nmeros pseudo aleatrios, os quais voc j tenha visto antes.
no so verdadeiramente aleatrios no sentido matemtico,
mas para os nossos propsitos eles so. Neste caso, queremos percorrer uma lista de
nmeros e contar o nmero de vezes que valor se encaixa em
O mdulo random contm uma funo chamada um determinado intervalo. Isso soa familiar. Na Seo 7.8,
random que retorna um nmero em ponto flutuante (floating- ns escrevemos um programa que percorria uma string e
point number) entre 0.0 e 1.0. Cada vez que voc chama contava o nmero de vezes que uma determinada letra
random, voc recebe o prximo nmero de uma longa srie. aparecia.
Para ver uma amostra, execute este loop:
Assim, podemos prosseguir copiando o
import random programa original e adaptando-o para o problema atual. O
programa original era:
for i in range(10):
x = random.random() contador = 0
print x for letra in fruta:
if letra == 'a':
Para gerar um nmero aleatrio ente 0.0 e um
limite superior, digamos superior, multiplique x por superior. contador = contador + 1
print contador
Como exerccio, gere um nmero aleatrio entre O primeiro passo substituir fruta por lista e
'inferior' e 'superior'. letra por numero. Isso no muda o programa, apenas o ajusta
Como exerccio adicional, gere um nmero para que ele se torne mais fcil de ler e entender.
inteiro aleatrio entre 'inferior' e 'superior', inclusive os dois O segundo passo mudar o teste. Ns no
extremos. estamos interessados em procurar letras. Ns queremos ver se
numero est entre inferior e superior.:
contador = 0
9.5 Lista de nmeros aleatrios
for numero in lista
if inferior < numero < superior:
O primeiro passo gerar uma lista aleatria de valores.
listaAleatoria pega um parmetro inteiro e retorna uma lista de contador = contador + 1
nmeros aleatrios com o comprimento dado. Inicia-se com print contador
uma lista de n zeros. A cada iterao do loop, ele substitui um O ltimo passo encapsular este cdigo em
dos elementos por um nmero aleatrio. O valor retornado uma funo chamada noIntervalo. Os parmetros so a lista e
uma referncia para a lista completa: os valores inferior e superior:
def listaAleatoria(n): def noIntervalo(lista, inferior, superior):
s = [0] * n contador = 0
for i in range(n): for numero in lista:
s[i] = random.random() if inferior < numero < superior:
return s contador = contador + 1
Vamos realizar um teste desta funo com uma return contador
lista de oito elementos. Para efeitos de depurao, uma boa Atravs da cpia e da modificao de um
idia comear com uma lista pequena. programa existente, estamos aptos a escrever esta funo
>>> listaAleatoria(8)
rapidamente e economizar um bocado de tempo de depurao.
Este plano de desenvolvimento chamado de casamento de
0.15156642489 padres. Se voc se encontrar trabalhando em um problema
0.498048560109 que voc j solucionou antes, reuse a soluo.
0.810894847068
0.360371157682
0.275119183077 9.7 Vrios intervalos
0.328578797631
0.759199803101 Conforme o nmero de intervalos aumenta, noIntervalo torna-
0.800367163582 se intragvel. Com dois intervalos, no to ruim:
Os nmeros gerados por random so
supostamente uniformemente distribudos, o que significa que inferior = noIntervalo(a, 0.0, 0.5)
cada valor tem uma probabilidade igual de acontecer. superior = noIntervalo(a, 0.5, 1)
Mas com quatro intervalos, comea a ficar
Se ns dividirmos a faixa de valores possveis desconfortvel.:
em intervalos do mesmo tamanho, e contarmos o nmero de
vezes que um determinado valor aleatrio caiu em seu intervalo1 = noIntervalo(a, 0.0, 0.25)
respectivo intervalo, ns devemos obter o mesmo nmero intervalo2 = noIntervalo(a, 0.25, 0.5)
aproximado de valores em cada um dos intervalos.
intervalo3 = noIntervalo(a, 0.5, 0.75)
Ns podemos testar esta teoria escrevendo um

Captulo 9: Tuplas #52


Como pensar como um cientista da Computao usando Python

intervalo4 = noIntervalo(a, 0.75, 1.0)


Existem aqui dois problemas. Um que temos
9.8 Uma soluo em um s passo
que criar novos nomes de varivel para cada resultado. O
outro que temos que calcular os limites de cada intervalo. Embora este programa funcione, ele no to eficiente quanto
poderia ser. Toda vez que ele chama noIntervalo, ele percorre
Vamos resolver o segundo problema primeiro. a lista inteira. Conforme o nmero de intervalos aumenta, a
Se o nmero de intervalos numeroDeIntervalos, ento a lista ser percorrida um bocado de vezes.
largura de cada intervalo 1.0 / numeroDeIntervalos.
Seria melhor fazer uma nica passagem pela
Vamos usar um lao (loop) para calcular a faixa, lista e calcular para cada valor o ndice do intervalo ao qual o
ou largura, de cada intervalo. A varivel do loop, i, conta de 0 valor pertena. Ento podemos incrementar o contador
at numeroDeIntervalos-1: apropriado.
larguraDoIntervalo = 1.0 / numeroDeIntervalos Na seo anterior, pegamos um ndice, i, e o
for i in range(numeroDeIntervalos): multiplicamos pela larguraDoIntervalo para encontrar o limite
inferior = i * larguraDoIntervalo inferior daquele intervalo. Agora queremos pegar um valor
entre 0.0 e 1.0 e encontrar o ndice do intervalo ao qual ele se
superior = inferior + larguraDoIntervalo encaixa.
print "do" inferior, "ao", superior
Para calcular o limite inferior (inferior) de cada J que este problema o inverso do problema
intervalo, ns multiplicamos a varivel do loop (i) pela largura anterior, podemos imaginar que deveramos dividir por
do intervalo (larguraDoIntervalo). O limite superior (superior) larguraDoIntervalo em vez de multiplicar. Esta suposio est
est exatamente uma "largura de intervalo" acima. correta.
Com numeroDeIntervalos = 8, o resultado : J que larguraDoIntervalo = 1.0 /
numeroDeIntervalos, dividir por larguraDoIntervalo o
0.0 to 0.125 mesmo que multiplicar por numeroDeIntervalos. Se
0.125 to 0.25 multiplicarmos um nmero na faixa entre 0.0 e 1.0 por
0.25 to 0.375
numeroDeIntervalos, obtemos um nmero na faixa entre 0.0 e
numeroDeIntervalos. Se arredondarmos este nmero para
0.375 to 0.5 baixo, ou seja, para o menor inteiro mais prximo, obtemos
0.5 to 0.625 exatamente o que estamos procurando - o ndice do intervalo:
0.625 to 0.75
0.75 to 0.875 numeroDeIntervalos = 8
0.875 to 1.0 intervalos = [0] * numeroDeIntervalos
for i in lista:
Voc pode confirmar que cada intervalo tem a
mesma largura, que eles no se sobrepe, e que eles cobrem indice = int(i * numeroDeIntervalos)
toda a faixa de valores de 0.0 a 1.0. intervalos[indice] = intervalos[indice] + 1
Usamos a funo int para converter um nmero
Agora, de volta ao primeiro problema. Ns em ponto flutuante (float) para um inteiro.
precisamos de uma maneira de guardar oito inteiros, usando a
vriavel do loop para indicar cada um destes inteiros. Voc Existe a possibilidade deste clculo produzir um
deve estar pensando, "Lista!" ndice que esteja fora dos limites (seja negativo ou maior que
len(intervalos)-1)?
Ns temos que criar a lista de intervalos fora do
loop, porque queremos fazer isto apenas uma vez. Dentro do Uma lista como intervalos que contm uma
loop, ns vamos chamar noIntervalo repetidamente e atualizar contagem do nmero de valores em cada intervalo chamada
o i-simo elemento da lista: de histograma.
numeroDeIntervalos = 8 Como exerccio, escreva uma funo chamada
intervalos = [0] * numeroDeIntervalos ``histograma`` que receba uma lista e um nmero de
larguraDoIntervalo = 1.0 / numeroDeIntervalos intervalos como argumentos e retorne um histograma com o
for i in range(numeroDeIntervalos):
nmero de intervalos solicitado.
inferior = i * larguraDoIntervalo
superior = inferior + larguraDoIntervalo
intervalos[i] = noIntervalo(lista, inferior, 9.9 Glossrio
superior)
print intervalos tipo imutvel Um tipo de elemento que no pode ser
Com uma lista de 1000 valores, este cdigo vai (immutable modificado. Atribuies a um elemento ou
produzir esta lista de quantidades de valores em cada type) "fatiamento (slices)" XXX aos tipos
intervalo: imutveis causaro erro.
[138, 124, 128, 118, 130, 117, 114, 131] tipo mutvel Tipo de dados onde os elementos podem
Esses nmeros esto razoavelmente pximos de (mutable type) ser modificados. Todos os tipos mutveis,
125, o que era o que espervamos. Pelo menos eles esto so tipos compostos. Listas e dicionrios
prximos o bastante para nos fazer acreditar que o gerador de so exemplos de tipos de dados mutveis.
nmero aleatrios est funcionando. String e tuplas no so.
Como exerccio, teste esta funo com algumas tupla (tuple) Tipo sequencial similar as listas com
listas longas, e veja se o nmero de valores em cada um dos exceo de que ele imutvel. Podem ser
intervalos tendem a uma distribuio nivelada. usadas Tuplas sempre que um tipo imutvel
for necessrio, por exemplo uma "chave
(key)" em um dicionrio
Atribuio a Atribuio a todos os elementos de uma
tupla (tuple tupla feita num nico comando de

Captulo 9: Tuplas #53


Como pensar como um cientista da Computao usando Python

assignment) 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 Um programa que realiza a mesma coisa
(deterministic) sempre que executado.
pseudo Uma sequncia de nmeros que parecem
aleatrio ser aleatrios mas so na verdade o
(pseudorando resultado de uma computao
m) "determinstica"
histograma Uma lista de inteiros na qual cada elemento
(histogram) conta o nmero de vezes que algo acontece.

Captulo 9: Tuplas #54


Como pensar como um cientista da Computao usando Python

Captulo 10: Dicionrios

Os tipos compostos que voce aprendeu - strings, listas e tuplas >>> del inventario['peras']
- utilizam inteiros como indices. Se voce tentar utilizar >>> print inventario
qualquer outro tipo como indice, voce receber um erro. {'laranjas': 525, 'abacaxis': 430, 'bananas': 312}
Dicionrios sao similiares a outros tipos Ou se ns esperamos por mais peras em breve,
compostos exceto por eles poderem user qualquer tipo nos podemos simplesmente trocar o valor associoado as peras:
imutavel de dados como indice. Como exemplo, nos
criaremos um dicionrio para traduzir palavras em Ingls para >>> inventario['peras'] = 0
Espanhol. Para esse dicionrio, os indices sero strings. >>> print inventario
{'laranjas': 525, 'abacaxis': 430, 'peras': 0, \
Uma maneira de criar um dicionario
comecando com um dicionrio vazio e depois adiconando 'bananas': 312}
elementos. Um dicionrio vazio denotado assim {}: A funo len tambm funciona com dicionrios;
retornando o nmero de pares chave-valor:
>>> ing2esp = {}
>>> ing2esp['one'] = 'uno' >>> len(inventario)
>>> ing2esp['two'] = 'dos' 4
A primeira atribuio cria um dicionario
chamado ing2esp; as outras atribuies adicionam novos
elementos para o dicionrio. Nos podemos imprimir o valor 10.2 Mtodos dos Dicionrios
corrente de um dicionario da maneira usual:
>>> print ing2esp Um mtodo parecido com uma funo - possui parametros e
{'one': 'uno', 'two': 'dos'} retorna valores - mas a sintaxe diferente. Por exemplo, o
Os elementos de um dicionrio aparecem em metodo keys recebe um dicionrio e retorna uma lista com as
uma lista separada por vrgulas. Cada entrada contm um chaves, mas em vez de usarmos a sintaxe de funo
indice e um valor separado por dois-pontos. Em um keys(ing2esp), nos usamos a sintaxe de mtodo
dicionrio, os ndices sao chamados de chaves, entao os ing2esp.keys():
elementos so chamados de pares chave-valor. >>> ing2esp.keys()
Outra maneira de criar dicionrios fornecendo ['one', 'three', 'two']
uma lista de pares chaves-valor utilizando a mesma sintaxe da Dessa forma o ponto especifica o nome da
ltima sada. funo, keys, e o nome do objeto em que deve ser aplicada a
funo, ing2esp. Os parenteses indicam que esse mtodo no
>>> ing2esp = {'one': 'uno', 'two': 'dos', \ possui parameteros.
'three': 'tres'}
Ao invs de chamarmos um mtodo, dizemos
Se nos imprimirmos o valor de ing2esp que ele invocado,
novamente, nos teremos uma surpresa: nesse caso, ns podemos dizer que ns
estamos invocando keys do objeto ing2esp.
>>> print ing2esp O mtodo values parecido; retorna a lista de
{'one': 'uno', 'three': 'tres', 'two': 'dos'} valores de um dicionrio:
Os pares chave-valor no esto em ordem!
Felizmente, no a motivos para se preocupar com a ordem, >>> ing2esp.values()
desde que os elementos do dicionrio nunca sejam indexados ['uno', 'tres', 'dos']
com indices inteiros. Podemos usar as chaves para buscar os O mtodo items retorna os dois, na forma de
valores correspondentes: uma lista de tuplas - cada tupla com um par chave-valor:
>>> print ing2esp['two'] >>> ing2esp.items()
'dos' [('one','uno'), ('three','tres'), ('two','dos')]
A chave 'two' retornou o valor 'dos' mesmo A sintaxe fornece uma informao util. Os
pensando que retornaria o terceiro par chave-valor. colchetes indicam que isso uma lista. Os parentses indicam
que os elementos da lista so tuplas.
Se o mtodo recebe de algum parmetro, se
10.1 Operaes dos Dicionrios utiliza a mesma sintaxe das funes. Por exemplo, o mtodo
has_key recebe uma chave e retorna verdadeiro (1) se a chave
O comando del remove um par chave-valor de um dicionrio. existe no dicionrio:
Por exemplo, o dicionrio abaixo contem os nomes de varias
frutas e o numero de cada fruta em no estoque: >>> ing2esp.has_key('one')
True
>>> inventario = {'abacaxis': 430, 'bananas': 312, \ >>> ing2esp.has_key('deux')
'laranjas': 525, 'peras': 217} False
>>> print inventario Se voce tentar chamar um mtodo sem
{'laranjas': 525, 'abacaxis': 430, 'peras': 217, \ especificar em qual objeto, voce obter um erro. Nesse caso, a
'bananas': 312} mensagem de erro no muito til:
Se alguem comprar todas as peras, podemos >>> has_key('one')
remover a entrada do dicionrio:

Captulo 10: Dicionrios #55


Como pensar como um cientista da Computao usando Python

NameError: has_key utilizamos o operador []:


>>> matriz[0,3]
1
10.3 Aliasing (XXX) e Copiar Note que a sintaxe da representao de um
dicionrio no a mesma que a sintaxe usada pela
Uma vez que os dicionrios so mutveis, voce precisa saber representao pelas listas. Em vez de usarmos dois ndices
sobre Aliasing. Sempre que duas variveis referenciarem o inteiros, ns usamos apenas um ndice, que uma tupla de
mesmo objeto, quando uma alterada, afeta a outra. inteiros.
Se voc quer modificar um dicionrio e Mas existe um problema. Se tentarmos buscar
continuar com uma copia original, utilize o mtodo copy. Por um elemento zero, obteremos um erro, pois no existe uma
exemplo, opposites um dicionrio que contm pares de entrada no dicionrio para a chave especificada:
antnimos:
>>> matriz[1,3]
>>> opposites = {'up': 'down', 'right': 'wrong', \ KeyError: (1,3)
'true': 'false'} O mtodo get resolve esse problema:
>>> alias = opposities
>>> copy = opposities.copy() >>> matriz.get((0,3), 0)
1
alias e opposites se referem ao mesmo objeto;
copy se refere a um novo objeto igual ao dicionrio opposites. O primeiro parmetro a chave; o segundo o
Se voc modificar o alias, opposites tambm ser alterado. valor que get retornar caso no existe a chave no dicionrio:
>>> alias['right'] = 'left' >>> matriz.get((1,3), 0)
>>> opossites['right'] 0
'left' get definitivamente melhora a semntica e a
Se modificarmos copy, opposites no ser sintaxe do acesso a matrizes esparsas.
modificado:
>>> copy['right'] = 'privilege'
10.5 Hint
>>> opposites['right']
'left'
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.
10.4 Matrizes Esparsas Alm disso, o tempo da execuo aumenta rapidamente. Em
uma das nossas mquinas, fibonacci(20) executa
instantaneamente, fibonacci(30) demora cerca de um
Na seo 8.14, ns usamos uma lista de listas para representar segundo, e fibonacci(40) demora uma eternidade.
uma matriz. Essa uma boa escolha se a matriz for
principalmente de valores diferentes de zero, mas Para entender o porque, considere o grfico de
considerando uma matriz esparsa como essa: chamadas para fibonacci com n=4:

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 O grfico mostra a estrutura da funo, com
linha e a coluna. Abaixo uma representao em um dicinario linhas conectando cada execuo com a execuo que a
da mesma matriz: chamou. No topo do grfico, fibonacci tem n=4, que chama
>>> matriz = {(0,3): 1, (2, 1): 2, (4, 3): 3}
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.
Ns precisamos apenas de trs pares chave-
valor, cada um sendo um elemento diferente de zero da Conte quantas vezes fibonacci(0) e fibonacci(1)
matriz. Cada chave uma tupla, e cada valor um nmero so chamadas. Essa uma soluo ineficiente para o
inteiro. problema, e torna-se pior quando o parmetro recebido um
nmero maior.
Para acessarmos um elemento da matriz, nos

Captulo 10: Dicionrios #56


Como pensar como um cientista da Computao usando Python

Uma boa soluo guardar os valores que j Os dois primeiros numeros da sequncia so long ints, ento
foram calculados armazenando-os em um dicionrio. Um todos os nmeros subsequentes da sequncia tambm sero.
valor previamente calculado que guardado para ser utilizado
mais tarde chamado de hint. Abaixo uma implementao de Como exerccio, converta fatorial para produzir
fibonacci usando hints: um inteiro longo como resultado.
>>> previous = {0:1, 1:1}
>>> def fibonacci(n):
10.7 Contando Letras
if previous.has_key(n):
return previous[n]
No captulo 7, escrevemos uma funo que contava o nmero
else: de ocorrncias de uma letra em uma string. A verso mais
newValue = fibonacci(n-1) + \ comum desse problema fazer um histograma das letras da
fibonacci(n-2) string, ou seja, quantas vezes cada letra aparece na string.
previous[n] = newValue
Um histograma pode ser util para comprimir um
return newValue arquivo de texto. Pois diferentes letras aparecem com
O dicionrio chamado previous guarda os diferentes frequncias, podemos comprimir um arquivo
nmeros de Fibonacci que ns ja conhecemos. Ele comea usando pequenos cdigos para letras comuns e longos cdigos
com apenas dois pares: 0 possui 1; e 1 possui 1. para letras que aparecem em menor frequncia.
Sempre que fibonacci chamada, ela verifica o Dicionrios fornecem uma maneira elegante de
dicionrio para determinar se ele j possui o resultado. Se o gerar um histograma:
resultado estiver ali, a funo pode retornar imediatamente
sempre precisar fazer mais chamadas recursivas. Se o >>> letterCounts = {}
resultado no estiver ali, ele calculado no newValue. O >>> for letter in "Mississippi":
valor de newValue adicionado no dicionrio antes da funo ... letterCounts[letter] =
retornar. letterCounts.get(letter,0) + 1
Usando essa verso de fibonacci, nossa ...
mquina consegue calcular fibonacci(40) em um piscar de >>> letterCounts
olhos. Mas quando tentamos calcular fibonacci(50), ns {'M': 1, 's': 4, 'p': 2, 'i': 4}
veremos um problema diferente: Comeamos com um dicionrio vazio. Para
>>> fibonacci(50)
cada letra da string, achamos o contador (possivelmente zero)
e o incrementamos. No final, o dicionrio contem pares de
OverflowError: integer addition letras e as suas frequncias.
A resposta, que voc ver em um minuto,
20.365.011.074. O problema que esse nmero muito mais atraente mostrarmos o histograma na
grande para guardarmos como um inteiro do Python 1. Isso ordem alfabtica. Podemos fazer isso com os mtodos items e
overflow. Felizmente, esse problema tem uma soluo sort:
simples.
>>> letterItems = letterCounts.items()
>>> letterItems.sort()
>>> print letterItems
10.6 Inteiros Longos [('M', 1), ('i', 4), ('p', 2), ('s', 4)]
Voc ja tinha visto o mtodo items antes, mas
Python possui um tipo chamado long int que permite sort o primeiro mtodo que voc se depara para aplicar em
trabalharmos com qualquer tamanho de inteiros. Existem duas listas. Existem muitos outros mtodos de listas, incluindo
maneiras de criarmos um valor long int. A primeira escrever append, extend, e reverse. Consulte a documentao do
um inteiro seguido de um L no final: Python para maiores detalhes.
>>> type(1L)
<type 'long int'>
A outra maneira usarmos a funo long que 10.8 Glossrio
converte um valor para um long int. long pode receber
qualquer valor nmerico e at mesmo uma string de digitos: dicionrio Uma coleo de pares de chaves-valores
>>> long(1) (dictionary) que so mapeados pelas chaves, para se
1L
obter os valores. As chaves podem ser
qualquer tipo de dados imutavel, e os
>>> long(3.9) valores podem ser de qualquer tipo.
3L
>>> long('57') chave (key) Um valor que usado para buscar uma
57L
entrada em um dicionrio.
Todas as operaes matemticas funcionam par chave-valor Um dos itens de um dicionrio.
com long int s, ento no precisamos modificar muito para (key-value pair)
adaptar fibonacci:
mtodo Um tipo de funo que chamada com
>>> previous = {0: 1L, 1:1L} (method) uma sintaxe diferente e invocada no
>>> fibonacci(50) contexto de um objeto.
20365011074L invocar (invoke) Chamar um mtodo.
Somente trocando os valores iniciais de
previous, conseguimos mudar o comportamento da fibonacci. hint O armazenamento temporrio de um valor
pr-computado para evitar a computao
1 N.T. A partir do Python 2. XXX este erro no ocorre mais, redundante.
pois em caso de sobrecarga o valor inteiro
automaticamente promovido para o tipo long. overflow Um resultado numrico que muito

Captulo 10: Dicionrios #57


Como pensar como um cientista da Computao usando Python

grande para ser representado no formato


numrico.

Captulo 10: Dicionrios #58


Como pensar como um cientista da Computao usando Python

Captulo 11: Arquivos e excees

temos um erro:
Arquivos e excees
>>> f = open("teste.cat", "r")
Durante a execuo de um programa, seus dados ficam na IOError: [Errno 2] No such file or directory: \
memria. Quando o programa termina, ou o computador 'teste.cat'
desligado, os dados na memria desaparecem. Para armazenar Sem nenhuma surpresa, o mtodo read l dados
os dados permanentemente, voc tem que coloc-los em um do arquivo. Sem argumentos, ele l todo o contedo do
arquivo. Arquivos usualmente so guardados em um disco arquivo:
rgido (HD), num disquete ou em um CD-ROM.
>>> texto = f.read()
Quando existe um nmero muito grande de
arquivos, eles muitas vezes so organizados dentro de >>> print texto
diretrios (tambm chamados de ?pastas? ou ainda ? Agora horade fechar o arquivo
*folders*?). Cada arquivo identificado por um nome nico, No existe espao entre ?hora? e ?de? porque
ou uma combinao de um nome de arquivo com um nome de ns no gravamos um espao entre as strings.
diretrio.
read tambm pode receber um argumento que
Lendo e escrevendo em arquivos, os programas indica quantos caracteres ler:
podem trocar informaes uns com os outros e gerar formatos
imprimveis como PDF. >>> f = open("teste.dat", "r")
>>> print f.read(9)
Trabalhar com arquivos muito parecido com
trabalhar com livros. Para utilizar um livro, voc tem que abr- Agora h
lo. Quando voc termina, voc tem que fech-lo. Enquanto o Se no houver caracteres suficientes no arquivo,
livro estiver aberto, voc pode tanto l-lo quanto escrever read retorna os caracteres restantes. Quando chegamos ao final
nele. Em qualquer caso, voc sabe onde voc est situado no do arquivo, read retorna a string vazia:
livro. Na maioria das vezes, voc l o livro inteiro em sua
ordem natural, mas voc tambm pode saltar atravs de alguns >>> print f.read(1000006)
trechos (skip around). orade fechar o arquivo
>>> print f.read()
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). >>>
A funo seguinte, copia um arquivo, lendo e
Abrir um arquivo cria um objeto arquivo. Neste gravando at cinqenta caracteres de uma vez. O primeiro
exemplo, a varivel f se referencia ao novo objeto arquivo. argumento o nome do arquivo original; o segundo o nome
do novo arquivo:
>>> f = open("teste.dat", "w")
>>> print f def copiaArquivo(velhoArquivo, novoArquivo):
<open file "teste.dat", mode "w" at fe820> f1 = open(velhoArquivo, "r")
A funo open recebe dois argumentos. O f2 = open(novoArquivo, "w")
primeiro o nome do arquivo, e o segundo o modo. Modo ? while 1:
w? significa que estamos abrindo o arquivo para gravao texto = f1.read(50)
(?*write*?, escrever). if texto == "":
Se no existir nenhum arquivo de nome break
teste.dat, ele ser criado. Se j existir um, ele ser substitudo f2.write(texto)
pelo arquivo que estamos gravando (ou escrevendo). f1.close()
Quando executamos um comando print sobre o f2.close()
objeto arquivo, visualizamos o nome do arquivo, o modo e a return
localizao do objeto na memria. A comando break novo. O que ele faz saltar
a execuo para fora do loop; o fluxo de execuo passa para
Para colocar dados dentro do arquivo, o primeiro comando depois do loop.
invocamos o mtodo write do objeto arquivo:
Neste exemplo, o loop while infinito porque o
>>> f.write("Agora hora") valor 1 sempre verdadeiro. O nico modo de sair do loop
>>> f.write("de fechar o arquivo") executando o break, o que ocorre quando texto a string
Fechar o arquivo diz ao sistema que terminamos vazia, o que ocorre quando alcanamos o fim do arquivo.
de escrever (gravar) e que o arquivo est livre para ser lido:
>>> f.close()
Agora podemos abrir o arquivo de novo, desta 11.1 Arquivos texto
vez para leitura, e ler o seu contedo para uma string. Desta
vez, o argumento modo ?r? para leitura (?reading?): Um arquivo texto um arquivo que contm caracteres
imprimveis e espaos, organizados dentro de linhas separadas
>>> f = open("teste.dat", "r") por caracteres de nova linha. J que Pyhton especialmente
Se tentarmos abrir um arquivo que no existe, projetado para processar arquivos texto, ele oferece mtodos
que tornam esta tarefa mais fcil.

Captulo 11: Arquivos e excees #59


Como pensar como um cientista da Computao usando Python

Para demonstrar, vamos criar um arquivo texto mdulo. Mas quando o primeiro operador uma string, % o
com trs linhas de texto separadas por caracteres de nova operador de formatao.
linha:
O primeiro operando a string de formatao,
>>> f = open("teste.dat", "w") e o segundo operando uma tupla de expresses. O resultado
>>> f.write("linha um\nlinha dois\nlinha trs\n") uma string que contm os valores das expresses,
>>> f.close()
formatadas de acordo com a string de formatao.
O mtodo readline l todos os caracteres at, e Num exemplo simples, a seqncia de
incluindo, o prximo caractere de nova linha: formatao "??%d??" significa que a primeira expresso na
tupla deve ser formatada como um inteiro. Aqui a letra d
>>> f = open("teste.dat", "r") representa ?decimal?.
>>> print f.readline()
linha um >>> carros = 52
>>> "%d" % carros
>>> '52'
readlines retorna todas as linhas restantes como O resultado a string ?52?, que no deve ser
uma lista de strings: confundida com o valor inteiro 52.
>>> print f.readlines()
Uma seqncia de formatao pode aparecer em
qualquer lugar na string de formatao, assim, podemos
['linha dois\012', 'linha trs\012'] embutir um valor em uma seqncia:
Neste caso, a sada est em formado de lista, o
que significa que as strings aparecem entre aspas e o caractere >>> carros = 52
de nova linha aparece como a seqncia de escape 012. >>> "Em julho vendemos %d carros." % carros
'Em julho vendemos 52 carros.'
No fim do arquivo, readline retorna a string
vazia e readlines retorna a lista vazia: A seqncia de formatao "%f" formata o
prximo item da tupla como um nmero em ponto flutuante, e
>>> print f.readline() "%s" formata o prximo como uma string:
>>> "Em %d dias fizemos %f milhes %s." % \
>>> print f.readlines()
(34,6.1,'reais')
[]
'Em 34 dias fizemos 6.100000 milhes de reais.'
A seguir temos um exemplo de um programa de
processamento de linhas. filtraArquivo faz uma cpia de Por padro, o formato de ponto flutuante exibe
velhoArquivo, omitindo quaisquer linhas que comecem por #: seis casas decimais.
def filtraArquivo(velhoArquivo, novoArquivo):
O nmero de expresses na tupla tem que ser
igual ao nmero de seqncias de formatao na string. Alm
f1 = open(velhoArquivo, "r") disso, os tipos das expresses tm que iguais aos da seqncia
f2 = open(novoArquivo, "w") de formatao:
while 1:
texto = f1.readline() >>> "%d %d %d" % (1,2)
if texto == "": TypeError: not enough arguments for format string
break >>> "%d" % 'reais'
if texto[0] == '#': TypeError: illegal argument type for built-in \
continue operation
f2.write(texto) No primeiro exemplo, no existem expresses
f1.close()
suficientes; no segundo, a expresso do tipo errado.
f2.close() Para um controle maior na formatao de
return nmeros, podemos especificar o nmero de dgitos como parte
O comando continue termina a iterao corrente da seqncia de formatao:
do loop, mas continua iterando o loop. O fluxo de execuo >>> "%6d" % 62
passa para o topo do loop, checa a condio e prossegue
conforme o caso. ' 62'
>>> "%12f" % 6.1
Assim, se texto for a string vazia, o loop ' 6,100000'
termina. Se o primeiro caractere de texto for o jogo da velha (? O nmero depois do sinal de porcentagem o
# ?), o fluxo de execuo passa para o topo do loop. Somente nmero mnimo de espaos que o valor ocupar. Se o valor
se ambas as condies falharem que texto ser copiado para fornecido tiver um nmero menor de dgitos, espaos em
dentro do novo arquivo. branco sero adicionados antes para preencher o restante. Se o
nmero de espaos for negativo, os espaos sero adicionados
depois:
11.2 Gravando variveis >>> "%-6d" % 62
'62 '
O argumento de write tem que ser uma string, assim se
quisermos colocar outros valores em um arquivo, temos de Para nmeros em ponto-flutuante, tambm
convert-los para strings primeiro. A maneira mais fcil de podemos especificar o nmero de dgitos depois da vrgula:
fazer isso com a funo str: >>> "%12.2f" % 6.1
>>> x = 52 ' 6.10'
>>> f.write(str(x)) Neste exemplo, o resultado reserva 12 espaos e
Uma alternativa usar o operador de inclui dois dgitos depois da vrgula. Esta formatao til
formatao %. Quando aplicado a inteiros, % o operador para exibir valores monetrios com os centavos alinhados.

Captulo 11: Arquivos e excees #60


Como pensar como um cientista da Computao usando Python

Por exemplo, imagine um dicionrio que comandos necessrios. Para us-lo, importe pickle e ento
contm nomes de estudantes como chaves e salrios-hora abra o arquivo da maneira usual:
como valores. Aqui est uma funo que imprime o contedo
do dicionrio como um relatrio formatado: >>> import pickle
>>> f = open(?test.pck?, ?w?)
def relatorio(salarios): Para armazenar uma estrutura de dados, use o
estudantes = salarios.keys() mtodo dump e ento feche o arquivo do modo usual:
estudantes.sort()
for estudante in estudantes: >>> pickle.dump(12.3, f)
print "%-20s %12.02f" % (estudante, \ >>> pickle.dump([1,2,3], f)
salarios[estudante]) >>> f.close()
Para testar esta funo, criaremos um pequeno Ento, podemos abrir o arquivo para leitura e
dicionrio e imprimiremos o contedo: carregar as estruturas de dados que foram descarregadas
(dumped):
>>> salarios = {'maria': 6.23, 'joo': 5.45, \
>>> f = open(?test.pck?, ?r?)
'josu': 4.25}
>>> x = pickle.load(f)
>>> relatorio(salarios)
>>> x
joo 5.45
12,3
josu 4.25
>>> type(x)
maria 6.23
<type ?float?>
Controlando a largura de cada valor, podemos
garantir que as colunas ficaro alinhadas, desde que os nomes >>> y = pickle.load(f)
contenham menos que vinte e um caracteres e os salrios >>> y
sejam menores do que um bilho de reais por hora. [1, 2, 3]
>>> type(y)
<type ?list?>
11.3 Diretrios Cada vez que invocamos load, obtemos um
nico valor do arquivo, completo com seu tipo original.
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 11.5 Excees
modo, quando voc abre um arquivo para leitura, Python
procura por ele no diretrio corrente.
Whenever que um erro em tempo de execuo acontece, ele
Se voc quiser abrir um arquivo que esteja em gera uma exceo. Usualmente, o programa pra e Python
algum outro lugar, voc tem que especificar o caminho (path) exibe uma mensagem de erro.
para o arquivo, o qual o nome do diretrio (ou folder) onde
o arquivo est localizado: Por exemplo, dividir por zero gera uma
exceo:
>>> f = open("/usr/share/dict/words", "r")
>>> print 55/0
>>> print f.readline()
ZeroDivisionError: integer division or modulo
Aarhus
Este exemplo abre um arquivo chamado words Do mesmo modo, acessar um item de lista
que reside em um diretrio de nome dict, o qual reside em inexistente:
share, o qual reside em usr, o qual reside no diretrio de mais >>> a = []
alto nvel do sistema, chamado /. >>> print a[5]
Voc no pode usar / como parte do nome de IndexError: list index out of range
um arquivo; ela um caractere reservado como um Ou acessar uma chave que no est em um
delimitador entre nomes de diretrios e nomes de arquivos. dicionrio:
O arquivo /usr/share/dict/words contm uma >>> b = {}
lista de palavras em ordem alfabtica, na qual a primeira >>> print b[?what?]
palavra o nome de uma universidade Dinamarquesa.
KeyError: what
Em cada caso, a mensagem de erro tem duas
partes: o tipo do erro antes dos dois pontos, e especificidades
11.4 Pickling do erro depois dos dois pontos. Normalmente Python tambm
exibe um ?*traceback*? de onde estava a execuo do
Para colocar valores em um arquivo, voc tem que convert- programa, mas ns temos omitido esta parte nos exemplos.
los para strings. Voc j viu como fazer isto com str: s vezes queremos executar uma operao que
>>> f.write (str(12.3)) pode causar uma exceo, mas no queremos que o programa
>>> f.write (str([1,2,3]))
pare. Ns podemos tratar a exceo usando as instrues try e
except.
O problema que quando voc l de volta o
valor, voc tem uma string. O Tipo original da informao foi Por exemplo, podemos pedir ao usurio um
perdido. De fato, voc no pode sequer dizer onde comea um nome de arquivo e ento tentar abr-lo. Se o arquivo no
valor e termina outro: existe, no queremos que o programa trave; queremos tratar a
exceo:
>>> f.readline()
?12.3[1, 2, 3]? nomedoarquivo = raw_input(?Entre com o nome do \
A soluo o pickling, assim chamado porque ? arquivo: ?)
preserva? estruturas de dados. O mdulo pickel contm os try:

Captulo 11: Arquivos e excees #61


Como pensar como um cientista da Computao usando Python

f = open (nomedoarquivo, ?r?) Se a funo que chamou entraNumero trata o


except: erro, ento o programa pode continuar; de outro modo, Pyhton
print ?No existe arquivo chamado?, nomedoarquivo
exibe uma mensagem de erro e sai:
A instruo try executa os comandos do >>> entraNumero()
primeiro bloco. Se no ocorrerem excees, ele ignora a Escolha um nmero: 17
instruo except. Se qualquer exceo acontece, ele executa os ErroNumeroRuim: 17 um nmero ruim
comandos do ramo except e continua.
A mensagem de erro inclui o tipo da exceo e a
Podemos encapsular esta habilidade numa informao adicional que voc forneceu.
funo: existe toma um nome de arquivo e retorna verdadeiro
se o arquivo existe e falso se no existe: Como um exerccio, escreva uma funo que
use entraNumero para pegar um nmero do teclado e que
def existe(nomedoarquivo) trate a exceo ErroNumeroRuim.
try:
f = open(nomedoarquivo)
f.close() 11.6 Glossrio
return 1
except: arquivo (file) Uma entidade nomeada, usualmente
return 0 armazenada em um disco rgido (HD),
Voc pode usar mltiplos blocos except para disquete ou CD-ROM, que contm uma
tratar diferentes tipos de excees. O Manual de Referncia de seqncia de caracteres.
Python (Python Reference Manual) tem os detalhes.
diretrio Uma coleo nomeada de arquivos,
Se o seu programa detecta uma condio de (directory) tambm chamado de pasta ou folder.
erro, voc pode faz-lo lanar uma exceo. Aqui est um
exemplo que toma uma entrada do usurio e testa se o valor caminho (path) Uma seqncia de nomes de diretrios que
17. Supondo que 17 no seja uma entrada vlida por uma especifica a exata localizao de um
razo qualquer, ns lanamos uma exceo. arquivo.
def entraNumero(): arquivo texto Um arquivo que contm caracteres
(text file) organizados em linhas separadas por
x = input (?Escolha um nmero: ?) caracteres de nova linha.
if x == 17:
raise ?ErroNumeroRuim?, ?17 um nmero ruim? comando Um comando que fora a atual iterao de
return x break (break um loop a terminar. O fluxo de execuo
statement) vai para o topo do loop, testa a condio e
O comando raise toma dois argumentos: o tipo prossegue conforme o caso.
da exceo e informaes especficas sobre o erro.
ErroNumeroRuim um novo tipo de exceo que ns
inventamos para esta aplicao.

Captulo 11: Arquivos e excees #62


Como pensar como um cientista da Computao usando Python

Captulo 12: Classes e objetos

>>> final.y = 4.0


12.1 Tipos compostos definidos pelo usurio Esta sintaxe similar sintaxe para acessar uma
varivel de um mdulo, como math.pi ou string.uppercase.
Depois de usarmos alguns tipos nativos do Python, estamos Neste caso, porm, estamos acessando um item de dado de
prontos para criar um tipo de dados: o Ponto. uma instncia. Estes itens so chamados atributos.
Considere o conceito matemtico de um ponto. O seguinte diagrama de estado mostra o
Em duas dimenses, um ponto um par de nmeros resultado destas atribuies:
(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) representa a origem, e (x, y)
representa o ponto x unidades direita, e y unidades acima da
origem.
Uma maneira natural para representar um ponto
em Python, com dois valores numricos em ponto flutuante.
A questo, ento, como agrupar estes dois valores em um A varivel final refere a um objeto Ponto, que
objeto composto. A maneira rpida e rasteira usar uma lista contm dois atributos. Cada atributo faz referncia a um
ou uma tupla, e para algumas aplicaes, esso pode ser a nmero em ponto flutuante.
melhor escolha1.
Podemos ler o valor de um atributo usando a
Uma alternativa definir um novo tipo mesma sintaxe:
composto, tambm chamado uma classe. Esta abordagem
envolve um pouco mais de esforo, mas ela tem vantagens >>> print final.y
que logo ficaro evidentes. 4.0
Eis a definio de uma classe: >>> x = final.x
>>> print x
class Ponto: 3.0
pass A expresso final.x significa, "V ao objeto
Definies de classes podem aparecer em final e pegue o valor de x". Neste caso, atribumos este valor a
qualquer parte de um programa, mas elas costuma ficar uma varivel cujo nome 'x'. No h conflito entre a varivel
prximas do comeo do programa (aps os comandos import). x e o atributo x. O propsito da notao objeto.atributo
As regras de sintaxe para a definio de classes so as mesmas identificar a qual varivel voc est fazendo referncia de
de outros comandos compostos (veja Seo 4.4). forma que no ambguo.
A definio acima cria uma nova classe Voc pode usar a notao objeto.atributo como
chamada Ponto. O comando pass no tem nenhum efeito; aqui parte de qualquer expresso; assim os seguintes comandos so
ele necessrio porque um comando composto precisa ter vlidos:
algo no seu corpo.
print '(' + str(final.x) + ', ' + str(final.y) + ')'
Quando criamos a classe Ponto, criamos um distAoQuadrado = final.x * final.x + final.y * \
novo tipo de dado, tambm chamado Ponto. Os membros
deste novo tipo so chamados instncias deste tipo ou final.y
objetos. Criar uma nova instncia instanciar. Para A primeira linha imprime (3.0, 4.0); a segunda
instanciar o objeto Ponto, invocamos a funo (adivinhou?) linha calcula o valor 25.0.
Ponto:
tentador imprimir o valor do prprio objeto
final = Ponto() final:
A varivel final agora contm uma referncia a >>> print final
um novo objeto da classe Ponto. Uma funo como Ponto, que <__main__.Ponto instance at 80f8e70>
cria novos objetos, chamada construtor.
O resultado indica que final uma instncia da
classe Ponto e foi definida no prgrama principal: __main__.
80f8e70 o identificador nico deste objeto, escrito em
12.2 Atributos hexadecimal (base 16). Esta no provavelmente a forma
mais informativa para mostrar um objeto Ponto. Logo voc ir
Podemos adicionar novos dados em uma instncia usando a ver como mudar isso.
notao de ponto (dot notation): Como exerccio, crie e imprima um objeto
>>> final.x = 3.0
Ponto, e ento use id para imprimir o identificador nico do
objeto. Traduza a forma hexadecimal para a forma decimal e
1 N.T.: A linguagem Python tambm incorpora um tipo nativo confirme se so compatveis.
complex que representa nmeros complexos. Uma
instncia de complex, como a=3+5j possui dois valores de
ponto flutuante em seus atributos a.real e a.imag, e pode
ser utilizada para armazenar pontos em um espao bi-
dimensional.

Captulo 12: Classes e objetos #63


Como pensar como um cientista da Computao usando Python

Para comparar o contedo dos objetos --


12.3 Instncias como parmetros igualdade profunda -- podemos escrever uma funo chamada
mesmoPonto:
Voc pode passar uma instncia como um parmetro da forma
usual. Por exemplo: def mesmoPonto(p1, p2) :
return (p1.x == p2.x) and (p1.y == p2.y)
def mostrarPonto(p): Agora se criarmos dois diferentes objetos que
print '(' + str(p.x) + ', ' + str(p.y) + ')' contm os mesmos dados, podemos usar mesmoPonto para
A funo mostrarPonto pega o ponto (p) como verificar se eles representam o mesmo ponto.
um argumento e mostra-o no formato padro. Se voc chamar
mostrarPonto(final), a sada ser (3.0, 4.0). >>> p1 = Ponto()
>>> p1.x = 3
Como um exerccio, re-escreva a funo >>> p1.y = 4
distncia da Seo 5.2 para receber dois pontos como >>> p2 = Ponto()
parmetros, ao invs de quatro nmeros.
>>> p2.x = 3
>>> p2.y = 4
>>> mesmoPonto(p1, p2)
12.4 O significado de "mesmo" True
claro, se as duas variveis referirem ao
O significado da palavra "mesmo" parece perfeitamente claro mesmo objeto, elas tm igualdade rasa e igualdade profunda.
at que voc pense a respeito, e ento voc percebe que h
mais nesta palavra do que voc esperava.
Por exemplo, se voc diz "Cris e eu temos o 12.5 Retngulos
mesmo carro", voc est dizendo que o carro de Cris e o seu
so do mesmo fabricante e modelo, mas so dois carros
diferentes. Se voc disser "Cris e eu temos a mesma me", Digamos que desejemos uma classe para representar um
voc est dizendo que a me de Cris e a sua, so a mesma retngulo. A questo , qual informao temos de prover para
pessoa1. Portanto a idia de 'semelhana' diferente especificar um retngulo? Para manter as coisas simples,
dependendo do contexto. assuma que o retngulo orientado verticalmente ou
horizontalmente, nunca em um ngulo.
Quando falamos de objetos, h uma
ambigidade similar. Por exemplo, se dois Pontos forem os H algumas possibilidades: poderamos
mesmos, isto quer dizer que eles contm os mesmos dados especificar o centro do retngulo (duas coordenadas) e seu
(coordenadas) ou que so realmente o "mesmo" objeto? tamanho (largura e altura); ou poderamos especificar um dos
lados e o tamanho; ou poderamos especificar dois lados
Para verificar se duas referncias se referem ao opostos. A escolha convencional especificar o canto superior
'mesmo' objeto, use o operador '==' 2. Por exemplo: esquerdo do retngulo e o tamanho.
>>> p1 = Ponto() Novamente, vamos definir uma nova classe:
>>> p1.x = 3
class Rectangle:
>>> p1.y = 4
pass
>>> p2 = Ponto()
>>> p2.x = 3
E instanci-la:
>>> p2.y = 4 box = Rectangle()
>>> p1 == p2 box.width = 100.0
False box.height = 200.0
Mesmo que p1 e p2 contenham as mesmas Este cdigo cria um novo objeto Retngulo com
coordenadas, os dois no representam o mesmo objeto. Se dois atributos ponto-flutuante. Para especificar o canto
atribuirmos p1 a p2, ento as duas variveis so pseudnimos superior esquerdo, podemos embutir um objeto dentro de um
do mesmo objeto. objeto!
>>> p2 = p1 box.corner = Ponto()
>>> p1 == p2 box.corner.x = 0.0;
True box.corner.y = 0.0;
Este tipo de igualdade chamado de igualdade A expresso box.corner.x significa, "v ao
rasa porque ela compara somente as referncias e no o objeto referenciado por 'box' e selecione o atributo 'corner';
contedo dos objetos. ento v ao objeto 'corner' e deste, selecione o atributo de
nome 'x'".
1 Nem todos os idiomas tm este problema. Por exemplo,
em alemo h palavras diferentes para diferentes sentidos A figura mostra o estado deste objeto:
de "mesmo". "Mesmo carro" nesse contexto seria "gleiche
Auto", e "mesma me" seria "selbe Mutter".
2 LR: Eu no diria que devemos usar == para verificar se
dois objetos so o mesmo. Isto uma falha do livro que
talvez se origine no original que falava de Java. Em Python
o operador is faz o mesmo que o == de Java: compara
referncias, e portanto serve para determinar se duas
variveis apontam para o mesmo objeto. No entanto, a o
cdigo acima est correto porque em Python a
implemetao default de == (mtodo __eq__) comparar o
id das instncias, porm as classes list e dict, por exemplo,
implementam __eq__ comparando os valores contidos (ex.:
isto retorna True: l1 = [1,2,3]; l2 = [1,2,3]; l1 == l2).

Captulo 12: Classes e objetos #64


Como pensar como um cientista da Computao usando Python

>>> import copy


12.6 Instancias como valores retornados >>> p1 = Ponto()
>>> p1.x = 3
Funes podem retornar instncias. Por exemplo, findCenter >>> p1.y = 4
pega um Retngulo como um argumento e retorna um Ponto
que contem as coordenadas do centro do retngulo: >>> p2 = copy.copy(p1)
>>> p1 == p2
def findCenter(box): 0
p = Ponto() >>> mesmoPonto(p1, p2)
p.x = box.corner.x + box.width/2.0 1
p.y = box.corner.y + box.height/2.0 Uma vez que importamos o modulo 'copy',
Para chamar esta funo, passe 'box' como um podemos usar o mtodo 'copy' para criar um outro 'Ponto'. p1
argumento e coloque o resultado em uma varivel. e p2 no representam o mesmo ponto, mas eles contem os
mesmo dados.
>>> center = findCenter(box)
>>> print mostrarPonto(center) Para copiar um simples objeto como um 'Ponto',
(50.0, 100.0) 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 'Ponto', o mtodo 'copy' no
12.7 Objetos so mutveis ir executar corretamente a copia. Ele ir copiar a referencia
para o objeto 'Ponto', portanto o que acontece aqui que os
Podemos mudar o estado de um objeto fazendo uma dois Rectangle (o novo e o antigo) iro fazer referencia a um
atribuio a um dos seus atributos. Por exemplo, para mudar o simples 'Ponto'.
tamanho de um retngulo sem mudar sua posio, podemos
modificar os valores de sua largura e altura. Veja: Em outras palavras, se criarmos um 'box', c1,
utilizando a forma usual, e depois fazer uma copia, c2, usando
box.width = box.width + 50 o mtodo 'copy', o diagrama de estado resultante ficar assim:
box.height = box.height + 100
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 o resultado no ser o que esperamos. Neste
quanto vamos aumentar o tamanho do retngulo em cada caso, invocando 'growRect' em um dos retngulos (c1), isto
direo. Chamando este mtodo, teramos o mesmo efeito. no ir afetar o outro retngulo (c2, neste exemplo). Mas se
usarmos o mtodo 'moveRect' em qualquer um deles, isto ir
Por exemplo, poderamos criar um novo inevitavelmente afetar o outro. Este comportamento confuso
Retngulo com o nome de 'bob' e passar este nome para o e propenso a erros!
mtodo growRect:
Mas felizmente o modulo 'copy' contem um
>>> bob = Rectangle() mtodo chamado 'deepcopy' que copia no somente o objeto,
>>> bob.width = 100.00 mas tambm copia todo e qualquer objeto 'embutido' neste
>>> bob.height = 200.00
objeto. Por isto, voc no ficar surpreso porque este mtodo
chama-se 'deepcopy' (copia profunda) no ? Veja como
>>> bob.corner.x = 0.0; funciona:
>>> bob.corner.y = 0.0;
>>> growRect(bob, 50, 100) >>> c2 = copy.deepcopy(c1)
Enquanto growRect est sendo executado, o Agora, c1 e c2 so objetos completamente
parmetro 'box' um alias (apelido) para 'bob'. Qualquer separados.
mudana feita em 'box', tambm ir afetar 'bob'. Podemos usar 'deepcopy' para re-escrever
Como exerccio, escreva uma function (mtodo) 'growRect' sendo que ao invs de modificar um Rectangle
com o nome de moveRect que pega um Rectangle e dois existente, ele cria um novo que tem a mesma localizao do
parmetros com o nome de 'dx' e 'dy'. Esta funo dever outro, mas com novas dimenses:
mudar a localizao do retngulo atravs da adio de 'dx'
coordenada 'x' e da adio de 'dy' coordenada 'y'. def growRect(box, dwidth, dheight):
import copy
newBox = copy.deepcopy(box)
newBox.width = newBox.width + dwidth
12.8 Copiando newBox.height = newBox.height + dheight
return newBox
Ao usar 'alias' - como fizemos na seo anterior - podemos
tornar o programa um pouco difcil de ler ou entender, pois as Como exerccio, re-escreva o mtodo
mudanas feitas em um local, podem afetar inesperadamente 'moveRect' para ele criar e retornar um novo Rectangle ao
um outro objeto. E pode se tornar difcil de encontrar todas as invs de apenas modificar o antigo.
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:

Captulo 12: Classes e objetos #65


Como pensar como um cientista da Computao usando Python

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 Criar uma instncia de uma classe.
(instantiate)
instncia Um objeto que pertence a uma classe.
(instance)
objeto (object) Um tipo de dado composto comumente
utilizado para representar uma coisa ou
um conceito do mundo real.
construtor Um mtodo utilizado para criar novos
(constructor) objetos.
atributo Um dos itens de dados nomeados que
(attribute) compem uma instncia.
igualdade rasa Igualdade de referncias; ocorre quando
(shallow duas referncias apontam para o mesmo
equality) objeto.
igualdade Igualdade de valores; ocorre quando duas
profunda (deep referncias apontam para objetos que tm
equality) o mesmo valor.
cpia rasa Ato de copiar o contedo de um objeto,
(shallow copy) incluindo as referncias a objetos
embutidos (XXX embedded);
implementada pela funo copy do
mdulo copy.
cpia profunda Ato de copiar o contedo de um objeto,
(deep copy) 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 #66


Como pensar como um cientista da Computao usando Python

Captulo 13: Classes e funes

quantidade de tempo que a mquina de fazer po gasta para


13.1 Horario fazer po. Ento vamos usar somaHorario para tentar saber
quando o po estar pronto. Se voc no tiver terminado de
Como exemplo de outro tipo definido pelo usurio, vamos escrever imprimirHorario ainda, de uma olhada na seo 14.2
definir uma classe chamada Horario que grava os registros de antes de voc continuar isso:
horrio do dia. Eis a definio da classe:
>>> horarioAtual = Horario()
class Horario: >>> horarioAtual.horas = 9
pass >>> horarioAtual.minutos = 14
Podemos criar uma nova instncia de Horario e >>> horarioAtual.segundos = 30
determinar atributos para horas, minutos e segundos:
>>> horarioDoPao = Horario()
horario = Horario()
>>> horarioDoPao.horas = 3
horario.horas = 11
>>> horarioDoPao.minutos = 35
horario.minutos = 59
>>> horarioDoPao.segundos = 0
horario.segundos = 30
O diagrama de estado para o objeto Horario
parece com isso: >>> 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, temos de
"transportar" os segundos extras para a coluna dos minutos ou
os minutos extras na coluna das horas.
Como exerccio, escreva uma funo Aqui est a segunda verso corrigida da funo:
'imprimirHorario' que tenha como argumento um objeto
Horario e imprima-o na forma horas:minutos:segundos. def somaHorario(t1, t2):
soma = Horario()
Como um segundo exerccio, escreva uma
funo booleana que tenha como argumento dois objetos soma.horas = t1.horas + t2.horas
Horario, h1 e h2, e retorne verdadeiro (1) se h1 vem depois soma.minutos = t1.minutos + t2.minutos
de h2 cronologicamente, do contrrio, retorne falso (0). soma.segundos = t1.segundos + t2.segundos

if soma.segundos >= 60:


13.2 Funes Puras soma.segundos = soma.segundos - 60
soma.minutos = soma.minutos + 1
Nas prximas sesses, vamos escrever duas verses de uma
funo chamada adicionaHorario, que calcula a soma de dois if soma.minutos >= 60:
horrios. Elas vo demonstrar 2 tipos de funes: funes soma.minutos = soma.minutos - 60
puras e funes modificadoras. soma.horas = soma.horas + 1
Segue uma verso rudimentar de somaHorario:
return soma
def somaHorario(h1, h2):
Apesar desta funo estar correta, ela est
soma = Horario() comeando a ficar grande. Depois vamos sugerir uma
soma.horas = h1.horas + h2.horas aproximao alternativa que rende um cdigo menor. Clique
soma.minutos = h1.minutos + h2.minutos aqui para feedback
soma.segundos = h1.segundos + h2.segundos
return soma
A funo cria um novo objeto Horario, 13.3 Modificadores
inicializa os seus atributos, e retorna uma referncia para o
novo objeto. Isso chamado de funo pura pois ela no Existem momentos quando til para uma funo modificar
modifica nenhum dos objetos que so passados como um ou mais dos objetos que ela recebe como parmetro.
parmetros e no tem nenhum efeito colateral, como imprimir Usualmente, quem est chamando a funo mantm uma
um valor ou pegar entrada do usurio. referncia para os objetos que ele passa, de forma que
Aqui est um exemplo de como usar esta quaisquer mudanas que a funo faz so visveis para quem
funo. Ns vamos criar dois objetos Horario: horarioAtual, est chamando. Funes que trabalham desta forma so
que contm o horrio atual; e horarioDoPao, que contm a chamadas modificadores.

Captulo 13: Classes e funes #67


Como pensar como um cientista da Computao usando Python

incrementar, que adiciona um nmero dado de


segundos para um objeto Horario, poderia ser escrito quase 13.5 Desenvolvimento Prototipado versus
naturalmente como um modificador. Um rascunho rudimentar
da funo seria algo parecido com isso: Desenvolvimento Planejado
def incrementar(horario, segundos): Neste captulo, demonstramos uma aproximao para o
horario.segundos = \ desenvolvimento de programas que chamamos de
horario.segundos + segundos desenvolvimento prototipado. Em cada caso, escrevemos um
rascunho rudimentar (ou prottipo) que executou os clculos
if horario.segundos >= 60: bsicos e ento, o testamos em uns poucos casos, corrigindo
as falhas que fomos encontrando.
horario.segundos = \
horario.segundos - 60 Embora esta aproximao possa ser eficaz, ela
horario.minutos = horario.minutos + 1 pode conduzir a cdigo que desnecessariamente complicado
pois trata de muitos casos especiais e no confivel, pois
difcil saber se voc encontrou todos os erros.
if horario.minutos >= 60:
horario.minutos = \ Uma alternativa o desenvolvimento planejado,
horario.minutos - 60 onde uma viso de alto nvel do problema pode tornar a
horario.horas = horario.horas + 1 codificao muito mais fcil. Nesse caso, a abstrao que
um objeto Horario realmente um nmero de trs digitos na
A primeira linha executa a operao bsica; o base 60! O componente segundo a "coluna dos uns", o
resto lida com os caso especiais que vimos antes. componente minuto a "coluna do 60", e o componente hora
Esta funo est correta ? O que aconteceria se a "coluna do 360".
o parmetro segundos for muito maior que sessenta ? Nesse Quando ns escrevemos somaHorario e
caso, no suficiente transportar apenas uma vez; teramos de incrementar, ns estvamos efetivamente fazendo adies em
continuar fazendo isso at que segundos seja menor que base 60, que o motivo pelo qual tinhamos de transportar de
sessenta. Uma soluo seria substituir os comando if por uma coluna para a prxima.
comandos while:
Essa observao sugere uma outra aproximao
def incrementar(horario, segundos): para todo o problema - ns podemos converter um objeto
horario.segundos = \ Horario em um nmero simples e levar vantagem do fato de
horario.segundos + segundos que um computador sabe como fazer aritmtica com nmeros.
A seguinte funo converte o objeto Horario em um inteiro:
while horario.segundos >= 60: def converterParaSegundos(t):
horario.segundos = horario.segundos - minutos = t.horas * 60 + t.minutos
60 segundos = minutos * 60 + t.segundos
horario.minutos = horario.minutos + 1 return segundos
Agora, tudo que precisamos uma maneira de
while horario.minutos >= 60: converter de um inteiro para um objeto Horario:
horario.minutos = \
horario.minutos - 60 def criarHorario(segundos):
horario.horas = horario.horas + 1 horario = Time()
Esta funo agora esta correta, mas no a horario.horas = segundos/3600
soluo mais eficiente. segundos = segundos - horario.horas * 3600
horario.minutos = segundos/60
Como um exerccio, reescreva esta funo de segundos = segundos - horario.minutos * 60
maneira que ela no contenha nenhum loop. Como um
segundo exerccio, reescreva incrementar como uma funo horario.segundos = segundos
pura, e escreva chamadas de funes para as duas funes. return horario
Clique aqui para feedback 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:
13.4 O que melhor ?
def somaHorario(t1, t2):
Qualquer coisa que pode ser feita com modificadores tambm segundos = \
podem ser feitas com funes puras. De fato, algumas converterParaSegundos(t1) + converterParaSegundos(t2)
linguagens de programao permitem apenas funes puras. return criarHorario(segundos)
Existe alguma evidncia que programas que usam funes
puras so desenvolvidos mais rapidamente e so menos Esta verso muito mais curta que a original, e
propensos a erros que programas que usam modificadores. No muito mais fcil para demonstrar que est correta
entanto, modificadores as vezes so convenientes, e em alguns (assumindo, como sempre, que as funes que so chamadas
casos, programao funcional menos eficiente. esto corretas).
Em geral, recomendamos que voc escreva Como um exerccio, reescreva incrementar da
funes puras sempre que for necessrio e recorrer para mesma forma. Clique aqui para feedback
modificadores somente se existir uma grande vantagem. Esta
aproximao poderia ser chamada de um estilo de
programao funcional. 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.

Captulo 13: Classes e funes #68


Como pensar como um cientista da Computao usando Python

Converso de base mais abstrata; nossa intuio para lidar Na nossa opinio, preocupante que humanos
com horrios melhor. gastem tanto tempo na escola aprendendo a executar
algoritmos que, literalmente, no requerem inteligncia.
Mas se conseguirmos abstrair horrios como
nmeros de base 60 e investirmos em criar as funes de Por outro lado, o processo de projetar
converso (converterParaSeguntos e criarHorario), ns algoritmos interessante, intelectualmente desafiante, e uma
conseguimos um programa que menor, fcil de ler e depurar, parte central daquilo que chamamos programao.
e mais confivel.
Algumas das coisas que as pessoas fazem
tambm fcil para adicionar funcionalidades naturalmente, sem dificuldade ou conscincia, so as mais
depois. Por exemplo, imagine subtrair dois Horarios para difceis de se expressar atravs de algoritmos. Entender a
encontrar a durao entre eles. Uma aproximao ingnua linguagem natural um bom exemplo. Todos ns fazemos
seria implementar subtrao com emprstimo. Usando as isso, mas at hoje ningum conseguiu explicar como fazemos
funes de converso ser mais fcil e provavelmente estar isso, pelo menos no na forma de algoritmo. Clique aqui para
correto. feedback.
Ironicamente, algumas vezes fazer um problema
mais difcil (ou mais genrico) o torna mais simples (porque
existem alguns poucos casos especiais e poucas oportunidades 13.8 Glossrio
para errar). Clique aqui para feedback
funo pura (pure Uma funo que no modifica
function) nenhum dos objetos que ela recebe
13.7 Algoritmos como parmetro. A maioria das
funes puras frutfera.
Quando voc escreve uma soluo genrica para uma classe modificador Uma funo que muda um ou mais
de problemas, ao contrrio de uma soluo especfica para um (modifier) dos objetos que ela recebe como
nico problema, voc escreveu um algoritmo. Ns parmetros. A maioria dos
mencionamos isso antes mas no definimos cuidadosamente. modificadores nula.
Isso no fcil para definir, ento vamos tentar definir
demonstrando algumas situaes. estilo de Um estilo de programao onde a
programao maioria das funes so puras.
Primeiramente, considere alguma coisa que no funcional (functional
seja um algoritmo. Quando voc aprendeu a multiplicar programming style)
nmeros de um dgito, voc provavelmente memorizou a
tabela de multiplicao. Como resultado, voc memorizou 100 desenvolvimento Uma maneira de desenvolver
solues especficas. Esse tipo de conhecimento no prototipado programas comeando com um
algoritmo. (prototype prottipo e gradualmente
development) melhorando-o.
Mas se voc "preguioso", voc
provavelmente trapaceou por ter aprendido alguns truques. desenvolvimento Uma maneira de desenvolver
Por exemplo, para encontrar o produto de n e 9, voc pode planejado (planned programas que envolvem uma
escrever n-1 como o primeiro dgito e 10-n como o segundo development) percepo de alto nvel do problema
dgito. Este truque um soluo genrica para multiplicar e mais planejamento do que
qualquer nmero de um dgito por 9. Isso um algoritmo! desenvolvimento incremental ou
desenvolvimento prototipado.
De modo parecido, as tcnicas que voc
aprendeu para somar com transporte, subtrao com algoritmo (algorithm) Um conjunto de instrues para
emprstimo, e diviso longa so todas algoritmos. Uma das resolver uma classe de problemas
caractersticas dos algoritmos que eles no requerem usando um processo mecnico, no
nenhuma inteligncia para serem executados. Eles so inteligente.
processos mecnicos no qual cada passo segue o ltimo de
acordo com um conjunto simples de regras.

Captulo 13: Classes e funes #69


Como pensar como um cientista da Computao usando Python

Captulo 14: Classes e mtodos

ATENO As referncias cruzadas a nomes em cdigos de


outros captulos (especialmente 13) ainda no foram 14.2 exibeHora (printTime)
unificadas...
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:
14.1 Caractersticas da orientao a objetos
class Horario:
Python uma linguagem de programao orientada a pass
objetos, o que significa que ela tem caractersticas que
suportam a programao orientada a objetos. def exibeHora(time)
No fcil definir programao orientada a print str(time.horas) + ?:? + \
objetos, mas temos visto already algumas de suas str(time.minutos) + ?:? + \
caractersticas: str(time.segundos)
Programas so construdos sobre definies de Para chamar esta funo, passamos um objeto
objetos e definies de funes, e a maioria das Time como um parmetro:
computaes expressa em termos de operaes
sobre objetos. >>> horaCorrente = Hora()
>>> horaCorrente.horas = 9
Cada definio de objeto corresponde a algum objeto >>> horaCorrente.minutos = 14
ou conceito do mundo real, e as funes que operam >>> horaCorrente.segundos = 30
com aqueles objetos correspondem maneira como
os objetos do mundo real interagem. >>> exibeHora(horaCorrente)
Para fazer de exibeHora um mtodo, tudo o que
Por exemplo, a classe Tempo, definida no temos a fazer mover a definio da funo para dentro da
captulo 13 corresponde maneira como as pessoas registram definio da classe. Note a mudana na endentao:
as horas do dia, e as funes que definimos correspondem aos
tipos de coisas que as pessoas fazem com times. Do mesmo class Horario:
modo, as classes Ponto e Retngulo correspondem aos def exibeHora(time):
conceitos matemticos de um ponto e de um retngulo. print str(time.horas) + ?:? + \
At aqui, no tiramos vantagem das str(time.minutos) + ?:? + \
caractersticas fornecidas por Python que suportam a str(time.segundos)
programao orientada a objetos. Estritamente falando, estas Agora podemos chamar exibeHora usando a
caractersticas no so necessrias. Na maior parte das vezes, natao de ponto:
elas fornecem uma sintaxe alternativa para as coisas que j
fizemos, mas em muitos casos, a alternativa mais concisa e >>> horaCorrente.exibeHora()
convm mais acuradamente estrutura do programa. Como usual, o objeto no qual o mtodo
Por exemplo, no programa Time, no existe invocado aparece antes do ponto e o nome do mtodo aparece
uma conexo bvia entre a definio da classe e a definio da depois do ponto.
funo que segue. Com alguma investigao, fica aparente O objeto no qual o mtodo invocado
que toda funo toma pelo menos um objeto Time como um atribudo ao primeiro parmetro, ento, neste caso,
parmetro. horaCorrente atribudo ao parmetro time.
Esta observao a motivao por trs dos Por conveno, o primeiro parmetro de um
mtodos. J temos visto alguns mtodos, tais como keys mtodo chamado self. A razo para isto um pouco
(chaves) e values (valores), os quais foram invocados em convoluted, mas baseada numa metfora til.
dicionrios. Cada mtodo associado com uma classe e
intended para ser invocado em instncias daquela classe. A sintaxe para uma chamada de funo,
exibeHora(horaCorrente), sugere que a funo um agente
Mtodos so simplesmente como funes, com ativo. Diz algo como, ?Ei, exibeHora! Aqui est um objeto
duas diferenas: para voc exibir.?
Mtodos so definidos dentro da definio de uma Na programao orientada a objetos, os objetos
classe para tornar explcita a relao entre a classe e o so agentes ativos. Uma chamado do tipo
mtodo. horaCorrente.exibeHora() diz ?Ei, horaCorrente! Por favor
A sintaxe para a chamada do mtodo diferente da exiba-se a si mesmo!?
sintaxe para a chamada de uma funo. Esta mudana de perspectiva pode ser mais
Nas prximas sees, vamos pegar as funes polida, mas no fica bvio que seja til. Nos exemplos que
dos dois captulos anteriores e transform-las em mtodos. temos visto at aqui, pode ser que no seja. Mas s vezes,
Esta transformao puramente mecnica: voc pode deslocar a responsabilidade das funes para cima dos objetos
consegu-la simplesmente seguindo uma seqncia de passos. torna possvel escrever funes mais versteis, e torna mais
Se voc se sentir confortvel convertendo de uma forma para fcil manter e reutilizar o cdigo.
a outra, voc estar apto para escolher a melhor forma para
seja o l o que for que voc estiver fazendo.

Captulo 14: Classes e mtodos #70


Como pensar como um cientista da Computao usando Python

14.3 Um outro exemplo orientada a tais como classes definidas pelo usurio e
objetos herana, que facilitam a programao
orientada a objetos.
Vamos converter incremento (da Seo 13.3) em um mtodo.
Para poupar espao, deixaremos de fora mtodos definidos programao Um estilo de programao na qual os
previamente(anteriormente?), mas voc deve mant-los em orientada a dados e as operaes que os manipulam
sua verso: objetos esto organizados em classes e mtodos.
class Time: mtodo Uma funo que definida dentro de uma
#previous method definitions here... definio de classe e chamada em
instncias desta classe.
def increment(self, segundos): override (sem Substituir uma definio j pronta.
self.seconds = seconds + self.seconds traducao; Exemplos incluem substituir um
termo parmetro padro por um argumento
consagrado) particular e substituir um mtodo padro,
while self.segundos >= 60: fornecendo um novo mtodo com o
self.seconds = self.segundos - 60 mesmo nome.
self.minutes = self.minutos + 1
mtodo de Um mtodo especial que invocado
inicializao automaticamente quando um novo objeto
while self.minutes >= 60: (tambem criado e que inicializa os atributos deste
self.minutes = self.minutos - 60 chamado de objeto.
self.hours = self.horas + 1 construtor)
A transformao puramente mecnica ? sobrecarga de Estender a funcionalidade dos operadores
movemos a definio do mtodo para dentro da definio da operador nativos (+, -, *, >, <, etc.) de forma que
classe e mudamos o nome do primeiro parmetro. eles funcionem tambm com tipos
Agora podemos chamar incremento como um definidos pelo usurio.
mtodo: produto escalar Operao definida na lgebra linear que
horaCorrente.incremento(500) multiplica dois pontos (com coordenadas
(x,y,z)) e retorna um valor numrico.
De novo, o objeto no qual o mtodo chamado
gets atribui ao primeiro parmetro, self. O segundo parmetro, multiplicao Operao definida na lgebra linear que
segundo toma(gets) o valor 500. por escalar multiplica cada uma das coordenadas de
um ponto por um valor numrico.
Como um exerccio, converta ?
converteParaSegundos? (da Seo 13.5) para um mtodo na polimrfica Uma funo que pode operar com mais de
classe ?Time?. 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.
14.10 Glossrio

linguagem Uma linguagem que prov caractersticas

Captulo 14: Classes e mtodos #71


Como pensar como um cientista da Computao usando Python

Captulo 15: Conjuntos de objetos

Rainha -> 12
15.1 Composio
Rei -> 13
At agora, voc vio diversos exemplos de composio. Um O motivo pelo qual ns estamos usando notao
dos primeiros exemplos foi o uso de uma invocao de matemtica para estes mapeamentos que eles no so parte
mtodo como parte de uma expresso. Outro exemplo a do programa Python. Eles so parte do projeto do programa,
estrutura aninhada dos comandos: voc pode pr um comando mas eles nunca aparecem explicitamente no cdigo. A
if dentro de um lao while, dentro de outro comando if, e definio de classe para o tipo Carta fica parecida com esta:
assim por diante.
class Carta:
Tendo visto este padro, e tendo aprendido a
respeito de listas e objetos, voc no deveria ficar surpreso em def __init__(self, naipe=0, posicao=0):
aprender que voc pode criar listas de objetos. Voc tambm self.naipe = naipe
pode criar obejtos que contm listas (como atritos); voc pode self.posicao = posicao
criar listas que contm listas; voc pode criar objetos que Como sempre, ns fornecemos um mtodo de
contm objetos; e assim por diante. inicializao que recebe um parmetro opcional para cada
Neste captulo e no prximo, voc ir ver alguns atributo.
exemplos destas combinaes, usando objetos Carta como Para criar um objeto que representa o 3 de Paus,
exemplo. usa-se este comando:
tresDePaus = Carta(0, 3)
15.2 Objetos Carta O primeiro argumento, 0, representa o naipe de
Paus.
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 15.3 Atributos de classe e o mtodo __str__
baralho, cada uma das quais pertence a um dos quatro naipes e
a uma das treze posies. Os naipes so Espadas, Copas, Para imprimir objetos Carta de uma maneira que as pessoas
Ouros e Paus (em ordem descendente no bridge). As posies possam facilmente ler, ns gostaramos de mapear os cdigos
so s, 2, 3, 4, 5, 6, 7, 8, 9, 10, Valete, Rainha e Rei. inteiros para palavras. Uma forma natural de fazer isso usar
Dependendo do jogo, a posio do s pode ser maior do que a listas de strings. Ns atribumos estas listas para atributos de
do Rei ou menor do que a do 2. classe no topo da definio de classe:
Se quisermos definir um novo objeto para class Carta:
representar uma carta, bvio que os atributos devem ser
posicao e naipe. No to bvio so os tipos aos quais devem listaDeNaipes = ["Paus", "Ouros", "Copas",
pertencer os atributos. Uma possibilidade usar strings "Espadas"]
contendo palavras como "Espada" para naipes e "Rainha" para listaDePosicoes = ["narf", "s", "2", "3", "4",
posies. Um problema com esta implementao que no "5", "6", "7",
seria fcil comparar cartas para ver qual possui o maior naipe "8", "9", "10", "Valete",
ou posio. "Rainha", "Rei"]
Uma alternativa usar inteiros para codificar as
posies e naipes. "Codificar", neste caso, no significa o # mtodo init omitido
mesmo que as pessoas normalmente pensam, que
criptografar ou traduzir para um cdigo secreto. O que um def __str__(self):
cientista da computao quer dizer com "codificar" "definir return (self.listaDePosicoes[self.posicao] +
um mapeamento entre uma seqncia de nmeros e os itens " de " + self.ListaDeNaipes[self.naipe])
que eu quero representar". Por exemplo:
Um atributo de classe definido fora de
Espadas -> 3 qualquer mtodo, e ele pode ser acessado por quaisquer
mtodos da classe.
Copas -> 2
Dentro de __str__, ns podemos usar
Ouros -> 1 listaDeNaipes e listaDePosicoes para mapear os valores
Paus -> 0 numricos de naipe e posicao para strings. Por exemplo, a
expresso self.listaDeNaipes[self.naipe] significa "use o
Uma caracterstica bvia deste mapeamento atributo naipe do objeto self como um ndice para o atributo
que os naipes so mapeados para inteiros na ordem, de modo de classe chamado listaDeNaipes, e selecione a string
que ns podemos comparar naipes pela comparao de apropriada".
inteiros. O mapeamento de posies bastante bvio. Cada O motivo para o "narf" no primeiro elemento
uma das posies numricas mapeia para o inteiro em listaDePosicoes preencher o lugar do 0-simo elemento
correspondente e, as cartas com figura so mapeadas da lista, que nunca ser usado. As nicas posies vlidas so
conforme abaixo: de 1 a 13. Este item desperdiado no inteiramente
Valete -> 11 necessrio. Ns poderamos ter iniciado com 0, como
normal. Porm, menos confuso codificar 2 como 2, 3 como

Captulo 15: Conjuntos de objetos #72


Como pensar como um cientista da Computao usando Python

3, e assim por diante. # verificar os naipes


if self.naipe > other.naipe: return 1
Com os mtodos que ns temos at agora, ns
podemos criar e imprimir cartas: if self.naipe < other.naipe: return -1
# as cartas tm o mesmo naipe... verificar as
>>> carta1 = Carta(1, 11) posies
>>> print carta1 if self.posicao > other.posicao: return 1
Valete de Ouros if self.posicao < other.posicao> return -1
Atributos de classe como listaDeNaipes so # as posies so iguais... um empate
compartilhados por todos os objetos Carta. A vantagem disso return 0
que ns podemos usar qualquer objeto Carta para acessar os Nesta ordenao, Ases so menores do que 2.
atributos de classe:
Como um exerccio, modifique ``__cmp__``, de
>>> carta2 = Carta(1, 3) modo que os Ases sejam maiores do que os Reis.
>>> print carta2
3 de Ouros
>>> print carta2.listaDeNaipes[1]
Ouros
15.5 Baralhos
A desvantagem que se ns modificarmos um
atributo de classe, isso afetar cada instncia da classe. Por Agora que ns temos objetos para representar Cartas, o
exemplo, se ns decidirmos que "Valete de Ouros" deveria prximo passo lgico definir uma classe para representar um
realmente se chamar "Valete de Baleias Rodopiantes", ns Baralho. claro que um baralho formado por cartas;
poderamos fazer isso: portanto, cada objeto Baralho ir conter uma lista de cartas
como um atributo.
>>> carta1.listaDeNaipes = "Baleias Rodopiantes"
A seguir, damos uma definio para a classe
>>> print carta1 Baralho. O mtodo de inicializao cria o atributo cartas e
3 de Baleias Rodopiantes gera o conjunto padro de 52 cartas:
O problema que todos os Ouros se tornam
Baleias Rodopiantes: classe Baralho
def __init__(self):
>>> print carta2 self.cartas = []
3 de Baleias Rodopiantes for naipe in range(4):
Normalmente, no uma boa idia modificar for posicao in range(1, 14):
atributos de classe. 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
15.4 Comparando cartas 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
Para tipos primitivos, existem operadores condicionais (<, >, quatro). Cada iterao cria uma nova instncia de Carta com o
==, etc.) que comparam valores e determinam quando um naipe e posio atuais e a inclui na lista cartas.
maior que, menor que ou igual a outro. Para tipos definidos
pelo usurio, ns podemos sobrescrever o comportamento dos O mtodo append trabalha sobre listas mas no,
operadores pr-definidos fornecendo um mtodo __cmp__. obviamente, sobre tuplas.
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.
15.6 Imprimindo o baralho
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 Como sempre, quando ns definimos um novo tipo de objeto,
de ponto flutuante so totalmente ordenados. Alguns ns gostaramos de ter um mtodo para imprimir o contedo
conjuntos so no-ordenados, o que significa que no existe de um objeto. Para imprimir um Baralho, ns percorremos a
maneira significativa de dizer que um elemento maior que o lista e imprimimos cada Carta:
outro. Por exemplo, as frutas so no-ordenadas, e por isso class Baralho:
que no podemos comparar mas e laranjas.
...
O conjunto de cartas de jogo parcialmente def imprimirBaralho(self):
ordenado, o que significa que s vezes voc pode comparar for carta in self.cartas:
cartas, e s vezes no. Por exemplo, voc sabe que o 3 de Paus print carta
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 Aqui, e a partir daqui, as reticncias (...)
Ouros? Um tem uma posio maior, mas o outro tem um indicam que ns omitimos os outros mtodos da classe.
naipe maior. Como uma alternativa a imprimirBaralho, ns
Para tornar as cartas comparveis, voc tem que poderamos escrever um mtodo __str__ para a classe
decidir o que mais importante: posio ou naipe. Para ser Baralho. A vantagem de __str__ que ela mais flexvel. Em
honesto, a escolha arbitrria. Por questo de escolha, ns vez de apenas imprimir o contedo de um objeto, ela gera uma
iremos dizer que naipe mais importante, porque um baralho representao em string que outras partes do programa podem
de cartas novo vem ordenado com todas as cartas de Paus manipular antes de imprimir ou armazenar para uso posterior.
juntas, seguidas pelas de Ouros, e assim por diante. Abaixo, uma verso de __str__ que devolve
Com essa deciso, ns podemos escrever uma representao em string de um Baralho. Para adicionar
__cmp__: um pouco de estilo, ela distribui as cartas em uma cascata, na
qual cada carta indentada um espao a mais do que a carta
def __cmp__(self, other): anterior:

Captulo 15: Conjuntos de objetos #73


Como pensar como um cientista da Computao usando Python

class Baralho: totalmente aleatria:


...
class Baralho:
def __str__(self):
...
s = ""
def embaralhar(self):
for i in range(len(self.cartas)):
import random
s = s + " "*i + str(self.cartas[i]) + "\n"
nCartas = len(self.cartas)
return s
for i in range(nCartas):
Este exemplo demonstra diversas j = random.randrange(i, nCartas)
caractersticas. Primeiro, em vez de percorrer self.cartas e
atribuir cada carta a uma varivel, ns estamos usando i como self.cartas[i], self.cartas[j] =
uma varivel de lao e um ndice para a lista de cartas. self.cartas[j], self.cartas[i]
Em vez de assumir que existem 52 cartas no
Segundo, ns estamos usando o operador de baralho, ns obtivemos o comprimento real da lista e o
multiplicao de strings para indentar cada carta com um guardamos na varivel nCartas.
espao adicional com relao anterior. A expresso " "*i
produz um nmero de espaos igual ao valor atual de i. Para cada carta no baralho, ns escolhemos uma
carta aleatria dentre as cartas que ainda no foram
Terceiro, em vez de usar o comando print para embaralhadas. Ento, ns trocamos a carta atual (i) pela carta
imprimir as cartas, ns usamos a funo str. Passar um objeto selecionada (j). Para trocar as cartas, ns usamos uma
como um argumento para str equivale a invocar o mtodo atribuio de tupla, como visto na Seo 9.2:
__str__ sobre o objeto.
self.cartas[i], self.cartas[j] = self.cartas[j],
Finalmente, ns estamos usando a varivel s self.cartas[i]
como um acumulador. Inicialmente, s a string vazia. A cada
repetio do lao, uma nova string gerada e concatenada Como exerccio, reescreva esta linha de cdigo
com o valor antigo de s para obter um novo valor. Quando o sem usar uma atribuio de seqncia.
lao termina, s contm a representao em string completa do
Baralho, que se parece com:
>>> baralho = Baralho()
15.8 Removendo e distribuindo cartas
>>> print Baralho
s de Paus Outro mtodo que pode ser til para a classe Baralho
removerCarta. Ele recebe uma carta como parmetro, remove-
2 de Paus a do baralho e retorna verdadeiro (1), se a carta estava no
3 de Paus baralho e falso (0), caso contrrio:
4 de Paus
5 de Paus class Baralho:
6 de Paus ...
7 de Paus def removerCarta(self, carta):
8 de Paus if carta in self.cartas:
9 de Paus self.cartas.remove(carta)
10 de Paus return 1
Valete de Paus else
Rainha de Paus return 0
Rei de Paus O operador in retorna verdadeiro se o primeiro
s de Ouros
operando estiver contido no segundo, que deve ser uma lista
ou uma tupla. Se o primeiro operando for um objeto, Python
E assim por diante. Mesmo que o resultado usa o mtodo __cmp__ do objeto para determinar igualdade
aparea em 52 linhas, uma string longa que contm com os itens da lista. Como o mtodo __cmp__ da classe
newlines. Carta verifica por igualdade profunda, o mtodo removerCarta
tambm testa por igualdade profunda.
Para distribuir as cartas, ns iremos remover e
15.7 Embaralhando devolver a carta do topo. O mtodo de lista pop fornece uma
maneira conveniente de fazer isso:
Se um baralho estiver perfeitamente embaralhado, ento cada
carta tem a mesma probabilidade de aparecer em qualquer class Baralho:
lugar no baralho, e qualquer localizao no baralho tem a ...
mesma probabilidade de conter qualquer carta. def distribuirCarta(self):
return self.cards.pop()
Para embaralhar as cartas, ns usaremos a
funo randrange do mdulo random. Com dois argumentos Na verdade, pop remove a ltima carta da lista.
inteiros, a e b, randrange escolhe um inteiro aleatrio no Portanto, ns estamos realmente distribuindo as cartas do fim
intervalo a <= x < b. Como o limite superior estritamente para o incio do baralho.
menor que b, ns podemos usar o comprimento de uma lista Uma ltima operao que ns poderamos
como o segundo parmetro, e ns garantimos que o ndice querer a funo booleana estahVazio, que retorna verdadeiro
sempre ser vlido. Por exemplo, esta expresso escolhe o se o baralho no contm cartas:
ndice de uma carta aleatria em um baralho:
class Baralho:
random.randrange(0, len(self.cartas))
...
Uma maneira fcil de embaralhar as cartas
percorrer a lista e trocar cada carta por outra escolhida def estahVazio(self):
aleatoriamente. possvel que a carta seja trocada por ela return (len(self.cartas) == 0)
mesma, mas isso no problema. Na verdade, se ns
exclussemos essa possibilidade, a ordem das cartas no seria

Captulo 15: Conjuntos de objetos #74


Como pensar como um cientista da Computao usando Python

15.9 Glossrio

codificar Representar um conjunto de valores


(encode) usando outro conjunto de valores,
construindo um mapeamento entre eles.
atributo de Uma varivel que definida dentro de uma
classe (class definio de classe, mas fora de qualquer
atribute) mtodo. Atributos de classe podem ser
acessados a partir de qualquer mtodo da
classe e so compartilhados por todas as
instncias da classe.
acumulador Uma varivel usada em um lao para
(accumulator) 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 #75


Como pensar como um cientista da Computao usando Python

Capitulo 16: Herana

Esse comando indica que a nova classe Mao


16.1 Herana herda da classe existente Baralho.
Uma das caractersticas mais marcantes das linguagens O construtor de Mao inicializa os atributos da
orientadas a objetos a herana. Herana a habilidade de mo, que so nome e cartas. A string nome identifica essa
definir uma nova classe que uma verso modificada de uma mo, provavelmente pelo nome do jogador que est segurando
classe existente. as cartas. O nome um parmetro opcional com a string vazia
como valor default. cartas a lista de cartas da mo,
A principal vantagem dessa caracterstica que inicializada com uma lista vazia
voc pode adicionar novos mtodos a uma classe sem ter que
modificar a classe existente. Chama-se "herana" porque a class Mao(Baralho):
nova classe herda todos os mtodos da classe existente. def __init__(self, nome=""):
Ampliando a metfora, podemos dizer que a classe existente self.cartas = []
s vezes chamada de classe me (parent). A nova classe pode self.nome = nome
ser chamada de classe filha ou, simplesmente, "subclasse". Em praticamente todos os jogos de cartas,
A herana uma caracterstica poderosa. necessario adicionar e remover cartas do baralho. Remover
Alguns programas que seriam complicados sem herana cartas j est resolvido, uma vez que Mao herda removerCarta
podem ser escritos de forma simples e concisa graas a ela. E de Baralho. Mas precisamos escrever adicionarCarta:
a herana tambm pode facilitar o reuso do cdigo, uma vez
que voc pode adaptar o comportamento de classes existentes class Mao(Baralho):
sem ter que modific-las. Em alguns casos, a estrutura da #...
herana reflete a natureza real do problema, tornando o def adicionarCarta(self,carta):
programa mais fcil de entender. self.cartas.append(carta)
Por outro lado, a herana pode tornar um De novo, a elipse indica que omitimos outros
programa seja difcil de ler. Quando um mtodo invocado, mtodos. O mtodo de listas append adiciona a nova carta no
s vezes no est claro onde procurar sua definio. A parte final da lista de cartas.
relevante do cdigo pode ser espalhada em vrios mdulos. E,
tambm, muitas das coisas que podem ser feitas utilizando
herana tambm podem ser feitas de forma igualmente 16.3 Dando as cartas
elegante (ou at mais) sem ela. Se a estrutura natural do
problema no se presta a utilizar herana, esse estilo de
programao pode trazer mais problemas que vantagens. Agora que temos uma classe Mao, queremos distribuir cartas
de Baralho para mos de cartas. No imediatamente bvio se
Nesse captulo, vamos demonstrar o uso de esse mtodo deve ir na classe Mao ou na classe Baralho, mas
herana como parte de um programa que joga uma variante de como ele opera num nico baralho e (possivelmente) em
Mico. Um dos nossos objetivos escrever um cdigo que vrias mos de cartas, mais natural coloc-lo em Baralho.
possa ser reutilizado para implementar outros jogos de cartas.
O mtodo distribuir deve ser bem geral, j que
diferentes jogos tero diferentes requerimentos. Podemos
querer distribuir o baralho inteiro de uma vez s ou adicionar
16.2 Uma mo de cartas uma carta a cada mo.
distribuir recebe dois argumentos, uma lista (ou
Para quase todos os jogos de baralho, preciso representar tupla) de mos e o numero total de cartas a serem dadas. Se
uma mo de cartas. Uma mo de cartas similar a um mao no houver cartas suficientes no baralho, o mtodo d todas as
de baralho. Porque ambos so formados por uma srie de cartas e pra:
cartas e ambos requerem operaes, como, adicionar e
remover cartas. Fora isso, a habilidade de embaralhar a mo e class Baralho:
o baralho tambm so teis. #...
Mas, ao mesmo tempo, a mo tambm def distribuir(self, maos, nCartas=999):
diferente do baralho. Dependendo do jogo que est sendo nMaos = len(maos)
jogado, precisamos realizar algumas operaes nas mos de for i in range(nCartas):
cartas que no fazem sentido para o baralho inteiro. Por if self.estahVazia(): break
exemplo, no pquer, podemos classificar uma mo (trinca,
flush, etc.) ou compar-la com outra mo. No jogo de bridge, # interromper se acabaram as cartas
podemos querer computar a quantidade de pontos que h carta = self.pegarCarta()
numa mo, a fim de fazer um lance. # pegar a carta do topo
mao = maos[i % nMaos]
Essa situao sugere o uso de herana. Se Mao
uma subclasse de Baralho, ter todos os mtodos de Baralho, e # quem deve receber agora?
novos mtodos podem ser adicionados. mao.adicionarCarta(carta)
# adicionar a carta mao
Na definio de classe, o nome da classe pai O segundo parmetro, nCartas, opcional; o
aparece entre parnteses: default um nmero grande, o que na prtica significa que
class Mao(Baralho): todas as cartas do baralho sero dadas se este parmetro for
pass
omitido.

Capitulo 16: Herana #76


Como pensar como um cientista da Computao usando Python

A varivel do lao i vai de 0 a nCartas-1. A cada def __init__(self):


volta do lao, uma carta removida do baralho, usando o self.baralho = Baralho()
mtodo de lista pop, que remove e retorna o ltimo item na self.baralho.embaralhar()
lista.
Este o primeiro dos casos que vimos at agora
O operador mdulo (%) permite dar cartas em em que o mtodo de inicializao realiza uma computao
ao redor da mesa (uma carta de cada vez para cada mo). significativa, para alm de inicializar atributos.
Quando i igual ao numero de mos na lista, a expresso i %
nMaos volta para o comeo da lista (ndice 0). Para implementar jogos especficos, podemos
herdar de JogoDeCartas e adicionar caracteristicas para o
novo jogo. Como exemplo, vamos escrever uma simulao de
Mico.
16.4 Exibindo a mao
O objetivo do jogo livrar-se das cartas que
estiverem na mo. Para fazer isso, preciso combinar cartas
Para exibir o contedo de uma mo, podemos tirar vantagem formando pares ou casais que tenham a mesma cor e o mesmo
dos mtodos exibirBaralho e __str__ herdados de Baralho. Por nmero ou figura. Por exemplo, o 4 de paus casa com o 4 de
exemplo: espadas porque os dois naipes so pretos. O Valete de copas
>>> baralho = Baralho()
combina com o Valete de ouros porque ambos so vermelhos.
>>> baralho.embaralhar() Antes de mais nada, a Dama de paus removida
>>> mao = Mao("fabio") do baralho, para que a Dama de espadas fique sem par. A
>>> baralho.distribuir([mao], 5) Dama de espadas ento faz o papel do mico. As 51 cartas que
>>> print mao
sobram so distribuidas aos jogadores em ao redor da mesa
(uma carta de cada vez para cada mo). Depois que as cartas
Mo fabio contm foram dadas, os jogadores devem fazer todos os casais
2 de espadas possveis que tiverem na mo, e em seguida descart-los na
3 de espadas mesa.
4 de espadas Quando ningum mais tiver nenhum par para
s de copas descartar, o jogo comea. Na sua vez de jogar, o jogador pega
9 de paus uma carta (sem olhar) do vizinho mais proximo esquerda,
Nao l uma grande mo, mas tem potencial que ainda tiver cartas. Se a carta escolhida casar com uma
para um straight flush. carta que ele tem na mo, ele descarta esse par. Quando todos
os casais possveis tiverem sido feitos, o jogador que tiver
Embora seja conveniente herdar os mtodos sobrado com a Dama de espadas na mo perde o jogo.
existentes, h outras informacoes num objeto Mao que
podemos querer incluir quando ao exib-lo. Para fazer isso, Em nossa simulao computacional do jogo, o
podemos fornecer um mtodo __str__ para a classe Mao que computador joga todas as mos. Infelizmente, algumas
sobrescreva o da classe Baralho: nuances do jogo presencial se perdem. Num jogo presencial, o
jogador que est com o mico na mo pode usar uns truques
class Mao(Baralho) para induzir o vizinho a pegar a carta, por exemplo,
#... segurando-a mais alto que as outras, ou mais baixo, ou se
def __str__(self): esforando para que ela no fique em destaque. J o
computador simplesmente pega a carta do vizinho
s = "Mao " + self.nome aleatoriamente...
if self.estahVazia():
return s + " est vazia\n"
else:
return s + " contm\n" + Baralho.__str__(self)
16.6 Classe MaoDeMico
Inicialmente, s uma string que identifica a
mo. Se a mo estiver vazia, o programa acrescenta as Uma mo para jogar Mico requer algumas habilidades para
palavras est vazia e retorna o resultado. alem das habilidades gerais de uma Mao. Vamos definir uma
nova classe, MaoDeMico, que herda de Mao e prov um
Se no, o programa acrescenta a palavra contm mtodo adicional chamado descartarCasais:
e a representao de string do Baralho, computada pela
invocao do mtodo __str__ na classe Baralho em self. class MaoDeMico(Mao):
def descartarCasais(self):
Pode parecer estranho enviar self, que se refere conta = 0
Mao corrente, para um mtodo Baralho, mas isso s at voce cartasIniciais = self.cartas[:]
se lembrar que um Mao um tipo de Baralho. Objetos Mao
podem fazer tudo que os objetos Baralho fazem, entao, for carta in cartasIniciais:
permitido passar uma instncia de Mao para um mtodo casal = Carta(3 - carta.naipe, carta.valor)
Baralho. if casal in self.cartas:
self.cartas.remove(carta)
Em geral, sempre permitido usar uma
instncia de uma subclasse no lugar de uma instncia de uma self.cartas.remove(casal)
classe me. print "Mao %s: %s casais %s" %
(self.nome,carta,casal)
conta = conta + 1
return conta
16.5 A classe JogoDeCartas
Comeamos fazendo uma cpia da lista de
cartas, para poder percorrer a cpia enquanto removemos
A classe JogoDeCartas toma conta de algumas tarefas bsicas cartas do original. Uma vez que self.cartas modificada no
comuns a todos os jogos, como, criar o baralho e embaralh- lao, no queremos us-la para controlar o percurso. Python
lo: pode ficar bem confuso se estiver percorrendo uma lista que
class JogoDeCartas:
est mudando!

Capitulo 16: Herana #77


Como pensar como um cientista da Computao usando Python

Para cada carta na mo, verificamos qual a # distribuir as cartas


carta que faz par com ela e vamos procur-la. O par da carta self.baralho.distribuir(self.maos)
tem o mesmo valor (nmero ou figura) e naipe da mesma cor. print "---------- As cartas foram dadas"
A expresso 3 - carta.naipe transforma um paus (naipe 0)
numa espadas (naipe 3) e um ouros (naipe 1) numa copas self.exibirMaos()
(naipe 2). Voc deve analisar a frmula at se convencer de
que as operaes opostas tambm funcionam. Se o par da # remover casais iniciais
carta tambem estiver na mo, ambas as cartas so removidas. casais = self.removerTodosOsCasais()
O exemplo a seguir demonstra como usar print "---------- Os pares foram descartados, o
descartarCasais: jogo comea"
self.exibirMaos()
>>> jogo = JogoDeCartas()
>>> mao = MaoDeMico("fabio") # jogar at que 25 casais se formem
>>> jogo.baralho.distribuir([mao], 13) vez = 0
>>> print mao numMaos = len(self.maos)
mo fabio contm while casais < 25:
s de espadas casais = casais + self.jogarVez(vez)
2 de ouros vez = (vez + 1) % numMaos
7 de espadas
8 de paus print "---------- Fim do jogo"
6 de copas self.exibirMaos()
8 de espadas Algumas etapas do jogo foram separadas em
7 de paus mtodos. removerTodosOsCasais percorre a lista de mos e
Rainha de paus invoca descartarCasais em cada uma:
7 de ouros
class Mico(JogoDeCartas):
5 de paus
#...
Valete de ouros
def removerTodosOsCasais(self):
10 de ouros
conta = 0
10 de copas
for mao in self.maos:
conta = conta + mao.descartarCasais()
>>> mao.descartarCasais()
return conta
Mo fabio: 7 de espadas faz par com 7 de paus
Mo fabio: 8 de espadas faz par com 8 de paus
Como exerccio, escreva ``exibirMaos`` que
percorre ``self.maos`` e exibe cada mo.
Mo fabio: 10 de ouros faz par com 10 de copas
>>> print mao conta uma acumulador que soma o nmero de
Mo fabio contm pares em cada mo e retorna o total.
s de espadas Quando o nmero total de pares alcana 25, 50
2 de ouros cartas foram removidas das mos, o que significa que sobrou
6 de copas s uma carta e o jogo chegou ao fim.
Rainha de paus A varivel vez mantm controle sobre de quem
7 de ouros a vez de jogar. Comea em 0 e incrementa de um em um;
5 de paus quando atinge numMaos, o operador mdulo faz ela retornar
Valete de ouros para 0.
Observe que no existe um mtodo __init__ O mtodo jogarVez recebe um argumento que
para a classe MaoDeMico. Ele herdado de Mao. indica de quem a vez de jogar. O valor de retorno o
nmero de pares feitos durante essa rodada:
class Mico(JogoDeCartas):
16.7 Classe Mico #...
def jogarVez(self, i):
Agora podemos focar nossa ateno no jogo em si. Mico if self.maos[i].estahVazia():
uma subclasse de JogoDeCartas com um novo mtodo
chamado jogar que recebe uma lista de jogadores como return 0
argumento. vizinho = self.buscarVizinho(i)
novaCarta = self.maos[vizinho].pegarCarta()
J que __init__ herdado de JogoDeCartas, um self.maos[i].adicionarCarta(novaCarta)
novo objeto Mico contm um novo baralho embaralhado:
print "Mao", self.maos[i].nome, "pegou",
class Mico(JogoDeCartas): novaCarta
def jogar(self, nomes): conta = self.maos[i].descartarCasais()
# remover a Dama de paus self.maos[i].embaralhar()
self.baralho.removerCarta(Carta(0,12)) return conta
Se a mo de um jogador estiver vazia, ele est
# fazer uma mo para cada jogador fora do jogo, ento, ele no faz nada e retorna 0.
self.maos = [] Do contrrio, uma jogada consiste em achar o
for nome in nomes : primeiro jogador esquerda que tenha cartas, pegar uma carta
self.maos.append(MaoDeMico(nome)) dele, e tentar fazer pares. Antes de retornar, as cartas na mo
so embaralhadas, para que a escolha do prximo jogador seja
aleatria.

Capitulo 16: Herana #78


Como pensar como um cientista da Computao usando Python

O mtodo buscarVizinho comea com o jogador Rei de espadas


imediatamente esquerda e continua ao redor da mesa at 10 de ouros
encontrar um jogador que ainda tenha cartas:
class Mico(JogoDeCartas): Mo Jair contm
#... Valete de espadas
def buscarVizinho(self, i): Valete de copas
numMaos = len(self.maos) Rei de ouros
for next in range(1,numMaos):
vizinho = (i + next) % numMaos Mo Clara contm
if not self.maos[vizinho].estahVazia(): Valete de ouros
return vizinho Rei de paus
Se buscarVizinho alguma vez circulasse pela 10 de copas
mesa sem encontrar cartas, retornaria None e causaria um erro
em outra parte do programa. Felizmente, podemos provar que Mo Alice pegou o Rei de ouros
isso nunca vai acontecer (desde que o fim do jogo seja Mo Alice: Rei de copas faz par com Rei de ouros
detectado corretamente). Mo Jair pegou 10 de copas
No mencionamos o mtodo exibirBaralhos. Mo Clara pegou Valete de paus
Esse voc mesmo pode escrever. Mo Alice pegou Valete de copas
A sada a seguir produto de uma forma Mo Jair pegou Valete de ouros
reduzida do jogo, onde apenas as 15 cartas mais altas do Mo Clara pegou Dama de espadas
baralho (do 10 para cima) foram dadas, para trs jogadores. Mo Alice pegou Valete de ouros
Com esse baralho reduzido, a jogada pra depois que 7 Mo Alice: Valete de copas faz par com Valete de
combinaes foram feitas, ao invs de 25: ouros
Mo Jair pegou Rei de paus
>>> import cartas
Mo Clara pegou Rei de espadas
>>> jogo = cartas.Mico()
Mo Alice pegou 10 de copas
>>> jogo.jogar(["Alice","Jair","Clara"])
Mo Alice: 10 de ouros faz par com 10 de copas
---------- As cartas foram dadas
Mo Jair pegou Dama de espadas
Mo Alice contm
Mo Clara pegou Valete de espadas
Rei de copas
Mo Clara: Valete de paus faz par com Valete de
Valete de paus
espadas
Rainha de espadas
Mo Jair pegou Rei de espadas
Rei de espadas
Mo Jeff: Rei de paus faz par com Rei de espadas
10 de ouros
---------- Fim do jogo
Mo Alice est vazia
Mo Jair contm
Rainha de copas
Mo Jair contm
Valete de espadas
Rainha de espadas
Valete de copas
Rei de ouros
Mo Clara est vazia
Rainha de ouros
Ento, o Jair perdeu.
Mo Clara contm
Valete of ouros
Rei de paus
10 de espadas 16.8 Glossrio
10 de copas
10 de paus herana (inheritance) Habilidade de definir uma nova
classe que a verso modificada de
Mo Jair: Dama de copas faz par com Dama de ouros uma classe definida anteriormente.
Mo Clara: 10 de espadas faz par com 10 de paus classe me (parent A classe de quem a classe filha
---------- Os pares foram descartados, o jogo comea class) herda.
Mo Alice contm
classe filho (child Um nova classe criada herdando de
Rei de copas class) uma classe existente; tambm
Valete de paus chamada de "subclasse".
Rainha de espadas

Capitulo 16: Herana #79


Como pensar como um cientista da Computao usando Python

Captulo 17: Listas encadeadas

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 Para ligar os ns, temos que fazer o primeiro n
lista. Alm disto, cada n contm uma unidade de dados da lista referir ao segundo e o segundo n referir ao terceiro:
chamada a carga.
>>> no1.proximo = no2
Uma lista ligada considerada uma estrutura >>> no2.proximo = no3
de dados recorrente porque ela tem uma definio
recorrente. A referncia do terceiro n None, que indica
que ele o final da lista. Agora o diagrama de estado se
Uma lista ligada : parece com:
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.
Agora voc sabe como criar ns e lig-los em
uma lista. O que pode estar menos claro neste ponto por qu.
17.2 A classe No (Node)
Como usual quando se escreve uma nova classe, ns 17.3 Listas como Colees
comearemos com os mtodos de inicializao e __str__ de
modo que podemos testar o mecanismo bsico de se criar e
mostrar o novo tipo: Listas so teis porque elas provm um modo de montar
mltiplos objetos em uma nica entidade, algumas vezes
class No: chamada uma coleo. No exemplo, o primeiro n da lista
def __init__(self, carga=None, proximo=None): serve como uma referncia para toda a lista.
self.carga = carga Para passar uma lista como um parmetro, voc
self.proximo = proximo apenas tem que passar uma referncia ao primeiro n. Por
exemplo, a funo imprimeLista toma um nico n como um
def __str__(self): argumento. Iniciando com o cabea da lista, ela imprime cada
return str(self.carga) n at que chegue ao fim:
Como de costume, os parmetros para o mtodo def imprimeLista(no):
de inicializao so opcionais. Por omisso (default), ambos, a while no:
carga e a ligao, proximo, so definidas como None. print no,
A representao string de um n simplesmente no = no.proximo
a representao string da carga. Como qualquer valor pode ser print
passado para a funo str, ns podemos armazenar qualquer Para chamar este mtodo, ns passamos uma
valor em uma lista. referncia ao primeiro no:
Para testar a implementao at agora, ns >>> imprimeLista(no1)
criamos um No e o imprimimos:
1 2 3
>>> no = No("teste") Dentro de imprimeLista ns temos uma
>>> print no referncia para o primeiro n da lista, mas no h variveis
teste que refiram aos outros ns. Ns temos que usar o valor
Para ficar interessante, ns precisamos uma lista proximo de cada n para alcanar o prximo n.
com mais do que um n: Para percorrer uma lista ligada, comum usar
uma varivel lao como no para referir a cada um dos ns
>>> no1 = No(1) sucessivamente.
>>> no2 = No(2)
>>> no3 = No(3) Este diagrama mostra o valor de lista e os
Este cdigo cria trs ns, mas ns ainda no valores que no assume:
temos uma lista ainda porque os ns no esto ligados. O
diagrama de estado parecido com este:

Captulo 17: Listas encadeadas #80


Como pensar como um cientista da Computao usando Python

figura mostra uma lista com dois ns, um dos quais refere-se a
si mesmo:

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 Se ns invocarmos imprimeLista nesta lista, ele


ficar em lao para sempre. Se ns invocarmos
natural expressar muitas operaes de listas utilizando imprimeDeTrasParaFrente, ele recorrer infinitamente. Este
mtodos recorrentes. Por exemplo, o seguinte um algoritmo tipo de comportamento torna as listas infinitas difceis de se
recorrente para imprimir uma lista de trs para frente. lidar.
1. Separe a lista em dois pedaos: o primeiro n A despeito disto, elas ocasionalmente so teis.
(chamado a cabea); e o resto (chamado o rabo). Por exemplo, podemos representar um nmero como uma lista
de dgitos e usar uma lista infinita para representar uma frao
2. Imprima o rabo de trs para frente. repetente.
3. Imprima a cabea. Mesmo assim, problemtico que no
possamos provar que imprimeLista e
Logicamente, o Passo 2, a chamada recorrente, imprimeDeTrasParaFrente terminem. O melhor que podemos
assume que ns temos um modo de imprimir a lista de trs fazer a afirmao hipottica, "Se a lista no contm laos,
para frente. Mas se ns assumimos que a chamada recorrente ento este mtodo terminar." Este tipo de hiptese chamado
funciona -- o passo de f -- ento podemos nos convencer de uma pr-condio. Ele impe uma limitao sobre um dos
que o algoritmo funciona. parmetros e descreve o comportamento do mtodo se a
Tudo o que precisamos so um caso base e um limitao satisfeita. Voc ver mais exemplos em breve.
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: 17.6 O Teorema da Ambigidade Fundamental
def imprimeDeTrasParaFrente(lista):
if lista == None : return Uma parte de imprimeDeTrasParaFrente pode ter gerado
cabeca = lista
surpresa:
rabo = lista.proximo cabeca = lista
imprimeDeTrasParaFrente(rabo) rabo = lista.proximo
print cabeca, Aps a primeira atribuio, cabeca e lista tm o
A primeira linha trata o caso base fazendo nada. mesmo tipo e o mesmo valor. Ento por que ns criamos uma
As prximas duas linhas dividem a lista em cabeca e rabo. As nova varivel?
duas ltimas linhas imprimem a lista. A vrgula no final da
ltima linha impede o Python de imprimir uma nova linha A razo que as duas variveis tm diferentes
aps cada n. papis. Quando pensamos em cabeca, pensamos como uma
referncia a um nico n, e quando pensamos em lista o
Ns invocamos este mtodo como invocamos o fazemos como uma referncia ao primeiro n da lista. Estes
imprimeLista: "papis" no so parte do programa; eles esto na mente do
programador.
>>> imprimeDeTrasParaFrente(no1)
3 2 1 Em geral no podemos dizer olhando para o
programa qual o papel que uma varivel tem. Esta
O resultado a lista de trs para frente. ambigidade pode ser til, mas tambm pode tornar os
Voc pode se perguntar por qu imprimeLista e programas difceis de serem lidos. Usamos freqentemente
imprimeDeTrasParaFrente so funes e no mtodos da nomes de variveis como no e lista para documentar como
classe No. A razo que ns queremos usar None para pretendemos usar uma varivel e algumas vezes criamos
representa a lista vazia e no legal invocar um mtodo sobre variveis adicionais para remover a ambigidade.
None. Esta limitao torna complicado escrever cdigo de Poderamos ter escrito
manipulao de lista em estilo orientado a objeto limpo. imprimeDeTrasParaFrente sem cabeca e rabo, que a tornaria
Podemos provar que imprimeDeTrasParaFrente mais concisa mas possivelmente menos clara:
sempre termina? Em outras palavras, ir ela sempre atingir o def imprimeDeTrasParaFrente(lista):
caso base? De fato, a resposta no. Algumas listas faro este
mtodo falhar. if lista == None : return
imprimeDeTrasParaFrente(lista.proximo)
print lista,
17.5 Listas Infinitas Olhando para as duas chamadas de funo,
temos que lembrar que imprimeDeTrasParaFrente trata seu
argumento como uma coleo e print trata seu argumento
No h nada que impea um n de referenciar de volta um n como um objeto nico.
anterior na lista, incluindo ele mesmo. Por exemplo, esta

Captulo 17: Listas encadeadas #81


Como pensar como um cientista da Computao usando Python

O teorema da ambigidade fundamental cabeca = lista


descreve a ambigidade que inerente referncia a um n: rabo = lista.proximo
Uma varivel que refere a um n pode tratar o imprimeDeTrasParaFrente(rabo)
n como um objeto nico ou como o primeiro em uma lista print cabeca,
de ns. print "]",
Novamente, uma boa idia verificar mtodos
como este para ver se eles funcionam com casos especiais
17.7 Modificando Listas como uma lista vazia ou um singleton.
Quando usamos este mtodo em algum lugar no
Existem duas maneiras de se modificar uma lista ligada. programa, invocamos imprimeDeTrasParaFrenteLegal
Obviamente, podemos modificar a carga dos ns, mas as diretamente, e ele invoca imprimeDeTrasParaFrente por ns.
operaes mais interessantes so aquelas que adicionam, Neste sentido, imprimeDeTrasParaFrenteLegal atua como um
removem ou reordenam os ns. envoltrio, e usa imprimeDeTrasParaFrente como um
ajudador.
Como um exemplo, vamos escrever um mtodo
que remove o segundo n na lista e retorna uma referncia ao
n removido:
17.9 A Classe ListaLigada
def removeSegundo(lista):
if lista == None : return Existem alguns problemas sutis com o modo que
primeiro = lista implementamos listas. Em um inverso de causa e efeito,
segundo = lista.proximo proporemos uma implementao alternativa primeiro e ento
# faz o primeiro no referir ao terceiro explicaremos qual problema ela resolve.
primeiro.proximo = segundo.proximo Primeiro, criaremos uma nova classe chamada
# separa o segundo no do resto da lista ListaLigada. Seus atributos so um inteiro que contm o
segundo.proximo = None comprimento da lista e uma referncia para o primeiro n.
return segundo Objetos do tipo ListaLigada servem como cabos (handles)
Novamente, estamos usando variveis para se manipular listas de objetos No:
temporrias para tornar o cdigo mais fcil de ser lido. Aqui class ListaLigada:
est como usar este mtodo: def __init__(self):
>>> imprimeLista(no1) self.comprimento = 0
1 2 3 self.cabeca = None
>>> removido = removeSegundo(no1) Uma coisa legal acerca da classe ListaLigada
>>> imprimeLista(removido) que ela prov um lugar natural para se colocar funes
2 envoltrias como imprimeDeTrasParaFrenteLegal, que
podemos transformar em um mtodo da classe ListaLigada:
>>> imprimeLista(no1)
1 3 class ListaLigada:
Este diagrama de estado mostra o efeito da ...
operao: def imprimeDeTrasParaFrente(self):
print "[",
if self.cabeca != None :
self.cabeca.imprimeDeTrasParaFrente()
print "]",

class No:
...
O que acontece se voc invocar este mtodo e def imprimeDeTrasParaFrente(self):
passar uma lista com somente um elemento (um singleton)? O if self.proximo != None:
que acontece se voc passar a lista vazia como um argumento? rabo = self.proximo
Existe uma pr-condio para este mtodo? Se houver, corrija
o mtodo para tratar uma violao da pr-condio de modo rabo.imprimeDeTrasParaFrente()
razovel. print self.carga,
Apenas para tornar as coisas confusas,
mudamos o nome de imprimeDeTrasParaFrenteLegal. Agora
existem dois mtodos chamados imprimeDeTrasParaFrente:
17.8 Envoltrios e Ajudadores um na classe No (o ajudador); e um na classe ListaLigada``(o
envoltrio). Quano o envoltrio invoca
Freqentemente til dividir uma operao de lista em dois ``self.cabeca.imprimeDeTrasParaFrente, ele est invocando o
mtodos. Por exemplo, para imprimir uma lista de trs para ajudador, porque self.cabeca um objeto No.
frente no formato convencional de lista [3, 2, 1], podemos
usar o mtodo imprimeDeTrasParaFrente para imprimir 3, 2, Outro benefcio da classe ListaLigada que ela
mas queremos um metodo separado para imprimir os torna mais fcil adicionar e remover o primeiro elemento de
braquetes e o primeiro n. Vamos cham-lo de uma lista. Por exemplo, adicionaPrimeiro um mtodo para
imprimeDeTrasParaFrenteLegal: ListaLigada; ele toma um item de carga como argumento e o
coloca no incio da lista:
def imprimeDeTrasParaFrenteLegal(lista):
class ListaLigada:
print "[",
...
if lista != None :

Captulo 17: Listas encadeadas #82


Como pensar como um cientista da Computao usando Python

def adicionaPrimeiro(self, carga): (embedded armazenada/associada em/a um


no = No(carga) reference) atributo de um objeto.
no.proximo = self.cabeca
lista ligada (linked Uma estrutura de dados que
self.cabeca = no list) implementa uma coleo usando
self.comprimento = self.comprimento + 1 uma sequncia de ns ligados.
Como de costume, voc deve conferir cdigos
como este para ver se eles tratam os casos especiais. Por n ou nodo (node) Um elemento de uma lista,
exemplo, o que acontece se a lista est inicialmente vazia? usualmente implementado como um
objeto que contm uma referncia
para outro objeto do mesmo tipo.
17.10 Invariantes carga (cargo) Um item de dado contido em um n.
ligao (link) Uma referncia embutida usada para
Algumas listas so "bem formadas"; outras no o so. Por ligar/conectar um objeto a outro.
exemplo, se uma lista contm um lao, ela far muitos de
nossos mtodos falharem, de modo que podemos querer pr-condio Uma assero que precisa/deve ser
requerer que listas no contenham laos. Outro requerimento (precondition) verdadeira para que um mtodo
que o valor de comprimento no objeto ListaLigada seja igual trabalhe corretamante.
ao nmero real de ns da lista. teorema da Uma referncia para um n de uma
Requerimentos como estes so chamados de ambigidade lista pode ser tratada como um
invariantes porque, idealmente, eles deveriam ser verdade para fundamental objeto nico ou como o primeiro em
cada objeto o tempo todo. Especificar invariantes para objetos (fundamental uma lista de ns.
um prtica de programao til porque torna mais fcil ambiguity theorem)
provar a correo do cdigo, verificar a integridade das singleton (singleton) Uma lista ligada com somente um
estruturas de dados e detectar erros. n.
Uma coisa que algumas vezes confusa acerca envoltrio (wrapper) Um mtodo que atua como um
de invariantes que existem momentos em que eles so intermedirio (middleman) entre um
violados. Por exemplo, no meio de adicionaPrimeiro, aps chamador e um mtodo ajudador
termos adicionado o n mas antes de termos incrementado (helper), freqentemente tornando a
comprimento, o invariante violado. Este tipo de violao invocao do mtodo mais fcil ou
aceitvel; de fato, freqentemente impossvel modificar um menos propensa a erros.
objeto sem violar um invariante por, no mnimo, um pequeno
instante. Normalmente, requeremos que cada mtodo que ajudador (helper) Um mtodo que no invocado
viola um invariante deve restaurar este invariante. diretamente pelo chamador (caller)
mas usado por outro mtodo para
Se h qualquer aumento significativo de cdigo realizar parte de uma operao.
no qual o invariante violado, importante tornar isto claro
nos comentrios, de modo que nenhuma operao seja feita invariante Uma assero que deveria ser
que dependa daquele invariante. (invariant) verdadeira sempre para um objeto
(exceto talvez enquanto o objeto
estiver sendo modificado).
17.11 Glossrio

referncia embutida Uma referncia

Captulo 17: Listas encadeadas #83


Como pensar como um cientista da Computao usando Python

Captulo 18: Pilhas

18.1 Tipos abstratos de dados 18.3 Implementando pilhas com listas de Python
Os tipos de dados que voc viu at agora so todos concretos, As operaes de lista que Python oferecem so similares s
no sentido que ns especificamos completamente como eles operaes que definem uma pilha. A interface no
so implementados. Por exemplo, a classe Card(XXX ver exatamente o que se supe ser, mas podemos escrever um
como foi traduzido) representa uma carta utilizando dois cdigo para traduzir do TAD Pilha para as operaes nativas.
inteiros. Como discutimos no momento, esta no a nica
maneira de representar uma carta; existem muitas Este cdigo chamado uma implementao do
implementaes alternativas. TAD Pilha. Geralmente, uma implementaa um conjunto
de mtodos que satisfazem os requisitos sintticos e
Um tipo abstrato de dado, ou TAD, especifica semnticos de uma interface.
um conjunto de operaes (ou mtodos) e a semntica das
operaes (o que elas fazem), mas no especifica a Aqui est uma implementao do TAD Pilha
implementao das operaes. Isto o que o faz abstrato. que usa uma lista do Python:
Por que isto til? class Stack :
def __init__(self) :
Simplifica a tarefa dde especificar um algoritmo se self.items = []
voc pode XXXdenotar(denote) as operaes que
voc precisa sem ter que pensar, ao mesmo tempo,
como as operaes so executadas. def push(self, item) :
self.items.apend(item)
Uma vez que existem geralmente muitas maneiras de
implementar um TAD, pode ser til escrever um
algritmo que pode ser usado com qualquer das def pop(self) :
possveis implementaes. return self.items.pop()

TADs bastante conhecidos, como o TAD Pilha deste def isEmpty(self) :


captulo, j esto implementados em bibliotecas
padro, ento eles podem ser escritos uma vez e return (self.items == [])
usado por muitos programadores. Um objeto Stack contm um atributo chamado
items que uma lista de tens na pilha. O mtodo de
As operaes em TADs provm uma linguagem de inicializao define items como uma lista vazia.
alto nvel comum para especificar e falar sobre
algoritmos. Para adicionar um novo tem na pilha, push o
coloca em items. Para remover um tem da pilha, pop usa o
Quando falamos sobre TADs, geralmente mtodo de lista homnimo para remover e retornar um ltimo
distinguimos o cdigo que usa o TAD, chamado cliente, do tem da lista.
cdigo que implementa o TAD, chamado cdigo fornecedor.
Finalmente, para verificar se a pilha est vazia,
isEmpty comprara items a uma lista vazia.
18.2 O TAD Pilha Uma implementao como esta, na qual os
mtodos consistem de simples invocaes de mtodos
Neste captulo, iremos olhar um TAD comum, a pilha. Uma existentes, chamado revestimento. Na vida real,
pilha uma coleo, ou seja, uma estrutura de dados que revestimento uma fina camada de madeira de boa qualidade
contei mltiplos elementos. Outras colees que vimos usado em XXX*furniture-making* para esconder madeira de
incluem dicionrios e listas. menor qualidade embaixo. Cientistas da Computao usam
esta metfora para descrever um pequeno trecho de cdigo
Um TAd definido pelo conjunto de operaes que esconde os detalhes de uma implementao e fornece uma
que podem ser executadas nele, que chamado interface. A interface mais simples, ou mais padronizada.
interface para uma pilha consiste nestas operaes:
__init__ : Inicializa uma nova pilha vazia.
18.4 Empilhando e desempilhando
push : Adiciona um novo item na pilha
pop : Remove um tem da pilha e o retorna, O Uma pilha uma estrutura de dados genrica, o que
tem que retornadao sempre o ltimo adicionado. significa que podemos adicionar qualquer tipo de tem a ela. O
exemplo a seguir empilha dois inteiros e uma XXXstring na
isEmpty : Verifica se a pilha est vazia. pilha:
Uma s vezes chamada uma estrutura de >>> s = Stack()
dados "last in, first out" ou LIFO, porque o ltimo tem >>> s.push(54)
adicionad o primeiro a ser removido. >>> s.push(45)
>>> s.push("+")
Podemos usar isEmpty e pop para remover e
imprimir todos os tens da pilha:

Captulo 18: Pilhas #84


Como pensar como um cientista da Computao usando Python

while not s.isEmpty() : A funo re.split mais poderosa, permitindo-


priint s.pop() nos fornecer uma expreso regular ao invs de um
A sada + 45 54. Em outras palavras, usamos a delimitador. Uma expresso regular uma maneira de
pilha para imprimir os tens ao contrrio! Sabidamente, este especificar um conjunto de strings. Por exemplo, [A-z] o
no o formato padro de imprimir uma lista, mas, usando conjunto de todas as letras e [0-9] o conjunto de todos os
uma pilha, foi notavelmente fcil de fazer. dgitos. O operador ^nega um conunto, ento [^0-9] o
conjunto de tudo o que no nmero, que exatamente o que
Voc deve comparar este trecho de cdigo com queremos para dividir expresses ps-fixas.
a implementao de printBackward na seo 17.4. Existe um >>> import re
paralelo natura entre a verso recursiva de printBackward e o
algoritmo de pilha aqui. A diferen que printBackward usa a >>> re.split ("[^0-9]", "123+456*/")
pilha de execuo para XXXmanter a trilha(keep track) dos ['123', '+', '456', '*', '', '/', ' ']
ns enquanto percorre a lista, e ento imprime-a no retorno da Note que a ordem dos argumentos diferente de
recurso. o algoritmo de pilha faz a mesma coisa, exceto que string.split, o delimitador vem antes da string.
usa o objeto Stack ao invs da pilha de execuo.
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.5 Usando uma pilha para avaliar expresses ps-
fixas
18.7 Avaliando em ps-fixo.
Em muitas linguagens de programao, expresses
matemticas so executadas com o poerador entre os roid Para avaliar uma expresso ps-fixa, usaremos o parser da
operandos, como em 1 + 2. Este formato chamado notao seo anterior e o algoritmo da seo anterior a ela. Para
infixa. Uma alternativa usada por algumas calculadoras manter as coisas simples, comearemos com um avaliador que
chamada notao ps-fixa. Em notao ps-fixa, o operador implementa somente os operadores + e .
segue os operandos, como em 1 2 +.
def evalPostfix (expr) :
A razo pela qual a notao ps-fixa til import re
algumas vezes que existe uma maneira natural de avaliar tokenList = re.split ("([^0-9])", expr)
uma expresso ps-fixa usando uma pilha:
stack = Stack()
comeando no incio da expresso, peque um termo for token in tokenList
(operador ou operando) de cada vez. if token == '' or token = ' ' :
Se o termo um operando, empilhe-o continue
if token == '+' :
Se o termo um operador, desempilhe dois sum = stack.pop() + stack.pop()
operandos, execute a operao neles, e empilhe o stack.push(sum)
resultado.
if token == '*' :
Quando chegar ao fim da expresso, deve existir product = stack.pop() * stack.pop()
exatamente um operando sobrando na pilha. Este stack.push(product)
operando o resultado. else:
Como um exerccio, aplique este algoritmo stack.push(int(token))
expresso 1 2 + 3 * . return stack.pop()
Este exemplo demonstra uma das vantagens da A primeira condio cuida de espaos e strings
notao ps-fixa - no necessrio usar parnteses para vazias. As duas prximas condies manipulam os
controlar a ordem das operaes. Para ter o mesmo resultado operadores. Ns assumimos, agora que qualquer coisa um
em notao infixa, deveramos escrever (1 + 2) * 3. operador. claro, seria melhor chegar por entrada errnea e
enviar uma mensagem de erro, mas faremos isto depois.
Como um exerccio, escreva a expresso ps-
fixa que equivalente a 1 + 2 * 3. Vamos test-lo avaliando a forma ps-fixa de
(56 + 47) * 2
>>> print evalPostfix("56 47 + 2 *")
18.6 Anlise sinttica 206

Para implementar o algoritmo anterior, necessitamos estar


prontos para percorrer uma string e quebr-la em operandos e 18.8 Clientes de fornecedores.
operadores. Este process um exemplo de parsing, e o
resultado - os pedaos da string - so chamados tokens. Voc
deve lembrar estas palavras do captulo 1. Um dos objetivos de um TAD separar os interesses do
fornecedor, quem escreve o cdigo que implementa o TAD, e
Python fornece um mtodo split nos mdulos o cliente, que usa o TAD. O fornecedor tem que se preocupar
string e re (expresses regulares). A funo string.split separa apenas se a implementao est correta - de acordo com a
uma string numa lista usando um nico caracter como especificao do TAD - e no como ele ser usado.
delimitador. Por exemplo:
Inversamente, o cliente assume que a
>>> import string implementao do TAD est correta e no se preocupa com os
>>> string.split ("Now is the time", " ") detalhes. Quando voc est usando um tipo nativo do Python,
['Now', 'is', 'the', 'time'] tem o luxo de pensar exclusivamente como um cliente.
Neste caso, o delimitador o caracter de espao, claro, quanto voc implementa um TAD, voc
ento a string dividida a cada espao. tambm tem que escrever cdigo cliente para test-lo. Neste
caso, voc faz os dois papis, o que pode ser confuso. Voc

Captulo 18: Pilhas #85


Como pensar como um cientista da Computao usando Python

deve fazer algum esfor para manter a trilha do papel que


est fazendo a cada momento.

18.9 Glossrio

tipo abstrato Um tipo de dado(geralmente uma coleo


de dados de objetos) que definidopor um conjunto
(TAD) de operaes, que podem ser implementadas
(abstract data de vrias maneiras.
type(ADT)):
interface o conjunto de operaes que definem um
(interface): TDA.
implementa Cdigo que satisfaz(preenche?) os requisitos
o sintticos e semnticos de uma interface.
(implementati
on):
cliente Um programa (ou o programador que o
(client): escreveu) que faz utilizao de um TDA.
fornecedor Cdigo (ou o programador que o escreveu)
(provider): que implementa um TDA.
revestimento Definio de classe que implementa um
(veneer): 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 Tipo de estrutura de dados que contem data
dados de um tipo qualquer(tipo genrico).
genrica
(generic data
structure):
infixa (infix): Notao matemtica em que os operadores
se situam entre os operandos.
ps-fixa Notao matemtica em que os operadores
(postfix): se situam aps os operandos.
parse (parse): Ler um conjunto de caracteres(string de
caracteres) ou tokens(smbolos atmicos) e
analisar sua estrutura gramatical.
token (token): Conjunto de caracteres que so tratados
como uma unidade atmica para fins de
anlise gramatical, como as palavras na
linguagem natural.
delimitador Um caracter que utilizado para separar os
(delimiter): smbolos atmicos(tokens), como a
pontuao na linguagem natural.

Captulo 18: Pilhas #86


Como pensar como um cientista da Computao usando Python

Captulo 19: Filas

Este captulo apresenta dois TDAs: Fila e Fila por Prioridade. else:
Na nossa vida diria, fila um alinhamento de consumidores # find the last node in the list
aguardando algum tipo de servio. Na maioria dos casos, o last = self.head
primeiro da fila o primeiro a ser atendido. Mas h excees.
No aeroporto, passageiros cujo vo vai decolar logo, s vezes while last.next: last = last.next
so chamados primeiro ao balco do check-in, mesmo que # append the new node
estejam no meio da fila. No supermercado, comum na fila do last.next = node
caixa algum deixar passar na frente uma pessoa que chega self.length = self.length + 1
fila s com um ou dois produtos na mo.
A regra que determina quem o prximo da fila def remove(self):
chama-se poltica de enfileiramento. A poltica de cargo = self.head.cargo
enfileiramento mais simples chama-se FIFO, sigla de first-in- self.head = self.head.next
first-out: primeiro a entrar, primeiro a sair. A poltica de self.length = self.length - 1
enfileiramento mais geral o enfileiramento por prioridade,
em que se atribui uma prioridade a cada pessoa da fila e a que return cargo
tiver maior prioridade vai primeiro, independente da sua Os mtodos isEmpty e remove so idnticos aos
ordem de chegada. Dizemos que essa a poltica mais geral mtodos isEmpty e removeFirst de LinkedList. O mtodo
de todas, porque a prioridade pode ser baseada em qualquer insert novo e um pouco mais complicado.
coisa: hora de partida do vo; quantos produtos a pessoa vai
passar pelo caixa; o grau de prestgio da pessoa. claro que Queremos inserir novos itens no fim da lista. Se
a fila estiver vazia, basta fazer head apontar ao novo n. Se
nem todas as polticas de enfileiramento so "justas", mas o
que justo depende do ponto de vista. no, percorremos a lista at o ltimo n e l penduramos o
novo n. possvel identificar o ltimo n porque o seu
O TDA Fila e o TDA Fila por Prioridade tm o atributo next None.
mesmo conjunto de operaes. A diferena est na semntica
das operaes: a fila usa a poltica FIFO; e a fila por Existem duas invariantes para um objeto Fila
prioridade (como o prprio nome sugere) usa a poltica de bem formado: o atributo length deve ser o nmero de ns na
enfileiramento por prioridade. fila, e o ltimo n deve ter seu atributo next igual a None.
Estude o mtodo at ficar convencido de que ele preserva
ambas invariantes.
19.1 Um TDA Fila
19.3 Caractersticas de performance
O TDA Fila definido pelas seguintes operaes:
__init__ Inicializar uma nova fila vazia. Quando invocamos um mtodo, normalmente no estamos
preocupados com os detalhes da sua implementao. Porm,
insert Adicionar um novo item fila. h um certo "detalhe" que pode ser bom conhecer: as
caractersticas de performance do mtodo. Quanto tempo leva,
remove Remover e retornar um item da fila. O item e como o tempo de execuo muda medida em que aumenta
retornado o que foi adicionado primeiro. o nmero de itens da coleo?
isEmpty Checar se a fila est vazia. Primeiro, olhe para remove. No h laos ou
chamadas de funo aqui, o que sugere que o tempo de
execuo desse mtodo sempre o mesmo, toda vez. Um
mtodo assim chamado de operao de tempo constante.
19.2 Fila encadeada Na verdade, o mtodo pode ser ligeiramente mais rpido
quando a lista est vazia, uma vez que ele pula o corpo da
A primeira implementao que vamos ver de um TDA Fila condicional, mas essa diferena no significativa. XXX: o
chama-se fila encadeada porque feita de objetos Ns condicional s aparece na re-implementao do mtodo na
encadeados. A definio da classe a seguinte: classe ImprovedQueue, p.200; essa inconsistncia pode ser
conferida tambm nas pginas 198-199 do livro original (PDF
class Queue: e impresso).
def __init__(self): A performance de insert muito diferente. No
self.length = 0 caso geral, temos de percorrer a lista para achar o ltimo
self.head = None elemento.
Este percurso leva um tempo proporcional
def isEmpty(self): extenso da lista. Uma vez que o tempo de execuo uma
return (self.length == 0) funo linear da extenso, dizemos que este mtodo opera em
tempo linear. Isso bem ruim, se comparado com o tempo
def insert(self, cargo): constante.
node = Node(cargo)
node.next = None
if self.head == None: 19.4 Fila encadeada aprimorada
# if list is empty the new node goes first
self.head = node Queremos uma implementao do TDA Fila que possa

Captulo 19: Filas #87


Como pensar como um cientista da Computao usando Python

realizar todas as operaes em tempo constante. Uma maneira


de fazer isso modificar a classe Fila, de modo que ela 19.5 Fila por prioridade
mantenha a referncia tanto ao primeiro quanto ao ltimo n,
como mostra a figura: O TDA Fila por Prioridade tem a mesma interface que o TDA
Fila, mas semntica diferente. Mais uma vez, a interface a
seguinte:
__init__ Inicializar uma nova fila vazia.
insert Adicionar um novo item fila.
remove Remover e retornar um item da fila. O item
retornado aquele que tiver maior prioridade.
A implementao de ImprovedQueue tem essa isEmpty Checar se a fila est vazia.
cara:
A diferena semntica que o item removido da
class ImprovedQueue: fila no necessariamente o que foi includo primeiro e, sim,
def __init__(self): o que tem maior prioridade. Que prioridades so essas e como
self.length = 0
elas se comparam umas com as outras no especificado pela
implementao Fila por Prioridade. Isso depende de quais
self.head = None itens esto na fila.
self.last = None
Por exemplo, se os itens da fila tiverem nome,
def isEmpty(self):
podemos escolh-los por ordem alfabtica. Se for a pontuao
de um jogo de boliche, podemos ir da maior para a menor,
return (self.length == 0) mas se for pontuao de golfe, teramos que ir da menor para
At agora, a nica mudana o atributo last. Ele a maior. Se possvel comparar os itens da fila, possvel
usado nos mtodos insert e remove: achar e remover o que tem maior prioridade. Essa
implementao da Fila por Prioridade tem como atributo uma
class ImprovedQueue: lista Python chamada items, que contm os itens da fila.
# ...
def insert(self, cargo): class PriorityQueue:
node = Node(cargo) def __init__(self):
node.next = None self.items = []
if self.length == 0:
#if list is empty, the new node is head & last def isEmpty(self):
self.head = self.last = node return self.items == []
else:
# find the last node def insert(self, item):
last = self.last self.items.append(item)
# append the new node O mtodo de inicializao, isEmpty, e insert so
last.next = node apenas uma fachada para operaes bsicas de lista. O nico
mtodo interessante remove:
self.last = node
self.length = self.length + 1 class PriorityQueue:
Uma vez que last no perde de vista o ultimo # ...
n, no necessrio busc-lo. Como resultado, esse mtodo def remove(self):
tem tempo constante. maxi = 0
Mas essa rapidez tem preo. preciso adicionar for i in range(1,len(self.items)):
um caso especial a remove, para configurar last para None if self.items[i] > self.items[maxi]:
quando o ultimo n removido: maxi = i
item = self.items[maxi]
class ImprovedQueue:
self.items[maxi:maxi+1] = []
#...
return item
def remove(self):
cargo = self.head.cargo No incio de cada iterao, maxi armazena o
ndice do maior item (a prioridade mais alta de todas) que
self.head = self.head.next vimos at agora. A cada volta do lao, o programa compara o
self.length = self.length - 1 i-simo item ao campeo. Se o novo item for maior, maxi
if self.length == 0: recebe o valor de i.
self.last = None
Quando o comando for se completa, maxi o
return cargo ndice do maior item. Esse item removido da lista e
Essa implementao mais complicada que a retornado.
primeira, e mais difcil de se demonstrar que est correta. A
vantagem que o objetivo foi atingido -- tanto insert quanto Vamos testar a implementao:
remove` so operaes de tempo constante.
>>> q = PriorityQueue()
Como exerccio, escreva uma implementao >>> q.insert(11)
do TDA Fila usando uma lista nativa do Python. Compare a >>> q.insert(12)
performance dessa implementao com a de ImprovedQueue, >>> q.insert(14)
para filas de diversos comprimentos.
>>> q.insert(13)
>>> while not q.isEmpty(): print q.remove()
14

Captulo 19: Filas #88


Como pensar como um cientista da Computao usando Python

13 >>> pq = PriorityQueue()
12 >>> pq.insert(tiger)
11 >>> pq.insert(phil)
Se a fila contm nmeros ou strings simples, >>> pq.insert(hal)
eles so removidas em ordem numrica decrescente ou >>> while not pq.isEmpty(): print pq.remove()
alfabtica invertida (de Z at A). Pyhton consegue achar o Tiger Woods : 61
maior inteiro ou string porque consegue compar-los usando Hal Sutton : 69
os operadores de comparao nativos.
Phil Mickelson : 72
Se a fila contm objetos de outro tipo, os Como exerccio, escreva uma implementao do
objetos tm que prover um mtodo __cmp__. Quando remove TDA Fila por Prioridade usando uma lista encadeada.
usa o operador > para comparar dois itens, o mtodo __cmp__ Mantenha a lista em ordem para que a remoo seja uma
de um dos itens invocado, recebendo o segundo item como operao de tempo constante. Compare a performance dessa
argumento. Desde que o mtodo __cmp__ funcione de forma implementao com a implementao usando uma lista
consistente, a Fila por Prioridade vai funcionar. nativa do Python.

19.6 A classe Golfer 19.7 Glossrio


Como exemplo de um objeto com uma definio no-usual de fila (queue) Conjunto de objetos ordenados esperando
prioridade, vamos implementar uma classe chamada Golfer algum tipo de servio.
(golfista), que mantm registro dos nomes e da pontuao de
golfistas. Como sempre, comeamos definindo __init__ e Fila (Queue) TAD (Tipo Abstrato de Dado) que realiza
__str__: operaes comuns de acontecerem em
uma fila.
class Golfer:
def __init__(self, name, score): poltica de As regras que determinam qual membro
self.name = name enfileiramento de uma fila o prximo a ser removido.
self.score= score (queueing
policy)
def __str__(self): FIFO "First In, First Out," (primeiro a entrar,
return "%-16s: %d" % (self.name, self.score) primeiro a sair) poltica de enfileiramento
O mtodo __str__ usa o operador de formato em que o primeiro membro a chegar o
para colocar nomes e pontuaes em colunas arrumadas. primeiro a ser removido.

Em seguida, definimos uma verso de __cmp__, fila por Poltica de enfileiramento em que cada
ma qual a pontuao mais baixa fica com prioridade mxima. prioridade membro tem uma prioridade, determinada
Como sempre, __cmp__ retorna 1 se self "maior que" other, (priority queue) por fatores externos. O membro com a
-1 se self "menor que" other, e 0 se eles so iguais. maior prioridade o primeiro a ser
removido.
class Golfer: Fila por TAD que define as operaes comuns de
#... Prioridade acontecerem em uma fila por prioridade.
def __cmp__(self, other): (Priority
if self.score < other.score: return 1 # less Queue)
is more
fila encadeada Implementao de uma fila usando uma
if self.score > other.score: return -1 (linked queue) lista encadeada.
return 0
Agora estamos prontos para testar a fila por tempo constante Operao cujo tempo de execuo no
prioridade com a classe Golfer: (constant time) depende do tamanho da estrutura de
dados.
>>> tiger = Golfer("Tiger Woods", 61)
tempo linear Operao cujo tempo de execuo uma
>>> phil = Golfer("Phil Mickelson", 72) (linear time) funo linear do tamanho da estrutura de
>>> hal = Golfer("Hal Sutton", 69) dados.
>>>

Captulo 19: Filas #89


Como pensar como um cientista da Computao usando Python

Captulo 20: rvores

Como listas ligadas, rvores so constitudas de clulas. Uma


espcie comum de rvores a rvore binria, em que cada 20.1 Construindo rvores
clula contm referncias a duas outras clulas (possivelmente
nulas). Tais referncias so chamadas de subrvore esquerda e O processo de montar uma rvore similar ao processo de
direita. Como as clulas de listas ligadas, as clulas de rvores montar uma lista ligada. cada invocao do construtor cria
tambm contm uma carga. Um diagrama de estados para uma uma clula.
rvore pode aparecer assim:
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:
Para evitar a sobrecarga da figura, ns
frequentemente omitimos os Nones. tree = Tree(1, left, right);
Podemos escrever este cdigo mais
O topo da rvore (a clula qual o apontador concisamente encaixando as invocaes do construtor:
tree se refere) chamada de raiz. Seguindo a metfora das
rvores, as outras clulas so chamadas de galhos e as clulas >>> tree = Tree(1, Tree(2), Tree(3))
nas pontas contendo as referncias vazia so chamadas de De qualquer forma, o resultado a rvore que
folhas. Pode parecer estranho que desenhamos a figura com a apareceu no incio do captulo.
raiz em cima e as folhas em baixo, mas isto nem ser a coisa
mais estranha.
Para piorar as coisas, cientistas da computao 20.2 Percorrendo rvores
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. Cada vez que Voc v uma nova estrutura de dados, sua
Clulas com o mesmo pai so chamadas de irmos. primeira pergunta deveria ser "Como eu percorro esta
estrutura?" A forma mais natural de percorrer uma rvore
Finalmente, existe tambm o vocabulrio fazer o percurso recursivamente. Por exemplo, se a rvore
geomtrico para falar de rvores. J mencionamos esquerda e contm inteiros na carga, a funo abaixo retorna a soma das
direita, mas existem tambm as direes "para cima" (na cargas:
direo da raiz) e "para baixo" (na direo dos filhos/folhas).
Ainda nesta terminologia, todas as clulas situadas mesma def total(tree) :
distncia da raiz constituem um nvel da rvore. if tree == None : return 0
return total(tree.left) + total(tree.right) +
Provavelmente no precisamos de trs
metforas para falar de rvores, mas a elas esto. tree.cargo
O caso base a rvore vazia, que no contm
Como listas ligadas, rvores so estruturas de nenhuma carga, logo a soma das cargas 0. O passo recursivo
dados recursivas j que elas so definidas recursivamente: faz duas chamadas recursivas para achar a soma das cargas
das subrvores dos filhos. Ao finalizar a chamada recursiva,
Uma rvore adicionamos a carga do pai e devolvemos o valor total.
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.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

Captulo 20: rvores #90


Como pensar como um cientista da Computao usando Python

saibamos que a multiplicao feita antes da adio. rvore numa ordem diferente, Voc produzir expresses
numa notao diferente. Por exemplo, se Voc imprime
A rvore de expresso seguinte representa a subrvores primeiro e depois a raiz, Voc ter:
mesma computao:
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
As clulas de uma rvore de expresso podem acabamos de omitir uma complicao importante. algumas
ser operandos como 1 e 2 ou operaes como + e *. As clulas vezes quando escrevemos expresses na notao infixa
contendo operandos so folhas; aquelas contendo operaes devemos usar parntesis para prescrever a ordem das
devem ter referncias aos seus operandos. (Todos os nossos operaes. Ou seja, um percurso em inordem no suficiente
operandos so binrios, significando que eles tem exatamente para gerar a expresso infixa.
dois operandos.)
Ainda assim, com alguns aperfeioamentos, a
Podemos construir rvores assim: rvore de expresso e os trs modos recursivos de percurso
resultam em algoritmos para transformar expresses de uma
>>> tree = Tree('+', Tree(1), Tree('*', Tree(2), notao para outra.
Tree(3)))
Examinando a figura, no h dvida quanto Como um exerccio, modifique
ordem das operaes; a multiplicao feita primeiro para `printTreeInorder` de modo que ele coloque parntesis em
calcular o segundo operando da adio. volta de cada operador e par de operandos. A sada correta
e no ambgua? Os parntesis so sempre necessrios?
rvores de expresso tem muitos usos. O
exemplo neste captulo usa rvores para traduzir expresses Se percorrermos uma rvore em inordem e
para as notaes psfixa, prefixa e infixa. rvores similares acompanharmos em qual nvel na rvore estamos, podemos
so usadas em compiladores para analisar sintaticamente, gerar uma representao grfica da rvore:
otimizar e traduzir programas.
def printTreeIndented(tree, level=0) :
if tree == None : return
printTreeIndented(tree.right, level+1)
20.4 Percurso de rvores print ' '*level + str(tree.cargo)
printTreeIndented(tree.left, level+1)
Podemos percorrer uma rvore de expresso e imprimir o seu O parmetro level registra aonde estamos na
contedo como segue: rvore. Por 'default', o nvel inicialmente zero. A cada
def printTree(tree) : chamada recursiva repassamos level+1 porque o nvel do filho
if tree == None : return
sempre um a mais do que o nvel do pai. Cada item
indentado dois espaos por nvel. Para o nosso exemplo
print tree.cargo, obtemos:
printTree(tree.left)
printTree(tree.right) >>> printTreeIndented(tree)
Em outras palavras, para imprimir uma rvore, 3
imprima primeiro o contedo da raiz, em seguida imprima *
toda a subrvore esquerda e finalmente imprima toda a 2
subrvore direita. Esta forma de percorrer uma rvore +
chamada de prordem, porque o contedo da raiz aparece 1
antes dos contedos dos filhos. Para o exemplo anterior, a
sada : Se Voc deitar a sada acima Voc enxerga uma
verso simplificada da figura original.
>>> tree = Tree('+', Tree(1), Tree('*', Tree(2),
Tree(3)))
>>> printTree(tree) 20.5 Construindo uma rvore de expresso
+ 1 * 2 3
Esta notao diferente tanto da notao Nesta seo analisamos expresses infixas e construmos as
psfixa quanto da infixa; uma notao chamada de prefixa, rvores de express correspondentes. Por exemplo, para a
em que os operadores aparecem antes dos seus operandos. expresso (3+7)*9 resultar a seguinte rvore:
Voc pode suspeitar que se Voc percorre a

Captulo 20: rvores #91


Como pensar como um cientista da Computao usando Python

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
Note que simplificamos o diagrama omitindo os buscar o segundo nmero e construir a rvore com a, b e o
nomes dos campos. operador.
O analisador que escreveremos aceitar Se o caractere seguinte for qualquer outra coisa,
expresses que incluam nmeros, parntesis e as operaes + ento simplesmente devolvemos uma clula folha com a.
e *. Vamos supor que a cadeia de entrada j foi tokenizada Seguem dois exemplos:
numa lista do Python. A lista de tokens para a expresso
(3+7)*9 : >>> tokenList = [9, '*', 11, 'end']
>>> tree = getProduct(tokenList)
['(', 3, '+', 7, ')', '*', 9, 'end'] >>> printTreePostorder(tree)
O token final end prtico para prevenir que o 9 11 *
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 >>> tokenList = [9, '+', 11, 'end']
devolve a lista de tokens. >>> tree = getProduct(tokenList)
A primeira funo que escreveremos getToken >>> printTreePostorder(tree)
que recebe como parmetros uma lista de tokens e um token 9
esperado. Ela compara o token esperado com o o primeiro O segundo exemplo sugere que ns
token da lista: se eles batem a funo remove o token da lista e consideramos um operando unitrio como uma espcie de
devolve um valor verdadeiro, caso contrrio a funo devolve produto. Esta definio de "produto" talvez no seja intuitiva,
um valor falso: mas ela ser til.
def getToken(tokenList, expected) : Agora tratamos produtos compostos, como 3 * 5
if tokenList[0] == expected : * 13. Encaramos esta expresso como um produto de
tokenList[0:1] = [] # remove the token produtos, mais precisamente como 3 * (5 * 13). A rvore
resultante :
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 Com uma pequena alterao em getProduct,
que resta na lista de tokens: podemos acomodar produtos arbitrariamente longos:
>>> tokenList = [9, 11, 'end'] def getProduct(tokenList) :
>>> x = getNumber(tokenList) a = getNumber(tokenList)
>>> printTreePostorder(x) if getToken(tokenList, '*') :
9 b = getProduct(tokenList) # this line changed
>>> print tokenList return Tree('*', a, b)
[11, 'end'] else :

Captulo 20: rvores #92


Como pensar como um cientista da Computao usando Python

return a idia dar a getNumber um nome mais descritivo do seu novo


Em outras palavras, um produto pode ser um papel.
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. 20.6 Manipulando erros
Testemos a nova verso com um produto
composto: Ao longo do analisador sinttico tnhamos suposto que as
expresses (de entrada) so bem formadas. Por exemplo,
>>> tokenList = [2, '*', 3, '*', 5 , '*', 7, 'end'] quando atingimos o fim de uma subexpresso, supomos que o
>>> tree = getProduct(tokenList) prximo caractere um facha parntesis. Caso haja um erro e
>>> printTreePostorder(tree) o prximo caractere seja algo diferente, devemos tratar disto.
2 3 5 7 * * *
def getNumber(tokenList) :
A seguir adicionamos o tratamento de somas. if getToken(tokenList, '(') :
De novo, usamos uma definio de "soma" que ligeiramente
no intuitiva. Para ns, uma soma pode ser uma rvore com + x = getSum(tokenList)
na raiz, que tem um produto como filho esquerdo e uma soma if not getToken(tokenList, ')'):
como filho direito. Ou, uma soma pode ser simplesmente um raise 'BadExpressionError',
produto. 'missing parenthesis'
Se Voc est disposto a brincar com esta return x
definio, ela tem uma propriedade interessante: podemos else :
representar qualquer expresso (sem parntesis) como uma # the rest of the function omitted
soma de produtos. Esta propriedade a base do nosso O comando raise cria uma exceo; neste caso
algoritmo de anlise sinttica. criamos um novo tipo de exceo, chamada de
getSum tenta construir a rvore com um produto BadExpressionError.
uma das outras
Se a funo que chamou getNumber, ou
funes no traceback, manipular a exceo,
esquerda e uma soma direita. Mas, se ele no encontra uma ento o programa pode continuar. caso contrrio Python vai
+, ele simplesmente constri um produto. imprimir uma mensagem de erro e terminar o processamento
def getSum(tokenList) : em seguida.
a = getProduct(tokenList) A ttulo de exerccio, encontre outros locais nas
if getToken(tokenList, '+') : funes criadas onde erros possam ocorrer e adiciona
b = getSum(tokenList) comandos ``raise`` apropriados. Teste seu cdigo com
return Tree('+', a, b) expresses mal formadas.
else :
return a
Vamos testar o algoritmo com 9 * 11 + 5 * 7: 20.7 A rvore dos animais
>>> tokenList = [9, '*', 11, '+', 5, '*', 7, 'end'] Nesta seo, desenvolvemos um pequeno programa que usa
>>> tree = getSum(tokenList) uma rvore para representar uma base de conhecimento.
>>> printTreePostorder(tree)
9 11 * 5 7 * + O programa interage com o usurio para criar
uma rvore de perguntas e de nomes de animais. Segue uma
Quase terminamos, mas ainda temos que tratar amostra da funcionalidade:
dos parntesis. Em qualquer lugar numa expresso onde
podemos ter um nmero, podemos tambm ter uma soma Are you thinking of an animal? y
inteira envolvida entre parntesis. Precisamos, apenas, Is it a bird? n
modificar getNumber para que ela possa tratar de What is the animals name? dog
subexpresses:
What question would distinguish a dog from a bird?
def getNumber(tokenList) : Can it fly
if getToken(tokenList, '(') : If the animal were dog the answer would be? n
x = getSum(tokenList) # get subexpression
getToken(tokenList, ')') #eat closing parenthesis Are you thinking of an animal? y
return x Can it fly? n
else : Is it a dog? n
x = tokenList[0] What is the animals name? cat
if type(x) != type(0) : return None What question would distinguish a cat from a dog?
tokenList[0:1] = [] # remove the token Does it bark
return Tree(x, None, None) # return a leaf If the animal were cat the answer would be? n
with the number
Testemos este cdigo com 9 * (11 + 5) * 7: Are you thinking of an animal? y
Can it fly? n
>>> tokenList = [9, '*', '(', 11, '+', 5, ')', '*', Does it bark? y
7, 'end']
Is it a dog? y
>>> tree = getSum(tokenList)
I rule!
>>> printTreePostorder(tree)
9 11 5 + 7 * *
Are you thinking of an animal? n
O analisador tratou os parntesis corretamente; a Aqui est a rvore que este dilogo constri:
adio feita antes da multiplicao.
Na verso final do programa, seria uma boa

Captulo 20: rvores #93


Como pensar como um cientista da Computao usando Python

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.
No comeo de cada rodada, o programa parte do
topo da rvore e faz a primeira pergunta. Dependendo da O lao while interno caminha na rvore de cima
resposta, ele segue pelo filho esquerdo ou direito e continua para baixo, guiado pelas respostas do usurio.
at chegar numa folha. Neste ponto ele arrisca um palpite. Se
o palpite no for correto, ele pergunta ao usurio o nome de Quando uma nova clula adicionada rvore,
um novo animal e uma pergunta que distingue o palpite errado a nova pergunta substitui a carga e os dois filhos so o novo
do novo animal. A seguir, adiciona uma clula rvore animal e a carga original.
contendo a nova pergunta e o novo animal. Uma falha do programa que ao sair ele
Aqui est o cdigo: esquece tudo que lhe foi cuidadosamente ensinado!
def animal() : A ttulo de exerccio, pense de vrias jeitos para
salvar a rvore do conhecimento acumulado num arquivo.
# start with a singleton Implemente aquele que Voc pensa ser o mais fcil.
root = Tree("bird")

# loop until the user quits


while 1 :
20.8 Glossrio
print
if not yes("Are you thinking of an animal? ") : rvore binria Uma rvore em que cada clula tem zero,
break (binary tree) um ou dois descendentes.
raiz (root) A clula mais alta de uma rvore, a (nica)
# walk the tree clula de uma rvore que no tem pai.
tree = root
folha (leaf) Uma clula mais baixa numa rvore; uma
while tree.getLeft() != None : clula que no tem descendentes.
prompt = tree.getCargo() + "? "
if yes(prompt): pai (parent) A clula que aponta para uma clula dada.
tree = tree.getRight() filho (child) Uma clula apontada por uma clula dada.
else:
tree = tree.getLeft()
irmos Clulas que tem o mesmo pai.
(siebling)
# make a guess nvel (level) Um conjunto de clulas equidistantes da
guess = tree.getCargo() raiz.
prompt = "Is it a " + guess + "? " operador Um operador sobre dois operandos.
if yes(prompt) : binrio
print "I rule!" (binary
continue operator)
subexpresso Uma expresso entre parntesis que se
# get new information (subexpressio comporta como um operando simples numa
prompt = "What is the animal\'s name? " n) expresso maior.
animal = raw_input(prompt) pr-ordem Uma forma de percorrer uma rvore
prompt = "What question would distinguish a %s (preorder) visitando cada clula antes dos seus filhos.
from a %s? "
question = raw_input(prompt % (animal,guess)) notao Uma forma de escrever uma expresso
prefixa (prefix matemtica em que cada operador aparece
notation) antes dos seus operandos.
# add new information to the tree
tree.setCargo(question) ps-ordem Uma forma de percorrer uma rvore
prompt = "If the animal were %s the answer would (postorder) visitando os filhos de cada clula antes da
be? " prpria clula.
if yes(prompt % animal) : in-ordem Uma forma de percorrer uma rvore
tree.setLeft(Tree(guess)) (inorder) visitando a subrvore esquerda, seguida da
tree.setRight(Tree(animal)) raiz e finalmente da subrvore direita.
else :

Captulo 20: rvores #94


Como pensar como um cientista da Computao usando Python

GNU Free Documentation License

Version 1.2, November 2002 matters, or of legal, commercial, philosophical, ethical or


political position regarding them.
Copyright (C) 2000,2001,2002 Free Software
Foundation, Inc. The "Invariant Sections" are certain Secondary
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 Sections whose titles are designated, as being those of
USA Invariant Sections, in the notice that says that the Document is
Everyone is permitted to copy and distribute
released under this License. If a section does not fit the above
definition of Secondary then it is not allowed to be designated
verbatim copies as Invariant. The Document may contain zero Invariant
of this license document, but changing it is not Sections. If the Document does not identify any Invariant
allowed. Sections then there are none.
The "Cover Texts" are certain short passages of
text that are listed, as Front-Cover Texts or Back-Cover Texts,
0. PREAMBLE in the notice that says that the Document is released under this
License. A Front-Cover Text may be at most 5 words, and a
The purpose of this License is to make a manual, textbook, or Back-Cover Text may be at most 25 words.
other functional and useful document "free" in the sense of A "Transparent" copy of the Document means a
freedom: to assure everyone the effective freedom to copy and machine-readable copy, represented in a format whose
redistribute it, with or without modifying it, either specification is available to the general public, that is suitable
commercially or noncommercially. Secondarily, this License for revising the document straightforwardly with generic text
preserves for the author and publisher a way to get credit for editors or (for images composed of pixels) generic paint
their work, while not being considered responsible for programs or (for drawings) some widely available drawing
modifications made by others. editor, and that is suitable for input to text formatters or for
This License is a kind of "copyleft", which automatic translation to a variety of formats suitable for input
means that derivative works of the document must themselves to text formatters. A copy made in an otherwise Transparent
be free in the same sense. It complements the GNU General file format whose markup, or absence of markup, has been
Public License, which is a copyleft license designed for free arranged to thwart or discourage subsequent modification by
software. readers is not Transparent. An image format is not
Transparent if used for any substantial amount of text. A copy
We have designed this License in order to use it that is not "Transparent" is called "Opaque".
for manuals for free software, because free software needs
free documentation: a free program should come with manuals Examples of suitable formats for Transparent
providing the same freedoms that the software does. But this copies include plain ASCII without markup, Texinfo input
License is not limited to software manuals; it can be used for format, LaTeX input format, SGML or XML using a publicly
any textual work, regardless of subject matter or whether it is available DTD, and standard-conforming simple HTML,
published as a printed book. We recommend this License PostScript or PDF designed for human modification.
principally for works whose purpose is instruction or Examples of transparent image formats include PNG, XCF
reference. and JPG. Opaque formats include proprietary formats that can
be read and edited only by proprietary word processors,
SGML or XML for which the DTD and/or processing tools
are not generally available, and the machine-generated
1. APPLICABILITY AND DEFINITIONS HTML, PostScript or PDF produced by some word processors
for output purposes only.
This License applies to any manual or other work, in any The "Title Page" means, for a printed book, the
medium, that contains a notice placed by the copyright holder title page itself, plus such following pages as are needed to
saying it can be distributed under the terms of this License. hold, legibly, the material this License requires to appear in
Such a notice grants a world-wide, royalty-free license, the title page. For works in formats which do not have any
unlimited in duration, to use that work under the conditions title page as such, "Title Page" means the text near the most
stated herein. The "Document", below, refers to any such prominent appearance of the work's title, preceding the
manual or work. Any member of the public is a licensee, and beginning of the body of the text.
is addressed as "you". You accept the license if you copy,
modify or distribute the work in a way requiring permission A section "Entitled XYZ" means a named
under copyright law. subunit of the Document whose title either is precisely XYZ
or contains XYZ in parentheses following text that translates
A "Modified Version" of the Document means XYZ in another language. (Here XYZ stands for a specific
any work containing the Document or a portion of it, either section name mentioned below, such as "Acknowledgements",
copied verbatim, or with modifications and/or translated into "Dedications", "Endorsements", or "History".) To "Preserve
another language. the Title" of such a section when you modify the Document
A "Secondary Section" is a named appendix or a means that it remains a section "Entitled XYZ" according to
front-matter section of the Document that deals exclusively this definition.
with the relationship of the publishers or authors of the The Document may include Warranty
Document to the Document's overall subject (or to related Disclaimers next to the notice which states that this License
matters) and contains nothing that could fall directly within applies to the Document. These Warranty Disclaimers are
that overall subject. (Thus, if the Document is in part a considered to be included by reference in this License, but
textbook of mathematics, a Secondary Section may not only as regards disclaiming warranties: any other implication
explain any mathematics.) The relationship could be a matter that these Warranty Disclaimers may have is void and has no
of historical connection with the subject or with related effect on the meaning of this License.

GNU Free Documentation License #95


Como pensar como um cientista da Computao usando Python

those of previous versions (which should, if there


2. VERBATIM COPYING were any, be listed in the History section of the
Document). You may use the same title as a previous
You may copy and distribute the Document in any medium, version if the original publisher of that version gives
either commercially or noncommercially, provided that this permission.
License, the copyright notices, and the license notice saying B. List on the Title Page, as authors, one or more
this License applies to the Document are reproduced in all persons or entities responsible for authorship of the
copies, and that you add no other conditions whatsoever to modifications in the Modified Version, together with
those of this License. You may not use technical measures to at least five of the principal authors of the Document
obstruct or control the reading or further copying of the copies (all of its principal authors, if it has fewer than five),
you make or distribute. However, you may accept unless they release you from this requirement.
compensation in exchange for copies. If you distribute a large C. State on the Title page the name of the publisher
enough number of copies you must also follow the conditions of the Modified Version, as the publisher.
in section 3. D. Preserve all the copyright notices of the
Document.
You may also lend copies, under the same E. Add an appropriate copyright notice for your
conditions stated above, and you may publicly display copies. modifications adjacent to the other copyright notices.
F. Include, immediately after the copyright notices, a
license notice giving the public permission to use the
3. COPYING IN QUANTITY Modified Version under the terms of this License, in
the form shown in the Addendum below.
If you publish printed copies (or copies in media that G. Preserve in that license notice the full lists of
commonly have printed covers) of the Document, numbering Invariant Sections and required Cover Texts given in
more than 100, and the Document's license notice requires the Document's license notice.
Cover Texts, you must enclose the copies in covers that carry, H. Include an unaltered copy of this License.
clearly and legibly, all these Cover Texts: Front-Cover Texts I. Preserve the section Entitled "History", Preserve its
on the front cover, and Back-Cover Texts on the back cover. Title, and add to it an item stating at least the title,
Both covers must also clearly and legibly identify you as the year, new authors, and publisher of the Modified
publisher of these copies. The front cover must present the full Version as given on the Title Page. If there is no
title with all words of the title equally prominent and visible. section Entitled "History" in the Document, create
You may add other material on the covers in addition. one stating the title, year, authors, and publisher of
Copying with changes limited to the covers, as long as they the Document as given on its Title Page, then add an
preserve the title of the Document and satisfy these item describing the Modified Version as stated in the
conditions, can be treated as verbatim copying in other previous sentence.
respects. J. Preserve the network location, if any, given in the
Document for public access to a Transparent copy of
If the required texts for either cover are too the Document, and likewise the network locations
voluminous to fit legibly, you should put the first ones listed given in the Document for previous versions it was
(as many as fit reasonably) on the actual cover, and continue based on. These may be placed in the "History"
the rest onto adjacent pages. section. You may omit a network location for a work
If you publish or distribute Opaque copies of the that was published at least four years before the
Document numbering more than 100, you must either include Document itself, or if the original publisher of the
a machine-readable Transparent copy along with each Opaque version it refers to gives permission.
copy, or state in or with each Opaque copy a computer- K. For any section Entitled "Acknowledgements" or
network location from which the general network-using public "Dedications", Preserve the Title of the section, and
has access to download using public-standard network preserve in the section all the substance and tone of
protocols a complete Transparent copy of the Document, free each of the contributor acknowledgements and/or
of added material. If you use the latter option, you must take dedications given therein.
reasonably prudent steps, when you begin distribution of L. Preserve all the Invariant Sections of the
Opaque copies in quantity, to ensure that this Transparent Document, unaltered in their text and in their titles.
copy will remain thus accessible at the stated location until at Section numbers or the equivalent are not considered
least one year after the last time you distribute an Opaque part of the section titles.
copy (directly or through your agents or retailers) of that M. Delete any section Entitled "Endorsements". Such
edition to the public. a section may not be included in the Modified
Version.
It is requested, but not required, that you contact N. Do not retitle any existing section to be Entitled
the authors of the Document well before redistributing any "Endorsements" or to conflict in title with any
large number of copies, to give them a chance to provide you Invariant Section.
with an updated version of the Document. O. Preserve any Warranty Disclaimers.
If the Modified Version includes new front-
matter sections or appendices that qualify as Secondary
4. MODIFICATIONS Sections and contain no material copied from the Document,
you may at your option designate some or all of these sections
You may copy and distribute a Modified Version of the as invariant. To do this, add their titles to the list of Invariant
Document under the conditions of sections 2 and 3 above, Sections in the Modified Version's license notice. These titles
provided that you release the Modified Version under must be distinct from any other section titles.
precisely this License, with the Modified Version filling the
role of the Document, thus licensing distribution and You may add a section Entitled
modification of the Modified Version to whoever possesses a "Endorsements", provided it contains nothing but
copy of it. In addition, you must do these things in the endorsements of your Modified Version by various parties--
Modified Version: for example, statements of peer review or that the text has
been approved by an organization as the authoritative
A. Use in the Title Page (and on the covers, if any) a definition of a standard.
title distinct from that of the Document, and from

GNU Free Documentation License #96


Como pensar como um cientista da Computao usando Python

You may add a passage of up to five words as a


Front-Cover Text, and a passage of up to 25 words as a Back- 7. AGGREGATION WITH INDEPENDENT
Cover Text, to the end of the list of Cover Texts in the
Modified Version. Only one passage of Front-Cover Text and WORKS
one of Back-Cover Text may be added by (or through
arrangements made by) any one entity. If the Document A compilation of the Document or its derivatives with other
already includes a cover text for the same cover, previously separate and independent documents or works, in or on a
added by you or by arrangement made by the same entity you volume of a storage or distribution medium, is called an
are acting on behalf of, you may not add another; but you may "aggregate" if the copyright resulting from the compilation is
replace the old one, on explicit permission from the previous not used to limit the legal rights of the compilation's users
publisher that added the old one. beyond what the individual works permit. When the
Document is included in an aggregate, this License does not
The author(s) and publisher(s) of the Document apply to the other works in the aggregate which are not
do not by this License give permission to use their names for themselves derivative works of the Document.
publicity for or to assert or imply endorsement of any
Modified Version. If the Cover Text requirement of section 3 is
applicable to these copies of the Document, then if the
Document is less than one half of the entire aggregate, the
Document's Cover Texts may be placed on covers that bracket
5. COMBINING DOCUMENTS the Document within the aggregate, or the electronic
equivalent of covers if the Document is in electronic form.
You may combine the Document with other documents Otherwise they must appear on printed covers that bracket the
released under this License, under the terms defined in section whole aggregate.
4 above for modified versions, provided that you include in
the combination all of the Invariant Sections of all of the
original documents, unmodified, and list them all as Invariant
Sections of your combined work in its license notice, and that 8. TRANSLATION
you preserve all their Warranty Disclaimers.
Translation is considered a kind of modification, so you may
The combined work need only contain one copy distribute translations of the Document under the terms of
of this License, and multiple identical Invariant Sections may section 4. Replacing Invariant Sections with translations
be replaced with a single copy. If there are multiple Invariant requires special permission from their copyright holders, but
Sections with the same name but different contents, make the you may include translations of some or all Invariant Sections
title of each such section unique by adding at the end of it, in in addition to the original versions of these Invariant Sections.
parentheses, the name of the original author or publisher of You may include a translation of this License, and all the
that section if known, or else a unique number. Make the same license notices in the Document, and any Warranty
adjustment to the section titles in the list of Invariant Sections Disclaimers, provided that you also include the original
in the license notice of the combined work. English version of this License and the original versions of
In the combination, you must combine any those notices and disclaimers. In case of a disagreement
sections Entitled "History" in the various original documents, between the translation and the original version of this License
forming one section Entitled "History"; likewise combine any or a notice or disclaimer, the original version will prevail.
sections Entitled "Acknowledgements", and any sections If a section in the Document is Entitled
Entitled "Dedications". You must delete all sections Entitled "Acknowledgements", "Dedications", or "History", the
"Endorsements." requirement (section 4) to Preserve its Title (section 1) will
typically require changing the actual title.

6. COLLECTIONS OF DOCUMENTS
9. TERMINATION
You may make a collection consisting of the Document and
other documents released under this License, and replace the You may not copy, modify, sublicense, or distribute the
individual copies of this License in the various documents Document except as expressly provided for under this
with a single copy that is included in the collection, providedLicense. Any other attempt to copy, modify, sublicense or
that you follow the rules of this License for verbatim copying distribute the Document is void, and will automatically
of each of the documents in all other respects. terminate your rights under this License. However, parties
You may extract a single document from such a who have received copies, or rights, from you under this
collection, and distribute it individually under this License, License will not have their licenses terminated so long as such
provided you insert a copy of this License into the extracted parties remain in full compliance.
document, and follow this License in all other respects
regarding verbatim copying of that document.
10. FUTURE REVISIONS OF THIS LICENSE
The Free Software Foundation may publish new, revised
versions of the GNU Free Documentation License from time
to time. Such new versions will be similar in spirit to the
present version, but may differ in detail to address new
problems or concerns. See http://www.gnu.org/copyleft/.
Each version of the License is given a
distinguishing version number. If the Document specifies that
a particular numbered version of this License "or any later
version" applies to it, you have the option of following the
terms and conditions either of that specified version or of any
later version that has been published (not as a draft) by the
Free Software Foundation. If the Document does not specify a

GNU Free Documentation License #97


Como pensar como um cientista da Computao usando Python

version number of this License, you may choose any version


ever published (not as a draft) by the Free Software
Foundation.

How to use this License for your documents


To use this License in a document you have
written, include a copy of the License in the document and put
the following copyright and license notices just after the title
page:
Copyright (c) YEAR YOUR NAME.
Permission is granted to copy, distribute and/or
modify this document
under the terms of the GNU Free Documentation
License, Version 1.2
or any later version published by the Free Software
Foundation;
with no Invariant Sections, no Front-Cover Texts,
and no Back-Cover
Texts. A copy of the license is included in the
section entitled "GNU
Free Documentation License".

If you have Invariant Sections, Front-Cover


Texts and Back-Cover Texts, replace the "with...Texts." line
with this:
with the Invariant Sections being LIST THEIR
TITLES, with the
Front-Cover Texts being LIST, and with the Back-
Cover Texts being LIST.

If you have Invariant Sections without Cover


Texts, or some other combination of the three, merge those
two alternatives to suit the situation.
If your document contains nontrivial examples
of program code, we recommend releasing these examples in
parallel under your choice of free software license, such as the
GNU General Public License, to permit their use in free
software.

GNU Free Documentation License #98

Você também pode gostar