You are on page 1of 118

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 Apresentao.................................................6 Preface...........................................................7
3.9 Parmetros e argumentos..........................24 3.10 Variveis e parmetros so locais...........25 3.11 Diagramas da pilha..................................25 3.12 Funes com resultados...........................25 3.13 Glossrio...................................................26

How and why I came to use Python..................7 Finding a textb o ok............................................7 Intro ducing programming with Python...........7 Captulo 4: Condicionais e recursividade..27 4.1 O operador mdulo....................................27 Building a community........................................8 4.2 Expresses booleanas................................27 Prefcio..........................................................9 4.3 Operadores lgicos.....................................27 Como e porque eu vim a usar Python...............9 4.4 Execuo condicional.................................27 Encontrando um livro texto...............................9 4.5 Execuo alternativa..................................28 Introduzindo programao com Python.........10 4.6 Condicionais encadeados...........................28 Construindo uma comunidade........................10 4.7 Condicionais aninhados.............................28 Contributor List...........................................11 4.8 A instruo return......................................28 Verso Brasileira.........................................13 4.9 Recursividade.............................................29 Captulo 1: O caminho do programa..........14 4.10 Diagramas de pilha para funes 1.1 A linguagem de programao Python.......14 recursivas.........................................................29 1.2 O que um programa?..............................15 4.11 Recursividade infinita..............................30 1.3 O que depurao (debugging)?...............15 4.12 Entrada pelo teclado................................30 1.3.1 Erros de sintaxe...............................15 4.13 Glossrio...................................................30 1.3.2 Erros em tempo de execuo Captulo 5: Funes frutferas....................31 (runtime errors)........................................15 5.1 Valores de retorno......................................31 1.3.3 Erros de semntica..........................15 5.2 Desenvolvimento de programas................31 1.3.4 Depurao experimental (Debugging) 5.3 Composio.................................................32 .................................................................16 5.4 Funes booleanas.....................................32 1.4 Linguagens naturais e linguagens formais... 5.5 Mais recursividade.....................................33 16 5.6 Voto de confiana (Leap of faith)...............33 1.5 O primeiro programa.................................17 5.7 Mais um exemplo.......................................34 1.6 Glossrio.....................................................17 5.8 Checagem de tipos......................................34 Captulo 2: Variveis, expresses e 5.9 Glossrio.....................................................34

comandos.....................................................18 Captulo 6: Iterao.....................................36


2.1 Valores e tipos.............................................18 2.2 Variveis.....................................................18 2.3 Nomes de variveis e palavras reservadas. . 18 2.4 Comandos...................................................19 2.5 Avaliando expresses.................................19 2.6 Operadores e operandos............................19 2.7 Ordem dos operadores...............................20 2.8 Operaes com strings...............................20 2.9 Composio.................................................20 2.11 Glossrio...................................................20 3.1 Chamadas de funes.................................22 3.2 Converso entre tipos.................................22 3.3 Coero entre tipos.....................................22 3.4 Funes matemticas.................................22 3.5 Composio.................................................23 3.6 Adicionando novas funes.......................23 3.7 Definies e uso..........................................24 3.8 Fluxo de execuo......................................24 6.1 Reatribuies..............................................36 6.2 O comando while........................................36 6.3 Tabelas........................................................37 6.4 Tabelas de duas dimenses (ou bidimensionais)...................................................38 6.5 Encapsulamento e generalizao..............38 6.6 Mais encapsulamento................................38 6.7 Variveis locais...........................................38 6.8 Mais generalizao.....................................39 6.9 Funes.......................................................39 6.10 Glossrio...................................................40 7.1 Um tipo de dado composto.........................41 7.2 Comprimento..............................................41 7.3 Travessia e o loop for.................................41 7.4 Fatias de strings..........................................42 7.5 Comparao de strings...............................42 7.6 Strings so imutveis.................................42 7.7 Uma funo find (encontrar).....................42 7.8 Iterando e contando...................................43

Captulo 3: Funes.....................................22 Captulo 7: Strings.......................................41

#3

Como pensar como um cientista da Computao usando Python

Captulo 8: Listas.........................................45 Captulo 13: Classes e funes....................66


8.1 Valores da lista...........................................45 13.1 Horario......................................................66 8.2 Acessado elementos...................................45 13.2 Funes Puras...........................................66 8.3 Comprimento da lista.................................45 13.3 Modificadores...........................................66 8.4 Membros de uma lista................................46 13.4 O que melhor ?.......................................67 8.5 Listas e laos for.........................................46 13.5 Desenvolvimento Prototipado versus 8.6 Operaes em listas....................................46 Desenvolvimento Planejado............................67 8.7 Fatiamento de listas...................................46 13.6 Generalizao...........................................67 8.8 Listas so mutveis.....................................46 13.7 Algoritmos.................................................68 8.9 Remoo em lista........................................47 13.8 Glossrio...................................................68 8.10 Ojetos e valores.........................................47 Captulo 14: Classes e mtodos...................69 8.11 Apelidos....................................................47 14.1 Caractersticas da orientao a objetos...69 8.12 Clonando listas..........................................48 14.2 exibeHora (printTime).............................69 8.13 Lista como parmetro..............................48 14.3 Um outro exemplo....................................70 8.14 Lista aninhadas........................................48 14.10 Glossrio.................................................70 8.15 Matrizes....................................................48 Captulo 15: Conjuntos de objetos..............71 8.16 Strings e listas...........................................49 15.1 Composio...............................................71 8.17 Glossrio...................................................49 15.2 Objetos Carta.............................................71 Captulo 9: Tuplas.......................................50 15.3 Atributos de classe e o mtodo __str__.....71 9.1 Mutabilidade e tuplas.................................50 15.4 Comparando cartas..................................72 9.2 Atribuies de tupla...................................50 15.5 Baralhos....................................................72 9.3 Tuplas como valores de retorno................50 15.6 Imprimindo o baralho..............................72 9.4 Nmeros aleatrios....................................50 15.7 Embaralhando..........................................73 9.5 Lista de nmeros aleatrios.......................51 15.8 Removendo e distribuindo cartas...........73 9.6 Contando.....................................................51 15.9 Glossrio...................................................74 9.7 Vrios intervalos........................................51 Capitulo 16: Herana..................................75 9.8 Uma soluo em um s passo....................52 16.1 Herana.....................................................75 9.9 Glossrio.....................................................52 16.2 Uma mo de cartas...................................75 Captulo 10: Dicionrios.............................54 16.3 Dando as cartas........................................75 10.1 Operaes dos Dicionrios.......................54 16.4 Exibindo a mao.........................................76 10.2 Mtodos dos Dicionrios..........................54 16.5 A classe JogoDeCartas..............................76 10.3 Aliasing (XXX) e Copiar............................55 16.6 Classe MaoDeMico....................................76 10.4 Matrizes Esparsas.....................................55 16.7 Classe Mico................................................77 10.5 Hint............................................................55 16.8 Glossrio...................................................78 10.6 Inteiros Longos.........................................56 Captulo 17: Listas encadeadas..................79 10.7 Contando Letras........................................56 17.1 Referncias Embutidas............................79 10.8 Glossrio...................................................56 17.2 A classe No (Node)....................................79 Captulo 11: Arquivos e excees...............58 17.3 Listas como Colees................................79 Arquivos e excees.........................................58 17.4 Listas e Recorrncia.................................80 11.1 Arquivos texto...........................................58 17.5 Listas Infinitas..........................................80 11.2 Gravando variveis..................................59 17.6 O Teorema da Ambigidade Fundamental 11.3 Diretrios..................................................60 80 11.4 Pickling.....................................................60 17.7 Modificando Listas...................................81 11.5 Excees....................................................60 17.8 Envoltrios e Ajudadores.........................81 11.6 Glossrio...................................................61 17.9 A Classe ListaLigada.................................81 Captulo 12: Classes e objetos.....................62 17.10 Invariantes..............................................82 12.1 Tipos compostos definidos pelo usurio. 62 17.11 Glossrio.................................................82 12.2 Atributos...................................................62 Captulo 18: Pilhas.......................................83 12.3 Instncias como parmetros...................63 18.1 Tipos abstratos de dados..........................83 12.4 O significado de "mesmo"........................63 18.2 O TAD Pilha...............................................83 12.5 Retngulos................................................63 18.3 Implementando pilhas com listas de
#4

7.9 O mdulo string..........................................43 7.10 Classificao de caracteres......................43 7.11 Glossrio...................................................43 7.11 Glossrio2.................................................44

12.6 Instancias como valores retornados.......64 12.7 Objetos so mutveis................................64 12.8 Copiando...................................................64 12.9 Glossrio...................................................65

Como pensar como um cientista da Computao usando Python

Python...............................................................83 20.4 Percurso de rvores.................................90 18.4 Empilhando e desempilhando.................83 20.5 Construindo uma rvore de expresso...90 18.5 Usando uma pilha para avaliar expresses 20.6 Manipulando erros...................................92 ps-fixas............................................................84 20.7 A rvore dos animais...............................92 18.6 Anlise sinttica.......................................84 20.8 Glossrio...................................................93 18.7 Avaliando em ps-fixo..............................84 GNU Free Documentation License.............94 18.8 Clientes de fornecedores..........................84 0. PREAMBLE ...................................................94 18.9 Glossrio...................................................85 1. APPLICABILITY AND DEFINITIONS ...........94 Captulo 19: Filas.........................................86 2. VERBATIM COPYING ...................................95 19.1 Um TDA Fila..............................................86 3. COPYING IN QUANTITY ..............................95 19.2 Fila encadeada..........................................86 4. MODIFICATIONS ..........................................95 19.3 Caractersticas de performance..............86 5. COMBINING DOCUMENTS ..........................96 19.4 Fila encadeada aprimorada.....................86 6. COLLECTIONS OF DOCUMENTS .................96 19.5 Fila por prioridade...................................87 7. AGGREGATION WITH INDEPENDENT 19.6 A classe Golfer..........................................88 WORKS .............................................................96 19.7 Glossrio...................................................88 8. TRANSLATION .............................................96 9. TERMINATION .............................................96 Captulo 20: rvores...................................89 10. FUTURE REVISIONS OF THIS LICENSE......96 20.1 Construindo rvores.................................89 How to use this License for your documents 20.2 Percorrendo rvores................................89 .................................................................96 20.3 rvores de expresses.............................89

#5

Como pensar como um cientista da Computao usando Python

Foreword

By David Beazley As an educator, researcher, and book author, I am delighted to see the completion of this book. Python is a fun and extremely easy-to-use programming language that has steadily gained in popularity over the last few years. Developed over ten years ago by Guido van Rossum, Pythons simple syntax and overall feel is largely derived from ABC, a teaching language that was developed in the 1980s. However, Python was also created to solve real problems and it borrows a wide variety of features from programming languages such as C++, Java, Modula-3, and Scheme. Because of this, one of Pythons most remarkable features is its broad appeal to professional software developers, scientists, researchers, artists, and educators.

Despite Pythons appeal to many dierent communities, you may still wonder why Python? or why teach programming with Python? Answering these questions is no simple taskespecially when popular opinion is on the side of more masochistic alternatives such as C++ and Java. However, I think the most direct answer is In reading Jereys preface, I am struck that programming in Python is simply a lot of fun by his comments that Python allowed him to see a and more productive. higher level of success and a lower level of When I teach computer science courses, frustration and that he was able to move faster I want to cover important concepts in addition to with better results. Although these comments refer making the material interesting and engaging to to his introductory course, I sometimes use Python students. Unfortunately, there is a tendency for for these exact same reasons in advanced graduate introductory programming courses to focus far too level computer science courses at the University of much attention on mathematical abstraction and Chicago. In these courses, I am constantly faced for students to be come frustrated with annoying with the daunting task of covering a lot of dicult problems related to low-level details of syntax, course material in a blistering nine week quarter. compilation, and the enforcement of seemingly Although it is certainly possible for me to inict a lot arcane rules. Although such abstraction and of pain and suering by using a language like C++, I often found this approach to be formalism is important to professional software have engineers and students who plan to continue their counterproductive especially when the course is study of computer science, taking such an approach about a topic unrelated to just programming. I in an introductory course mostly succeeds in nd that using Python allows me to better focus on making computer science boring. When I teach a the actual topic at hand while allowing students to course, I dont want to have a room of uninspired complete substantial class pro jects. students. I would much rather see them trying to Although Python is still a young and solve interesting problems by exploring dierent evolving language, I believe that it has a bright ideas, taking unconventional approaches, breaking future in education. This book is an important step the rules, and learning from their mistakes. In doing in that direction. so, I dont want to waste half of the semester trying to sort out obscure syntax problems, unintelligible David Beazley compiler error messages, or the several hundred University of Chicago ways that a program might generate a general protection fault. Author of the Python Essential Reference

One of the reasons why I like Python is that it provides a really nice balance between the practical and the conceptual. Since Python is interpreted, beginners can pick up the language and start doing neat things almost immediately without getting lost in the problems of compilation and linking. Furthermore, Python comes with a large library of modules that can be used to do all sorts of tasks ranging from web-programming to graphics. Having such a practical focus is a great way to engage students and it allows them to complete significant pro jects. However, Python can also serve as an excellent foundation for introducing important computer science concepts. Since Python fully supports procedures and classes, students can be gradually introduced to topics such as procedural abstraction, data structures, and ob jectoriented programmingall of which are applicable to later courses on Java or C++. Python even borrows a number of features from functional programming languages and can be used to introduce concepts that would be covered in more detail in courses on Scheme and Lisp.

Foreword #6

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 ver completo este trabalho. Python uma linguagem de programao divertida e extremamente fcil de usar que tem ganho forte popularidade nestes ltimos poucos anos. Desenvolvida dez anos atrs por Guido van Rossun, a sintaxe simples do Python e seu sentido geral so grandemente derivados do ABC, uma linguagem didtica que foi desenvolvida nos anos 80. Entretanto, Python tambm foi criado para solucionar problemas reais e tomou emprestado uma grande quantidade de caractersticas de linguagens de programao como C++, Java, Modula-3 e Scheme. Por causa disso, uma das mais notveis caractersticas do Python o grande apelo que tem junto a desenvolvedores profissionais de software, cientistas, pesquisadores, artistas e educadores. A Despeito deste apelo do Python junto s mais variadas comunidades, voc pode ainda estar pensando ?por que Python?? ou ?por que ensinar programao com Python??. Responder estas perguntas no uma tarefa fcil ? especialmente se a opinio pblica est do lado de alternativas mais masoquistas como C++ e Java. Entretanto, eu acho que a resposta mais direta que programar com Python um bocado divertido e mais produtivo. Uma das razes pelas quais eu gosto de Python que ele oferece um equilbrio realmente bom entre o lado prtico e o lado conceitual. Sendo Python interpretado, os iniciantes podem pegar a linguagem e comear a fazer coisas legais quase imediatamente sem se perderem em problemas de compilao e ligao. Alm disso, Python vem com uma grande biblioteca de mdulos que podem ser utilizados para fazer todo tipo de tarefa, desde a programao para a web at grficos. Com tal enfoque prtico temos uma bela maneira de alcanar o engajamento dos alunos e permitir que eles finalizem projetos significativos. Entretanto, Python tambm pode servir de excelente embasamento para a introduo de conceitos importantes em cincia da computao. J que Python suporta plenamente procedimentos (procedures) e classes, os alunos podem ser gradualmente introduzidos a tpicos como abstrao procedural, estruturas de dados, e programao orientada a objetos ? todos aplicveis em cursos posteriores de Java ou C++. Python ainda toma emprestado certas caractersticas de linguagens de programao funcionais e pode ser usado para introduzir conceitos cujos detalhes poderiam ser aprofundados em cursos de Scheme e Lisp. Lendo o prefcio de Jeffrey, fiquei impressionado com seu comentrio de que Python o fez ver um ?maior nvel de sucesso e um menor nvel de frustrao? o que lhe permitiu ?progredir mais depressa com resultados melhores?. Embora estes comentrios refiram-se aos seus cursos introdutrios, eu s vezes uso Python exatamente pelas mesmas razes em cursos avanados de psgraduao em cincia da computao na Universidade de Chicago. Nestes cursos, enfrento constantemente a assustadora tarefa de cobrir muitos tpicos difceis em um rapidssimo trimestre de nove semanas. Embora me seja possvel inflingir um bocado de dor e sofrimento pelo uso de uma linguagem como C++, tenho percebido muitas vezes que este enfoque contraproducente ? especialmente quando o curso sobre um tpico no relacionado apenas com ?programar?. Acho que usar Python me permite um melhor foco no tpico em questo, enquanto permite que os alunos completem projetos substanciais em classe.

Quando ministro cursos de cincias da computao, o que desejo cobrir conceitos importantes alm de tornar a matria interessante e os alunos participativos. Infelizmente, existe uma tendncia entre os cursos introdutrios de programao a focar ateno demais em abstraes matemticas, e de frustrao entre os alunos com problemas enfadonhos e inoportunos relacionados a detalhes de sintaxe em baixo nvel, compilao e a imposio de regras que aparentemente s um expert pode compreender. Embora alguma abstrao e formalismo sejam importantes para engenheiros profissionais de software e estudantes que planejam continuar seus estudos em cincias da computao, escolher tal abordagem em um curso introdutrio faz da cincia da computao algo entediante. Quando ministro um curso, no desejo uma sala cheia de alunos sem inspirao. Em vez disso, preferiria muito mais v-los tentando solucionar problemas interessantes explorando idias diferentes, trilhando caminhos no Embora Python seja ainda uma convencionais, quebrando regras, e aprendendo a linguagem jovem e em evoluo, acredito que tem partir de seus erros. Fazendo assim, no pretendo um futuro brilhante em educao. Este livro um desperdiar metade de um semestre tentando passo importante nessa direo. explicar problemas obscuros de sintaxe, mensagens David Beazley ininteligveis de compiladores ou as vrias centenas de maneiras pelas quais um programa pode gerar Universidade de Chicago uma falha geral de proteo. Autor de Python Essencial Reference

Apresentao #7

Como pensar como um cientista da Computao usando Python

Preface

By Je Elkner This book owes its existence to the collaboration made possible by the Internet and the free software movement. Its three authorsa college professor, a high school teacher, and a professional programmerhave yet to meet face to face, but we have been able to work closely together and have been aided by many wonderful folks who have donated their time and energy to helping make this book better. We think this book is a testament to the benets and future possibilities of this kind of collaboration, the framework for which has been put in place by Richard Stallman and the Free Software Foundation.

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 accomplishment, combined with Matts positive assessment of Python, suggested that Python was the solution I was looking for.

Finding a textb o ok
Having decided to use Python in both of my introductory computer science classes the following year, the most pressing problem was the lack of an available textbook. Free content came to the rescue. Earlier in the year, Richard Stallman had introduced me to Allen Downey. Both of us had written to Richard expressing an interest in developing free educational content. Allen had already written a rst-year computer science textbook, How to Think Like a Computer Scientist. When I read this book, I knew immediately that I wanted to use it in my class. It was the clearest and most helpful computer science text I had seen. It emphasized the processes of thought involved in programming rather than the features of a particular language. Reading it immediately made me a better teacher. 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 modied to meet the needs of its user. Once I decided to use Python, it occurred to me that I could translate Allens original Java version of the book into the new language. While I would not have been able to write a textbook on my own, having Allens book to work from made it possible for me to do so, at the same time demonstrating that the cooperative development model used so well in software could also work for educational content.

How and why I came to use Python


In 1999, the College Boards Advanced Placement (AP) Computer Science exam was given in C++ for the rst time. As in many high schools throughout the country, the decision to change languages had a direct impact on the computer science curriculum at Yorktown High School in Arlington, Virginia, where I teach. Up to this point, Pascal was the language of instruction in both our rst-year and AP courses. In keeping with past practice of giving students two years of exposure to the same language, we made the decision to switch to C++ in the rst-year course for the 1997-98 school year so that we would be in step with the College Boards change for the AP course the following year.

Two years later, I was convinced that C+ + was a poor choice to use for introducing students to computer science. While it is certainly a very powerful programming language, it is also an extremely dicult language to learn and teach. I found myself constantly ghting with C++s dicult syntax and multiple ways of doing things, and I was losing many students unnecessarily as a result. Convinced there had to be a better language choice Working on this book for the last two for our rst-year class, I went looking for an years has been rewarding for both my students and alternative to C++. me, and my students played a big part in the process. Since I could make instant changes I needed a language that would run on whenever someone found a spelling error or the machines in our Linux lab as well as on the dicult passage, I encouraged them to look for Windows and Macintosh platforms most students mistakes in the book by giving them a bonus point have at home. I wanted it to be free and available each time they made a suggestion that resulted in a electronically, so that students could use it at home change in the text. This had the double benet of regardless of their income. I wanted a language that encouraging them to read the text more carefully was used by professional programmers, and one and of getting the text thoroughly reviewed by its that had an active developer community around it. most important critics, students using it to learn It had to support both procedural and ob ject- computer science. oriented programming. And most importantly, it had to be easy to learn and teach. When I For the second half of the book on ob investigated the choices with these goals in mind, ject-oriented programming, I knew that someone Python stood out as the best candidate for the job. with more real programming experience than I had would be needed to do it right. The book sat in an I asked one of Yorktowns talented unnished state for the better part of a year until students, Matt Ahrens, to give Python a try. In two the free software community once again provided months he not only learned the language but wrote the needed means for its completion. Preface #8

Como pensar como um cientista da Computao usando Python I received an email from Chris Meyers expressing interest in the book. Chris is a professional programmer who started teaching a programming course last year using Python at Lane Community College in Eugene, Oregon. The prospect of teaching the course had led Chris to the book, and he started helping out with it immediately. By the end of the school year he had created a companion project on our Website at http://www.ibiblio.org/obp called Python for Fun and was working with some of my most advanced students as a master teacher, guiding them beyond where I could take them. Using a very high-level language like Python allows a teacher to postpone talking about low-level details of the machine until students have the background that they need to better make sense of the details. It thus creates the ability to put rst things rst pedagogically. One of the best examples of this is the way in which Python handles variables. In C++ a variable is a name for a place that holds a thing. Variables have to be declared with types at least in part because the size of the place to which they refer needs to be predetermined. Thus, the idea of a variable is bound up with the hardware of the machine. The powerful and fundamental concept of a variable is already dicult enough for beginning students (in both computer science and algebra). Bytes and addresses do 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 students and is much closer to the meaning of variable that they learned in their math courses. I had much less diculty teaching variables this year than I did in the past, and I spent less time helping students with problems using them.

Intro ducing programming with Python


The process of translating and using How to Think Like a 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.

Another example of how Python aids in The rst example from the text illustrates this point. It is the traditional hello, the teaching and learning of programming is in its world program, which in the C++ version of the syntax for functions. My students have always had a great deal of diculty understanding functions. book looks like this: The main problem centers around the dierence #include <iostream.h> between a function denition and a function call, and the related distinction between a parameter void main() and an argument. Python comes to the rescue with { syntax that is nothing short of beautiful. Function cout << "Hello, world." << endl; denitions begin with the keyword def, so I simply } tell my students, When you dene a function, begin in the Python version it becomes: with def, followed by the name of the function that you are dening; when you call a function, simply print "Hello, World!" call (type) out its name. Parameters go with Even though this is a trivial example, denitions; arguments go with calls. There are no the advantages of Python stand out. Yorktowns return types, parameter types, or reference and Computer Science I course has no prerequisites, so value parameters to get in the way, so I am now many of the students seeing this example are able to teach functions in less than half the time looking at their rst program. Some of them are that it previously took me, with better undoubtedly a little nervous, having heard that comprehension. computer programming is dicult to learn. The C++ Using Python has improved the version has always forced me to choose between two unsatisfying options: either to explain the eectiveness of our computer science program for #include, void main(), {, and } statements and risk all students. I see a higher general level of success confusing or intimidating some of the students right and a lower level of frustration than I experienced at the start, or to tell them, Just dont worry about during the two years I taught C++. I move faster all of that stu now; we will talk about it later, and with better results. More students leave the course risk the same thing. The educational ob jectives at with the ability to create meaningful programs and this point in the course are to introduce students to with the positive attitude toward the experience of the idea of a programming statement and to get programming that this engenders. them to write their rst program, thereby introducing them to the programming environment. The Python program has exactly what is needed to Building a community do these things, and nothing more. Comparing the explanatory text of the program 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 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 found this same thing happening throughout the book. Whole paragraphs simply disappear from the Python version of the text because Pythons much clearer syntax renders them unnecessary. I have received email from all over the globe from people using this book to learn or to teach programming. A user community has begun to emerge, and many people have been contributing to the pro ject by sending in materials for the companion Website at http://www.thinkpython.com. With the publication of the book in print form, I expect the growth in the user community to continue and accelerate. The emergence of this user community and the possibility it suggests for similar collaboration among educators have been the most

Preface #9

Como pensar como um cientista da Computao usando Python exciting parts of working on this pro ject for me. By working together, we can increase the quality of materials available for our use and save valuable time. I invite you to join our community and look forward to hearing from you. Please write to the authors at feedback@thinkpython.com. Jerey Elkner Yorktown High School Arlington, Virginia

Preface #10

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 autores ? um professor universitrio, um secundrio e um programador profissional ? ainda no se encontraram pessoalmente, mas temos podido trabalhar bem de perto e temos sido ajudados por muitos colegas maravilhosos que tm dedicado seu tempo e energia a ajudar a fazer deste um livro cada vez melhor. Achamos que este livro um testemunho dos benefcios e possibilidades futuras deste tipo de colaborao, cujo modelo tem sido colocado por Richard Stallman e pela Free Software Foundation. importante, deveria ser fcil de aprender e de ensinar. Quando considerei as alternativas tendo em mente aquelas metas, Python sobressaiu-se como a melhor candidata para a tarefa. Pedi para um dos talentosos estudantes de Yorktown, Matt Ahrens, que experimentasse Python. Em dois meses ele no s aprendeu a linguagem como tambm escreveu uma aplicao chamada pyTicket que possibilitou nossa equipe reportar problemas de tecnologia pela Web. Eu sabia que Matt no poderia ter finalizado uma aplicao 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.

Como e porque eu vim a usar Python


Em 1999, o Exame de Colocao Avanada em Cincia da Computao da Comisso de Faculdades (College Board?s Advanced Placement (AP) Computer Science) foi aplicado em C++ pela primeira vez. Como em muitas escolas secundrias atravs do pas, a deciso de mudar linguagens teve um impacto direto no currculo de cincia da computao na Yorktown High School em Arlington, Virginia, onde leciono. At ento, Pascal era a linguagem didtica para nossos cursos de primeiro ano e avanado. Mantendo a prtica corrente de dar aos estudantes dois anos de exposio mesma linguagem, tomamos a deciso de mudar para C++ no curso de primeiro ano para o ano letivo de 1997-98 de modo que estaramos em sincronismo com a mudana da Comisso de Faculdades (College Board?s) em relao ao curso avanado para o ano seguinte.

Encontrando um livro texto


Tendo decidido usar Python em ambas as minhas classes introdutrias de cincia da computao do ano seguinte, o problema mais urgente era a falta de um livro texto disponvel.

O contedo livre veio em socorro. Anteriormente naquele ano, Richard Stallman tinha me apresentado a Allen Downey. Ambos havamos escrito a Richard expressando interesse em desenvolver contedo educacional livre. Allen j tinha escrito um livro texto para o 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 enfatizava o processo de reflexo envolvido em programao em vez de caractersticas de uma linguagem em Dois anos depois, eu estava convencido particular. L-lo fez de mim imediatamente um que C++ foi uma escolha infeliz para introduzir os melhor professor. alunos em cincia da computao. Ao mesmo tempo O How to Think Like a Computer em que certamente uma linguagem de programao muito poderosa, tambm uma Scientist era no s um excelente livro, como linguagem extremamente difcil de aprender e de tambm fora lanado sob uma licena pblica GNU, ensinar. Eu me encontrava constantemente lutando o que significava que ele poderia ser usado com a sintaxe difcil do C++ e as mltiplas maneiras livremente e modificado para atender as de fazer a mesma coisa, e estava, como resultado, necessidades de seu usurio. Uma vez que eu havia perdendo muitos alunos desnecessariamente. decidido usar Python, me ocorreu que eu poderia Convencido de que deveria existir uma linguagem traduzir a verso original do livro de Allen do Java melhor para a nossa classe de primeiro ano, fui para a nova linguagem. Apesar de no estar capacitado para escrever eu mesmo um livro texto, procurar por uma alternativa ao C++. tendo o livro de Allen a partir do qual trabalhar Eu precisava de uma linguagem que tornou possvel para mim faz-lo, ao mesmo tempo pudesse rodar nas mquinas em nosso laboratrio demonstrando que o modelo de desenvolvimento Linux bem como nas plataformas Windows e cooperativo to bem utilizado em software poderia Macintosh que a maioria dos alunos tinha em casa. tambm funcionar para contedo educacional. Eu precisava que ela fosse gratuita e disponvel Trabalhar neste livro pelos ltimos dois eletronicamente, assim os alunos poderiam utilizla em casa independentemente de suas rendas. Eu anos tem sido recompensador para mim e meus queria uma linguagem que fosse utilizada por alunos, e eles tiveram um grande papel neste programadores profissionais, e que tivesse uma processo. A partir do momento em que eu podia comunidade de desenvolvimento ativa em torno fazer mudanas instantneas assim que algum dela. Ela teria que suportar ambas, programao encontrasse um erro ortogrfico ou um trecho procedural e orientada a objetos. E, mais difcil, eu os encorajei a procurar por erros no livro, Prefcio #11

Como pensar como um cientista da Computao usando Python dando a eles pontos de bonificao cada vez que eles fizessem uma sugesto que resultasse em uma mudana no texto. Isto teve o duplo benefcio de encoraj-los a ler o texto mais cuidadosamente e de ter o texto totalmente revisado por seus crticos mais importantes: alunos utilizando-o para aprender cincia da computao. Para a segunda metade do livro, sobre programao orientada a objetos, eu sabia que seria preciso algum com uma maior experincia do que a minha em programao real para faz-lo corretamente. O livro esteve em estado inacabado por quase um ano at que a comunidade de software livre providenciasse mais uma vez os meios necessrios para sua concluso. Eu recebi um e-mail de Chris Meyers mostrando interesse no livro. Chris um programador profissional que comeou a dar um curso de programao no ano anterior usando Python no Lane Community College em Eugene, Oregon. A perspectiva de dar aquele curso ligou Chris ao livro, e ele comeou a ajudar o trabalho imediatamente. Pelo final do ano letivo ele tinha criado um projeto colaborativo em nosso Website em http://www.ibiblio.org/obp chamado Python for Fun e estava trabalhando com alguns dos meus alunos mais avanados como um guru, guiando-os alm de onde eu poderia lev-los. programa, deste modo introduzindo-os ao ambiente de programao. O programa em Python tem exatamente o que necessrio para conseguir isto, e nada mais. Comparar o texto explicativo do programa em cada verso do livro ilustra ainda mais o que significa para o aluno iniciante. Existem treze pargrafos de explicao do ?Al, mundo!? na verso C++; na verso Python existem apenas dois. Mais importante, os onze pargrafos perdidos no se ocupam das ?idias chave? da programao de computadores, mas com a mincia da sintaxe C++. Vejo a mesma coisa acontecendo atravs de todo o livro. Pargrafos inteiros simplesmente desaparecem da verso do texto para Python porque a sintaxe muito mais clara do Python os torna desnecessrios. Utilizar uma linguagem de to alto nvel como Python, permite ao professor deixar para falar mais tarde sobre os nveis mais baixos, prximos mquina, quando os alunos j tero a experincia necessria para ver com mais sentido os detalhes. Desta maneira podemos ?por em primeiro lugar as primeiras coisas?, pedagogicamente. Um dos melhores exemplos disto a maneira com que Python lida com variveis. Em C++ uma varivel um nome para um lugar que guarda uma coisa. Variveis tm de ser declaradas com seu tipo pelo menos em parte por que o tamanho do lugar a que se referem precisa ser predeterminado. Assim, a idia de varivel fica amarrada ao hardware da mquina. O conceito poderoso e fundamental de varivel j bastante difcil para o aluno iniciante (em ambas, cincia da computao e lgebra). Bytes e endereos no ajudam neste caso. Em Python uma varivel um nome que se refere a uma coisa. Este um conceito muito mais intuitivo para alunos iniciantes e est muito mais prximo do significado de ?varivel? que eles aprenderam em seus cursos de matemtica. Eu tive muito menos dificuldade em ensinar variveis este ano do que tive no passado, e gastei menos tempo ajudando aos alunos com problemas no uso delas. Um outro exemplo de como Python ajuda no ensino e aprendizagem de programao em sua sintaxe para funo. Meus alunos tm sempre tido grande dificuldade na compreenso de funes. O problema principal gira em torno da diferena entre a definio de uma funo e a chamada de 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 com def, ento eu simplesmente digo aos meus alunos ? Quando voc define uma funo, comece com def, seguido do nome da funo que voc est definindo; quando voc chama uma funo, simplesmente chame-a digitando o nome dela?. Parmetros ficam nas definies; argumentos vo com as chamadas. No existem tipos de retorno, tipos de parmetro ou passagem de parmetros por valor ou por referncia no meio do caminho, permitindo-me ensinar funes em menos da metade do tempo que isto me tomava anteriormente, com uma melhor compreenso.

Introduzindo programao com Python


O processo de traduzir e utilizar How to Think Like a Computer Scientist pelos ltimos dois anos tem confirmado a convenincia de Python no ensino de alunos iniciantes. Python simplifica tremendamente os programas exemplo e torna idias importantes de programao mais fceis de ensinar. O primeiro exemplo do texto ilustra este ponto. o tradicional programa ?Al mundo?, do qual na verso C++ do livro se parece com isto:
#include <iostream.h> void main() { cout << "Al, mundo." << endl; }

Na verso Python, ele se transforma em:


print "Al, Mundo!"

Mesmo sendo um exemplo trivial, as vantagens do Python saltam aos olhos. O curso de Cincia da Computao I que ministro em Yorktown no tem pr-requisitos, assim, muitos dos alunos que veem esse exemplo esto olhando para o seu primeiro programa. Alguns deles esto indubitavelmente nervosos, por j terem ouvido falar que programao de computadores difcil de aprender. A verso C++ tem sempre me forado a escolher entre duas opes insatisfatrias: ou explicar os comandos #include, void main(), {, e } e arriscar confundir ou intimidar alguns dos alunos logo assim que iniciam, ou dizer a eles ?No se preocupem com todas estas coisas agora; falaremos A utilizao do Python tem melhorado a sobre elas mais tarde?, e correr o mesmo risco. O objetivo educacional neste ponto do curso efetividade de nosso programa em cincia da introduzir os alunos idia de comando em computao para todos os estudantes. Eu vejo um programao e v-los escrever seu primeiro nvel geral de sucesso muito mais alto e um nvel Prefcio #12

Como pensar como um cientista da Computao usando Python mais baixo de frustrao do que experimentei durante os dois anos em que ensinei C++. Eu avano mais rpido com melhores resultados. Mais alunos deixam o curso com a habilidade de criar programas significativos e com uma atitude positiva em relao a experincia de programao que isso traz. http://www.thinkpython.com

Com a publicao do livro em formato impresso, minha expectativa quanto ao crescimento da comunidade de usurios que ela seja contnua e acelerada. O surgimento desta comunidade de usurios e a possibilidade que sugere de colaborao semelhante entre educadores tem sido para mim a parte mais excitante do trabalho neste projeto. Trabalhando juntos, podemos aumentar a Construindo uma comunidade qualidade do material disponvel para o nosso uso e poupar tempo valioso. Eu convido voc a se juntar a comunidade e espero ouvir algo de voc. Por Tenho recebido e-mails de todo o planeta de pessoas nossa favor, escreva para os autores em utilizando este livro para aprender ou ensinar feedback@thinkpython.com. programao. Uma comunidade de usurios tem comeado a emergir e muitas pessoas tm Jeffrey Elkner contribudo com o projeto enviando seus materiais Yorktown High School para o Website cooperativo em: Arlington, Virginia

Prefcio #13

Como pensar como um cientista da Computao usando Python

Contributor List

To paraphrase the philosophy of the Free Software Foundation, this book is free like free speech, but not necessarily free like free pizza. It came about because of a collaboration that would not have been possible without the GNU Free Documentation License. So we thank the Free Software Foundation for developing this license and, of course, making it available to us. We also thank the more than 100 sharpeyed and thoughtful readers who have sent us suggestions and corrections over the past few years. In the spirit of free software, we decided to express our gratitude in the form of a contributor list. Unfortunately, this list is not complete, but we are doing our best to keep it up to date. If you have a chance to look through the list, you should realize that each person here has spared you and all subsequent readers from the confusion of a technical error or a less-thantransparent explanation, just by sending us a note. Impossible as it may seem after so many corrections, there may still be errors in this book. If you should stumble across one, please check the online version of the book at http://thinkpython.com, which is the most up-todate version. If the error has not been corrected, please take a minute to send us email at feedback@thinkpython.com. If we make a change due to your suggestion, you will appear in the next version of the contributor list (unless you ask to be omitted). Thank you!

David Kershaw xed the broken catTwice function in Section 3.10. Eddie Lam has sent in numerous corrections to Chapters 1, 2, and 3. He also xed the Makele so that it creates an index the rst time it is run and helped us set up a versioning scheme. Man-Yong Lee sent in a correction to the example code in Section 2.4. David Mayo pointed out that the word unconsciously in Chapter 1 needed to be changed to subconsciously. Chris McAloon sent in several corrections to Sections 3.9 and 3.10. Matthew J. Moelter has been a long-time contributor who sent in numerous corrections and suggestions to the book. Simon Dicon Montford reported a missing function denition and several typos in Chapter 3. He also found errors in the increment function in Chapter 13. John Ouzts corrected the return value in Chapter 3. denition of

Kevin Parks sent in valuable comments and suggestions as to how to improve the distribution of the book. David Pool sent in a typo in the glossary of Chapter 1, as well as kind words of encouragement. Michael Schmitt sent in a correction to the chapter on les and exceptions. Robin Shaw pointed out an error in Section 13.1, where the printTime function was used in an example without being dened. Paul Sleigh found an error in Chapter 7 and a bug in Jonah Cohens Perlscript that generates HTML from LaTeX. Craig T. Snydal is testing the text in a course at Drew University. He has contributed several valuable suggestions and corrections. Ian Thomas and his students are using the text in a programming course. They are the rst ones to test the chapters in the latter half of the book, and they have made numerous corrections and suggestions. Keith Verheyden sent in a correction in Chapter 3. Peter Winstanley let us know about a longstanding error in our Latin in Chapter 3. Chris Wrobel made corrections to the code in the chapter on le I/O and exceptions.

Lloyd Hugh Allen sent in a correction to Section 8.4. Yvon Boulianne sent in a correction of a semantic error in Chapter 5. Fred Bremmer submitted a correction in Section 2.1. Jonah Cohen wrote the Perl scripts to convert the LaTeX source for this book into beautiful HTML. Michael Conlon sent in a grammar correction in Chapter 2 and an improvement in style in Chapter 1, and he initiated discussion on the technical aspects of interpreters. Benoit Girard sent in a correction to a humorous mistake in Section 5.6. Courtney Gleason and Katherine Smith wrote horsebet.py, which was used as a case study in an earlier version of the book. Their program can now be found on the website. Lee Harr submitted more corrections than we have room to list here, and indeed he should be listed as one of the principal editors of the text. James Kaylin is a student using the text. He has submitted numerous corrections.

Contributor List #14

Como pensar como um cientista da Computao usando Python

Moshe Zadka has made invaluable contributions to this pro ject. In addition to writing the rst draft of the chapter on Dictionaries, he provided continual guidance in the early stages of the book. Christoph Zwerschke sent several corrections and pedagogic suggestions, and explained the dierence between gleich and selbe. James Mayer sent us a whole slew of spelling and typographical errors, including two in the contributor list. Hayden McAfee caught confusing inconsistency examples. a potentially between two

D. J. Webre suggested a clarication in Chapter 3. Ken found a stful of errors in Chapters 8, 9 and 11. Ivo Wever caught a typo in Chapter 5 and suggested a clarication in Chapter 3. Curtis Yanko suggested a clarication in Chapter 2. Ben Logan sent in a number of typos and problems with translating the book into HTML. Jason Armstrong saw the missing word in Chapter 2. Louis Cordier noticed a spot in Chapter 16 where the code didnt match the text. Brian Cain suggested several clarications in Chapters 2 and 3. Rob Black sent in a passel of corrections, including some changes for Python 2.2. Jean-Philippe Rey at Ecole Centrale Paris sent a number of patches, including some updates for Python 2.2 and other thoughtful improvements. Jason Mader at George Washington University made a number of useful suggestions and corrections. Jan Gundtofte-Bruun reminded us that a error is an error. Abel David and Alexis Dinno reminded us that the plural of matrix is matrices, not matrixes. This error was in the book for years, but two readers with the same initials reported it on the same day. Weird. Charles Thayer encouraged us to get rid of the semi-colons we had put at the ends of some statements and to clean up our use of argument and parameter. Roger Sperberg pointed out a twisted piece of logic in Chapter 3.

Angel Arnal is part of an international team of translators working on the Spanish version of the text. He has also found several errors in the English version. Tauhidul Hoque and Lex Berezhny created the illustrations in Chapter 1 and improved many of the other illustrations. Dr. Michele Alzetta caught an error in Chapter 8 and sent some interesting pedagogic comments and suggestions about Fibonacci and Old Maid. Andy Mitchell caught a typo in Chapter 1 and a broken example in Chapter 2. Kalin Harvey suggested a clarication in Chapter 7 and caught some typos. Christopher P. Smith caught several typos and is helping us prepare to update the book for Python 2.2. David Hutchins Foreword. caught a typo in the

Gregor Lingl is teaching Python at a high school in Vienna, Austria. He is working on a German translation of the book, and he caught a couple of bad errors in Chapter 5. Julie Peters caught a typo in the Preface. Florin Oprina sent in an improvement in makeTime, a correction in printTime, and a nice typo.

Contributor List #15

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 (claudio) 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 #16

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 observam o comportamento de sistemas complexos, formulam hipteses e testam previses.

para rodar em outro tipo. Devido a essas vantagens, quase todos os programas so escritos em linguagens de alto nvel. As de baixo nvel so utilizadas somente para umas poucas aplicaes especializadas.

Dois tipos de programas processam linguagens de alto nvel, traduzindo-as em linguagens de baixo nvel: interpretadores e compiladores. O interpretador l um programa escrito em linguagem de alto nvel e o executa, ou seja, faz o que o programa diz. Ele processa o programa um pouco de cada vez, alternadamente: A habilidade mais importante de um ora lendo algumas linhas, ora realizando cientista da computao a soluo de problemas. computaes. Soluo de problemas a habilidade de formular questes, pensar criativamente sobre solues possveis e expressar uma soluo de forma clara e precisa. Ocorre que aprender a programar uma excelente oportunidade de praticar 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 um objetivo. medida que voc for avanando na leitura, esse objetivo ficar mais claro. O compilador l o programa e o traduz completamente antes que o programa comece a rodar. Neste caso, o programa escrito em linguagem de alto nvel chamado de cdigo fonte, e o programa traduzido chamado de cdigo objeto ou executvel. Uma vez que um programa compilado, voc pode execut-lo repetidamente, sem que precise de nova traduo.

1.1 A linguagem de programao Python


Python a linguagem de programao que voc vai estudar neste livro. Python um exemplo de linguagem de programao de alto nvel ; outras linguagens de alto nvel de que voc j pode ter ouvido falar so C, C++, Perl e Java. Como voc pode deduzir a partir da expresso "linguagem de alto nvel", tambm existem as "linguagens de baixo nvel", s vezes chamadas de "linguagens de mquina" ou "linguagem assembly" ("linguagens de montagem"). Dito de maneira simples, o computador s consegue executar programas escritos em linguagens de baixo nvel. Deste modo, programas escritos em linguagens de alto nvel precisam ser processados antes que possam rodar. Esse processamento extra toma algum tempo, o que uma pequena desvantagem em relao s linguagens de alto nvel. Mas as vantagens so enormes. Primeiro, muito mais fcil programar em uma linguagem de alto nvel. mais rpido escrever programas em uma linguagem de alto nvel; eles so mais curtos e mais fceis de ler e mais provvel que estejam corretos. Segundo, as linguagens de alto nvel so portveis, o que significa que podem rodar em diferentes tipos de computador, com pouca ou nenhuma modificao. Programas em baixo nvel s podem rodar em um nico tipo de computador e precisam ser re-escritos

Python considerada uma linguagem interpretada, porque os programas em Python so executados 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:
$ python Python 2.4.3 (#2, Oct 6 2006, 07:49:22) [GCC 4.0.3 (Ubuntu 4.0.3-1ubuntu5)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> print 1 + 1 2

A primeira linha deste exemplo o comando que inicia o interpretador Python. As trs linhas seguintes so mensagens do interpretador. A quarta linha comea com >>>, que o sinal usado pelo interpretador para indicar que ele est pronto. No exemplo anterior, digitamos print 1 + 1 e o interpretador respondeu 2. Voc tambm pode escrever um programa em um arquivo e usar o interpretador para executar o contedo desse arquivo. Um

Captulo 1: O caminho do programa #17

Como pensar como um cientista da Computao usando Python arquivo como este chamado de script. Por sejam simples o suficiente para serem executadas exemplo, usamos um editor de texto para criar um com uma dessas instrues bsicas. arquivo chamado leticia.py com o seguinte Isso pode parecer um pouco vago, mas contedo: vamos voltar a esse tpico mais adiante, quando print 1 + 1 falarmos sobre algoritmos. Por conveno, arquivos que contenham programas em Python tm nomes que terminam com .py. 1.3 O que depurao (debugging)? Para executar o programa, temos de dizer ao interpretador o nome do script: Programar um processo complicado e, como feito por seres humanos, freqentemente conduz a $ python leticia.py erros. Por mero capricho, erros em programas so 2 chamados de bugs e o processo de encontr-los e Em outros ambientes de corrigi-los chamado de depurao (debugging). desenvolvimento, os detalhes da execuo de Trs tipos de erro podem acontecer em programas podem ser diferentes. Alm disso, a maioria dos programas so mais interessantes do um programa: erros de sintaxe, erros em tempo de execuo (runtime errors) e erros de semntica. que esse... Distinguir os trs tipos ajuda a localiz-los mais A maioria dos exemplos neste livro so rpido: executados a partir da linha de comando. Trabalhar com a linha de comando conveniente 1.3.1 Erros de sintaxe no desenvolvimento e testagem de programas, porque voc pode digitar os programas e execut- Python s executa um programa se ele estiver los imediatamente. Uma vez que voc tem um sintaticamente correto; caso contrrio, o processo programa que funciona, deve guard-lo em um falha e retorna uma mensagem de erro. Sintaxe se script, de forma a poder execut-lo ou modific-lo refere estrutura de um programa e s regras no futuro. sobre esta estrutura. Por exemplo, em portugus, uma frase deve comear com uma letra maiscula e terminar com um ponto.

1.2 O que um programa?

Um programa uma seqncia de instrues que especificam como executar uma computao. A computao pode ser algo matemtico, como solucionar um sistema de equaes ou encontrar as razes de um polinmio, mas tambm pode ser uma computao simblica, como buscar e substituir uma palavra em um documento ou (estranhamente) compilar um programa.

esta frase contm um erro de sintaxe. Assim como esta

Para a maioria dos leitores, uns errinhos de sintaxe no chegam a ser um problema significativo e por isso que conseguimos ler a poesia moderna de e. e. cummings sem cuspir mensagens de erro. Python no to indulgente. Se o seu programa tiver um nico erro de sintaxe em algum lugar, o interpretador Python vai exibir uma mensagem de erro e vai terminar - e o programa Os detalhes so diferentes em diferentes no vai rodar. Durante as primeiras semanas da carreira como programador, voc linguagens, mas algumas instrues bsicas sua provavelmente perder um bocado de tempo aparecem em praticamente todas as linguagens: procurando erros de sintaxe. Conforme for entrar Pegar dados do teclado, de um ganhando experincia, entretanto, cometer menos arquivo ou de algum outro erros e os localizar mais rpido. dispositivo. sair Mostrar dados na tela ou enviar 1.3.2 Erros em tempo de execuo (runtime dados para um arquivo ou outro errors) dispositivo. O segundo tipo de erro o erro de runtime, ou erro calcular Executar operaes matemticas em tempo de execuo, assim chamado porque s bsicas, como adio e aparece quando voc roda o programa. Esses erros multiplicao. so tambm conhecidos como excees, porque indicam que alguma coisa executar Checar certas condies e normalmente condicionalme executar a seqncia apropriada excepcional (e ruim) aconteceu. nte de instrues. Erros de runtime so raros nos programas simples que voc vai ver nos primeiros alguma ao repetir Executar repetidamente, normalmente captulos - ento, vai demorar um pouco at voc se deparar com um erro desse tipo. com alguma variao. Acredite se quiser: isso praticamente tudo. Todos os programas que voc j usou, no importa quo complicados, so feitos de instrues mais ou menos parecidas com essas. Assim, poderamos definir programao como o processo de dividir uma tarefa grande e complexa em subtarefas cada vez menores, at que as sub-tarefas 1.3.3 Erros de semntica O terceiro tipo de erro o erro de semntica (mais comumente chamado erro de lgica). Mesmo que o seu programa tenha um erro de semntica, ele vai rodar com sucesso, no sentido de que o computador

Captulo 1: O caminho do programa #18

Como pensar como um cientista da Computao usando Python no vai gerar nenhuma mensagem de erro. S que Linguagens formais so linguagens o programa no vai fazer a coisa certa, vai fazer que foram projetadas por pessoas, para aplicaes alguma outra coisa. Especificamente, aquilo que especficas. Por exemplo, a notao que os voc tiver dito para ele fazer. matemticos usam uma linguagem formal, que particularmente boa em denotar relaes entre O problema que o programa que voc nmeros e smbolos. Os qumicos usam uma escreveu no aquele que voc queria escrever. O linguagem formal para representar a estrutura significado do programa (sua semntica ou lgica) qumica das molculas. E, mais importante: est errado. Identificar erros semnticos pode ser complicado, porque requer que voc trabalhe de Linguagens de programao so trs para frente, olhando a sada do programa e linguagens formais que foram desenvolvidas para tentando imaginar o que ele est fazendo. expressar computaes. As linguagens formais tendem a ter regras estritas quanto sintaxe. Por exemplo, 3 + 3 = 6 uma expresso matemtica sintaticamente Uma das habilidades mais importantes que voc vai correta, mas 3=+6$ no . H2O um nome qumico adquirir a de depurar. Embora possa ser sintaticamente correto, mas 2Zz no . frustrante, depurar uma das partes intelectualmente mais ricas, desafiadoras e As regras de sintaxe so de dois tipos, interessantes da programao. um relacionado aos tokens, outro estrutura. "Tokens" so os elementos bsicos da linguagem, De certa maneira, a depurao como como as palavras, nmeros, e elementos qumicos. um trabalho de detetive. Voc se depara com pistas, Um dos problemas com 3=+6$ que $ no um e tem que deduzir os processos e eventos que token vlido em linguagem matemtica (pelo levaram aos resultados que aparecem. menos at onde sabemos). Do mesmo modo, 2Zz Depurar tambm como uma cincia invlida porque no existe nenhum elemento cuja experimental. Uma vez que voc tem uma idia do abreviatura seja Zz. que est errado, voc modifica o seu programa e O segundo tipo de erro de sintaxe est tenta de novo. Se a sua hiptese estava correta, relacionado estrutura de uma expresso -- quer ento voc consegue prever o resultado da dizer, ao modo como os tokens esto arrumados. A modificao e fica um passo mais perto de um expresso 3=+6$ estruturalmente invlida, porque programa que funciona. Se a sua hiptese estava voc no pode colocar um sinal de "mais" errada, voc tem que tentar uma nova. Como imediatamente aps um sinal de "igual". Do mesmo Sherlock Holmes mostrou, "Quando voc tiver modo, frmulas moleculares devem ter ndices eliminado o impossvel, aquilo que restou, ainda subscritos colocados depois do nome do elemento, que improvvel, deve ser a verdade." (Arthur no antes. Conan Doyle, O signo dos quatro). Faa este exerccio: crie o que parea Para algumas pessoas, programao e ser uma frase bem estruturada em portugus com depurao so a mesma coisa. Ou seja, programar "tokens" irreconhecveis dentro dela. Depois o processo de gradualmente depurar um programa, escreva outra frase com todos os "tokens" vlidos, at que ele faa o que voc quer. A idia comear mas com uma estrutura invlida. com um programa que faa alguma coisa e ir fazendo pequenas modificaes, depurando-as Quando voc l uma frase em portugus conforme avana, de modo que voc tenha sempre ou uma expresso em uma linguagem formal, voc um programa que funciona. tem de imaginar como a estrutura da frase (embora, em uma linguagem natural, voc faa isso Por exemplo, o Linux um sistema inconscientemente). Este processo chamado operacional que contm milhares de linhas de parsing (anlise sinttica). cdigo, mas comeou como um programa simples, que Linus Torvalds usou para explorar o chip Intel Por exemplo, quando voc ouve a frase, 80386. De acordo com Larry Greenfield, "Um dos "Caiu a ficha", entende que "a ficha" o sujeito e primeiros projetos de Linus Torvalds foi um "caiu" o verbo. Uma vez que voc analisou a frase, programa que deveria alternar entre imprimir consegue entender o seu significado, ou a semntica AAAA e BBBB. Isso depois evoluiu at o Linux". (The da frase. Assumindo que voc saiba o que uma Linux User's Guide Verso Beta 1) ficha e o que significa cair, voc entender o sentido geral dessa frase. Captulos posteriores faro mais sugestes sobre depurao e outras prticas de Muito embora as linguagens formais e programao. as naturais tenham muitas caractersticas em comum -- tokens, estrutura, sintaxe e semntica -existem muitas diferenas: 1.3.4 Depurao experimental (Debugging)

1.4 Linguagens naturais e linguagens formais


Linguagens naturais so as linguagens que as pessoas falam, como o portugus, o ingls e o espanhol. Elas no foram projetadas pelas pessoas (muito embora as pessoas tentem colocar alguma ordem nelas); elas evoluram naturalmente.

ambigida As linguagens naturais esto cheias de de ambigidades, que as pessoas contornam usando pistas contextuais e outras informaes. J as linguagens formais so desenvolvidas para serem quase ou totalmente desprovidas de ambigidade, o que significa que qualquer expresso tem precisamente s um sentido, independentemente do contexto.

Captulo 1: O caminho do programa #19

Como pensar como um cientista da Computao usando Python redundnc Para compensar a ambigidade e ia reduzir mal-entendidos, emprega-se muita redundncia nas linguagens naturais, o que freqentemente as torna prolixas. As linguagens formais so menos redundantes e mais concisas. literalidad As linguagens naturais esto cheias expresses idiomticas e e de metforas. Se eu digo "Caiu a ficha", possvel que no exista ficha nenhuma, nem nada que tenha cado. Nas linguagens formais, no h sentido ambguo. Pessoas que crescem falando uma linguagem natural -- ou seja, todo mundo - muitas vezes tm dificuldade de se acostumar com uma linguagem formal. De certa maneira, a diferena entre linguagens formais e naturais como a diferena entre poesia e prosa, porm mais acentuada: poesia As palavras so usadas pela sua sonoridade, alm de seus sentidos, e o poema como um todo cria um efeito ou uma reao emocional. A ambigidade no apenas freqente, mas na maioria das vezes, proposital. prosa O sentido literal das palavras mais importante, e a estrutura contribui mais para o significado. A prosa mais fcil de analisar do que a poesia, mas ainda muitas vezes ambgua. program O significado de um programa de as computador exato e literal, e pode ser inteiramente entendido pela anlise de seus tokens e de sua estrutura. Aqui vo algumas sugestes para a leitura de programas (e de outras linguagens formais). Primeiro, lembre-se de que linguagens formais so muito mais densas do que linguagens naturais, por isso, mais demorado l-las. A estrutura, tambm, muito importante, logo, geralmente no uma boa idia ler de cima para baixo, da esquerda para a direita. Em vez disso, aprenda a analisar o programa na sua cabea, identificando os tokens e interpretando a estrutura. Finalmente, os detalhes so importantes. Pequenas coisas, como, erros ortogrficos e m pontuao, com as quais voc pode se safar nas linguagens naturais, podem fazer uma grande diferena em uma linguagem formal.
Al, Mundo!

As aspas no programa marcam o comeo e o fim do valor; elas no aparecem no resultado final. Algumas pessoas julgam a qualidade de uma linguagem de programao pela simplicidade do programa "Al, Mundo!". Por esse padro, Python se sai to bem quanto possvel.

1.6 Glossrio
soluo de O processo de formular um problemas problema, encontrar uma soluo (problem e expressar esta soluo. solving) linguagem de alto nvel (high-level language) linguagem de baixo nvel (low-level language) Uma linguagem de programao como Python: projetada para ser fcil para os seres humanos a utilizarem. Uma linguagem de programao que concebida para ser fcil para um computador, tal como a linguagem de mquina ou a linguagem montagem (assembly language)

portabilidade Propriedade que um programa (portability) tem, de rodar em mais de um tipo de computador. interpretar Executar um programa escrito em (interpret) uma linguagem de alto nvel, traduzindo-o uma linha de cada vez. compilar Traduzir todo um programa (compile) escrito em uma linguagem de alto nvel para uma de baixo nvel de um s vez, em preparao para uma execuo posterior. cdigo fonte Um programa em uma linguagem (source code) de alto nvel, antes de ter sido compilado. cdigo objeto A sada do compilador, depois que (object code) ele traduziu o programa. executvel Um outro nome para cdigo (executable) objeto que est pronto para ser executado. script Um programa guardado em um arquivo (normalmente um que ser interpretado). programa Conjunto de instrues (program) especifica uma computao. que

1.5 O primeiro programa


Tradicionalmente, o primeiro programa escrito em uma nova linguagem de programao chamado de "Al, Mundo!" porque tudo que ele faz apresentar as palavras "Al, Mundo!". Em Python, ele assim:
print "Al, Mundo!"

algoritmo Processo geral para soluo de certa categoria de (algorithm) uma problemas. bug Erro em um programa. depurao O processo de encontrar e (debugging) remover qualquer um dos trs tipos de erros de programao. sintaxe A estrutura de um programa. (syntax)

Isso um exemplo de um comando print, que, na realidade, no "imprime" nada em papel. Ele apresenta o valor na tela. Neste caso, o resultado so as palavras:

Captulo 1: O caminho do programa #20

Como pensar como um cientista da Computao usando Python erro de Erro em um programa, que torna sintaxe impossvel a anlise sinttica (syntax error) (logo, tambm impossvel a interpretao). erro em tempo de execuo (runtime error) Erro que no ocorre at que o programa seja executado, mas que impede que o programa continue. (natural evoludo naturalmente. language) linguagem formal (formal language) Qualquer linguagem desenvolvida pelas pessoas para propsitos especficos, tais como, a representao de idias matemticas ou programas de computadores; todas as linguagens de programao so linguagens formais.

exceo Um outro nome para um erro em (exception) tempo de execuo ou erro de runtime. erro de Erro em um programa, que o leva semntica a fazer algo diferente do que (semantic pretendia o programador. error) semntica O significado de um programa. (semantics) linguagem Qualquer lngua natural seres humanos falada pelos que tenha

tomo (token) Um elemento bsico da estrutura sinttica de um programa, anlogo a uma palavra em uma linguagem natural. anlise Examinar um programa e sinttica analisar sua estrutura sinttica. (parse) comando Instruo que leva print (`print` interpretador Python statement) apresentar um valor na tela. o a

Captulo 1: O caminho do programa #21

Como pensar como um cientista da Computao usando Python

Captulo 2: Variveis, expresses e comandos

2.1 Valores e tipos


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

interpreta 1,000,000 como uma tupla, algo que veremos no Captulo 9. Por hora, lembre-se apenas de no colocar vrgulas nos nmeros.

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

O comando print tambm funciona com

Este exemplo faz trs atribuies. A primeira atribui a string "E a, Doutor?" a uma nova varivel chamada mensagem. A segunda d o valor Se voc estiver em dvida sobre qual o inteiro 17 a n, e a terceira atribui o nmero de tipo de um determinado valor, o interpretador pode ponto flutuante 3.14159 varivel chamada pi. revelar: Uma maneira comum de representar >>> type("Al, Mundo!") variveis no papel escrever o nome delas com <type 'string'> uma seta apontando para o valor da varivel. Esse >>> type(17) tipo de figura chamado de diagrama de estado porque mostra em que estado cada varivel est <type 'int'> Nenhuma surpresa: strings pertencem (pense nisso como o estado de esprito da varivel). ao tipo string e inteiros pertencem ao tipo int. O diagrama a seguir mostra o resultado das Menos obviamente, nmeros com um ponto decimal instrues de atribuio: pertencem a um tipo chamado float, porque estes nmeros so representados em um formato chamado ponto flutuante 1:
>>> type(3.2) <type 'float'>

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

variveis:

O comando print tambm funciona com

Eles so strings.

Ao digitar um nmero grande, tentador usar pontos entre grupos de trs dgitos, assim: 1.000.000. Isso no funciona porque Python usa o ponto como separador decimal. Usar a vrgula, como se faz em ingls, resulta numa Em cada um dos casos, o resultado o expresso vlida, mas no no nmero que valor da varivel. Variveis tambm tm tipo; queramos representar: novamente, podemos perguntar ao interpretador >>> print 1,000,000 quais so eles:
1 0 0

>>> print mensagem E a, Doutor? >>> print n 17 >>> print pi 3.14159

No nada do que se esperava! Python


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

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

Captulo 2: Variveis, expresses e comandos #22

Como pensar como um cientista da Computao usando Python Um script normalmente contm uma seqncia de comandos. Se houver mais de um O tipo de uma varivel o tipo do valor comando, os resultados aparecero um de cada vez, conforme cada comando seja executado. ao qual ela se refere. Por exemplo, o "script":
>>> type(pi) <type 'float'>

2.3 Nomes de variveis e palavras reservadas


Os programadores geralmente escolhem nomes significativos para suas variveis -eles documentam para o qu a varivel usada.

print 1 x = 2 print 2

produz a sada:
1 2

Novamente, o comando de atribuio no produz sada. Nomes de variveis podem ser arbitrariamente longos. Eles podem conter tanto letras quanto nmeros, mas tm de comear com uma letra. Embora seja vlida a utilizao de letras 2.5 Avaliando expresses maisculas, por conveno, no usamos. Se voc o fizer, lembre-se de que maisculas e minsculas so diferentes. Bruno e bruno so variveis diferentes. Uma expresso uma combinao de valores, variveis e operadores. Se voc digitar uma O caractere para sublinhado ( _ ) pode expresso na linha de comando, o interpretador aparecer em um nome. Ele muito utilizado em avalia e exibe o resultado: nomes com mltiplas palavras, tal como em >>> 1 + 1 meu_nome ou preco_do_cha_na_china. Se voc der a uma varivel um nome Embora expresses contenham valores, invlido, causar um erro de sintaxe: variveis e operadores, nem toda expresso contm todos estes elementos. Um valor por si s >>> 76trombones = "grande parada" considerado uma expresso, do mesmo modo que SyntaxError: invalid syntax uma varivel: >>> muito$ = 1000000
SyntaxError: invalid syntax >>> class = "Ciencias da Computacao 101" SyntaxError: invalid syntax >>> 17 17 >>> x 2 2

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

Quando Python exibe o valor de uma expresso, usa o mesmo formato que voc usaria para entrar com o valor. No caso de strings, isso significa que as aspas so includas [#]_. Mas o comando print imprime o valor da expresso, que, neste caso, o contedo da string.

Num script, uma expresso sozinha Pode ser til ter essa lista mo. Se o interpretador acusar erro sobre um de seus nomes um comando vlido, porm sem efeito. O script: de varivel e voc no souber porqu, veja se o 17 nome est na lista. 3.2

2.4 Comandos

"Al, Mundo!" 1 + 1

no produz qualquer sada. Como voc mudaria o "script" para exibir os valores destas Um comando uma instruo que o interpretador quatro expresses? Python pode executar. Vimos at agora dois tipos de comandos: de exibio (print) e de atribuio. Quando voc digita um comando na 2.6 Operadores e operandos linha de comando, o Python o executa e mostra o resultado, se houver um. O resultado de um Operadores so smbolos especiais que representam comando print a exibio de um valor. Comandos computaes como adio e multiplicao. Os de atribuio no produzem um resultado visvel. valores que o operador usa so chamados Captulo 2: Variveis, expresses e comandos #23

Como pensar como um cientista da Computao usando Python operandos. Todas as expresses seguintes so vlidas em Python e seus significados so mais ou menos claros:
20+32 hora-1 5**2 \ (5+9)*(15-7) hora*60+minuto minuto/60

Adio e da Subtrao, que tambm tm a mesma precedncia. Assim 2*3-1 d 5 em vez de 4, e 2/3-1 -1, no 1 (lembre-se de que na diviso inteira, 2/3=0).

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

Operadores com a mesma precedncia so avaliados da esquerda para a direita. Assim, na expresso minuto*100/60, a multiplicao acontece primeiro, resultando em 5900/60, o que se transforma produzindo 98. Se as operaes tivessem sido avaliadas da direita para a esquerda, o resultado poderia ter sido 59*1, que 59, que est errado.

2.8 Operaes com strings


De maneira geral, voc no pode executar operaes matemticas em strings, ainda que as strings se paream com nmeros. O que segue invlido (assumindo que mensagem do tipo string):
mensagem-1 "Al"/123 mensagem*"Al" "15"+2

Interessante o operador +, que funciona com strings, embora ele no faa O valor de minuto 59 e, em aritmtica exatamente o que voc poderia esperar. Para convencional, 59 dividido por 60 0,98333, no 0. A strings, o operador + representa concatenao, que razo para a discrepncia que Python est significa juntar os dois operandos ligando-os pelos realizando uma diviso inteira. extremos. Por exemplo: Quando ambos os operandos so fruta = "banana" inteiros, o resultado tem de ser tambm um inteiro assada = " com canela" e, por conveno, a diviso inteira sempre arredonda para baixo, mesmo em casos como este, print fruta + assada A sada deste programa banana com em que o inteiro seguinte est muito prximo: canela. O espao antes da palavra com parte da >>> minuto*100/60 string e necessrio para produzir o espao entre as 98 strings concatenadas. De novo, o resultado arredondado O operador * tambm funciona com para baixo, mas agora pelo menos a resposta strings; ele realiza repetio. Por exemplo, "Legal"*3 aproximadamente correta. A alternativa usar a "LegalLegaLegal". Um dos operadores tem que ser diviso em ponto flutuante, o que veremos no uma string; o outro tem que ser um inteiro. captulo 3. Por um lado, esta interpretao de + e * faz sentido pela analogia entre adio e multiplicao. Assim como 4*3 equivale a 4+4+4, 2.7 Ordem dos operadores no de estranhar que "Legal"*3 seja o mesmo que "Legal"+"Legal"+"Legal". Por outro lado, uma Quando mais de um operador aparece em uma diferena significativa separa concatenao e expresso, a ordem de avaliao depende das repetio de adio e multiplicao. Voc saberia regras de precedncia. Python segue as mesmas mencionar uma propriedade da adio e da regras de precedncia para seus operadores multiplicao que no ocorre na concatenao e na matemticos que a matemtica. O acrnimo repetio? PEMDAS uma maneira prtica de lembrar a ordem das operaes:

Parnteses tm a mais alta precedncia e podem ser usados para forar uma expresso a ser avaliada na ordem que voc quiser. J que expresses entre parnteses so avaliadas primeiro, 2 * (3-1) 4, e (1+1)**(5-2) 8. Voc tambm pode usar parnteses para tornar uma expresso mais fcil de ler, como em (minuto * 100) / 60, ainda que isso no altere o resultado.

2.9 Composio
At agora, vimos os elementos de um programa -variveis, expresses, e instrues ou comandos -isoladamente, sem mencionar como combin-los.

Uma das caractersticas mais prticas das linguagens de programao a possibilidade de pegar pequenos blocos e combin-los numa . Por exemplo, ns sabemos como Exponenciao ou potenciao tem a composio nmeros e sabemos como exibi-los; acontece prxima precedncia mais alta, assim somar que podemos fazer as duas coisas ao mesmo tempo: 2**1+1 3 e no 4, e 3*1**3 3 e no 27. Multiplicao e Diviso tm a mesma precedncia, que mais alta do que a da
>>> print 17 + 3 20

Captulo 2: Variveis, expresses e comandos #24

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

e valores, que (expression) operadores representa um resultado nico. avaliar Simplificar uma expresso atravs (evaluate) da realizao de operaes, para produzir um valor nico. diviso inteira (integer division) regras de precedncia (rules of precedence) Operao que divide um inteiro por outro e resulta em um inteiro. A diviso inteira resulta no nmero de vezes que o numerador divisvel pelo denominador e descarta qualquer resto. O conjunto de regras que governa a ordem em que expresses envolvendo mltiplos operadores e operandos so avaliadas. Juntar dois operandos lado a lado. Habilidade de combinar expresses e comandos simples em expresses e comandos compostos, de forma a representar computaes complexas de forma concisa.

Esta possibilidade pode no parecer muito impressionante agora, mas voc ver outros exemplos em que a composio torna possvel expressar computaes complexas de modo limpo e conciso.

Ateno: Existem limites quanto ao lugar onde voc pode usar certos tipos de expresso. Por exemplo, o lado esquerdo de um comando de concatenar atribuio tem que ser um nome de varivel, e no (concatenate uma expresso. Assim, o seguinte no vlido: ) minuto+1 = hora. composio (compositio n)

2.11 Glossrio

valor (value) Um nmero ou string (ou outra coisa que ainda vamos conhecer) que pode ser atribuda a uma varivel ou computada em uma expresso. tipo (type) Um conjunto de valores. O tipo de um valor determina como ele pode ser usado em expresses. At agora, os tipos vistos so: inteiros (tipo int), nmeros em ponto-flutuante (tipo float) e strings (tipo string). ponto- Formato para representar nmeros flutuante que possuem partes fracionrias. (floatingpoint) varivel Nome que se refere a um valor. (variable) comando Trecho de cdigo que representa (statement) uma instruo ou ao. At agora, os comandos vistos foram de atribuio e exibio. atribuio Comando que atribui um valor a (assignment) uma varivel. diagrama de Representao grfica de um estado (state conjunto de variveis e os valores diagram) aos quais elas se referem. palavra- Palavra reservada usada pelo chave compilador para analisar o (keyword) programa; voc no pode usar palavras-chave como if, def, e while como nomes de variveis. operador Smbolo especial que representa (operator) uma computao simples, como adio, multiplicao ou concatenao de strings. operando Um dos valores sobre o qual o (operand) operador opera. expresso Combinao de variveis,

comentrio Informao em um programa (comment) dirigida a outros programadores (ou qualquer pessoa que esteja lendo o cdigo fonte) e que no tem efeito na execuo do programa.

Captulo 2: Variveis, expresses e comandos #25

Como pensar como um cientista da Computao usando Python

Captulo 2: Variveis, expresses e comandos #26

Como pensar como um cientista da Computao usando Python

Captulo 3: Funes

3.1 Chamadas de funes

Voc j viu um exemplo de uma chamada de Finalmente, a funo str converte para o funo: tipo string:
>>> type('32') <type 'str'> >>> str(32) '32' >>> str(3.14149) '3.14149'

32.0 >>> float('3.14159') 3.14159

O nome da funo type e ela exibe o tipo de um valor ou varivel. O valor ou varivel, que chamado de argumento da funo, tem que Pode parecer curioso que Python faa vir entre parnteses. comum se dizer que uma funo 'recebe' um valor e 'retorna' um resultado. O distino entre o valor inteiro 1 e o valor em ponto flutuante 1.0. Eles podem representar o mesmo resultado chamado de valor de retorno . nmero, mas pertencem a tipos diferentes. A razo Em vez de imprimir um valor de que eles so representados de modo diferente dentro do computador. retorno, podemos atribui-lo a uma varivel:
>>> bia = type('32') >>> print bia <type 'str'>

3.3 Coero entre tipos

Como outro exemplo, a funo id recebe um valor ou uma varivel e retorna um inteiro, que Agora que podemos converter entre tipos, temos atua como um identificador nico para aquele outra maneira de lidar com a diviso inteira. Voltando ao exemplo do captulo anterior, suponha valor: que queiramos calcular a frao de hora que j >>> id(3) passou. A expresso mais bvia, minuto / 60, faz aritmtica inteira, assim, o resultado sempre 0, 134882108 mesmo aos 59 minutos passados da hora. >>> bia = 3 Uma soluo converter minuto para ponto flutuante e fazer a diviso em ponto Todo valor tem um id, que um nmero flutuante: nico relacionado ao local onde ele est guardado na memria do computador. O id de uma varivel >>> minuto = 59 >>> float(minuto) / 60 o id do valor a qual ela se refere.
0.983333333333 >>> bia(beth) 134882108

Opcionalmente, podemos tirar vantagem das regras de converso automtica entre tipos, chamada de coero de tipos. Para os operadores matemticos, se qualquer operando for Python prov uma coleo de funes nativas que um float, o outro automaticamente convertido convertem valores de um tipo em outro. A funo para float: int recebe um valor e o converte para inteiro, se >>> minuto = 59 possvel, ou, se no, reclama:

3.2 Converso entre tipos

>>> int('32') 32 >>> int('Al') ValueError: invalid literal for int() : Al

>>> minuto / 60.0 0.983333333333

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

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

3.4 Funes matemticas

Em matemtica, voc provavelmente j viu funes como seno (sin) e log, e aprendeu a resolver expresses como sin(pi/2) e log(1/x). Primeiro voc A funo float converte inteiros e strings resolve e expresso entre parnteses (o argumento). Por exemplo, pi/2 aproximadamente 1,571, e 1/x em nmeros em ponto flutuante: 0.1 (se x for 10,0).
>>> float(32)

A voc avalia a funo propriamente Captulo 3: Funes #27

Como pensar como um cientista da Computao usando Python dita, seja procurando numa tabela ou realizando >>> x = math.exp(math.log(10.0)) vrios clculos. O sin de 1,571 1 e o log de 0,1 -1 Esta instruo encontra o logaritmo (assumindo que log indica o logaritmo na base 10). base e de 10 e ento eleva e quela potncia. O Este processo pode ser aplicado resultado atribudo a x. repetidamente para avaliar expresses mais complicadas, como log(1/sin(pi/2)). Primeiro voc avalia o argumento na funo mais interna, depois 3.6 Adicionando novas funes avalia a funo e assim por diante. Python tem um mdulo matemtico que prov a maioria das funes matemticas mais familiares. Um mdulo um arquivo que contm uma coleo de funes relacionadas agrupadas juntas. Antes de podermos usar as funes contidas em um mdulo, temos de import-lo:
>>> import math

At aqui, temos utilizado somente as funes que vm com Python, mas tambm possvel adicionar novas funes. Criar novas funes para resolver seus prprios problemas uma das coisas mais teis de uma linguagem de programao de propsito geral.

No contexto de programao, funo uma seqncia nomeada de instrues ou comandos, que realizam uma operao desejada. Para chamar uma das funes, temos Esta operao especificada numa definio de que especificar o nome do mdulo e o nome da funo. At agora, as funes que usamos neste funo, separados por um ponto. Esse formato livro so pr-definidas e suas definies no foram chamado de notao de ponto : apresentadas. Isso demonstra que podemos usar funes sem ter que nos preocupar com os detalhes >>> decibel = math.log10(17.0) de suas definies. A sintaxe para uma definio de funo A primeira instruo atribui a decibel o : logaritmo de 17 na base 10. Existe tambm uma def NOME( LISTA DE PARAMETROS ) : funo chamada log, que pega o logaritmo na base COMANDOS e. Voc pode usar o nome que quiser para A terceira instruo encontra o seno do as funes que criar, exceto as palavras reservadas valor da varivel angulo. sin e as outras funes do Python. A lista de parmetros especifica que trigonomtricas (cs, tan, etc.) recebem argumentos informao, se houver alguma, voc tem que em radianos. Para converter de graus em radianos, fornecer para poder usar a nova funo. divida por 360 e multiplique por 2*pi. Por exemplo, Uma funo pode ter quantos comandos para encontrar o seno de 45 graus, primeiro calcule forem necessrios, mas eles precisam ser o ngulo em radianos e depois ache o seno: endentados a partir da margem esquerda. Nos >>> graus = 45 exemplos deste livro, usaremos uma endentao de dois espaos. >>> angulo = graus * 2 * math.pi / 360.0 As primeiras funes que vamos mostrar no tero parmetros, ento, a sintaxe ter A constante pi tambm parte do esta aparncia: mdulo math. Se voc sabe geometria, pode checar o resultado anterior comparando-o com a raiz def novaLinha(): print quadrada de dois dividido por dois: Esta funo chamada de novaLinha. >>> math.sqrt(2) / 2.0 Os parnteses vazios indicam que ela no tem 0.707106781187 parmetros. Contm apenas um nico comando, que gera como sada um caractere de nova linha (isso o que acontece quando voc usa um comando print sem qualquer argumento).
>>> math.sin(angulo) 0.707106781187 >>> angulo = 1.5 >>> altura = math.sin(angulo)

3.5 Composio

A sintaxe para a chamada desta nova funo a mesma sintaxe para as funes nativas: Do mesmo modo como nas funes matemticas, as funes do Python podem ser compostas, o que print 'Primeira Linha.' significa que voc pode usar uma expresso como novaLinha() parte de outra. Por exemplo, voc pode usar print 'Segunda Linha.' qualquer expresso como um argumento para uma A sada deste programa : funo:
>>> x = math.cos(angulo + pi/2) Primeira Linha.

Esta instruo toma o valor de pi, divide-o por 2, e soma o resultado ao valor de Segunda Linha. angulo. A soma ento passada como um Observe o espao extra entre as duas argumento para a funo cos. linhas. E se quisssemos mais espao entre as linhas? Poderamos chamar a mesma funo Voc tambm pode pegar o resultado de repetidamente: uma funo e pass-lo como um argumento para outra: print 'Primeira Linha.' Captulo 3: Funes #28

Como pensar como um cientista da Computao usando Python


novaLinha() novaLinha() novaLinha() print 'Segunda Linha.' print 'Primeira Linha.' tresLinhas() print 'Segunda Linha.'

Esse programa contm duas definies Ou poderamos escrever uma nova de funes: novaLinha e tresLinhas. Definies de funo chamada tresLinhas, que produzisse trs funes so executadas como quaisquer outros comandos, mas o efeito criar a nova funo. Os novas linhas: comandos dentro da definio da funo no so def tresLinhas() : executados at que a funo seja chamada, logo, a novaLinha() definio da funo no gera nenhuma sada.
novaLinha() novaLinha() print 'Primeira Linha.' tresLinhas() print 'Segunda Linha.'

Como voc j deve ter imaginado, preciso criar uma funo antes de poder execut-la. Em outras palavras, a definio da funo tem que ser executada antes que ela seja chamada pela primeira vez. Como exerccio, mova as ltimas trs linhas deste programa para o topo, de modo que a chamada da funo aparea antes das definies. Rode o programa e veja que mensagem de erro voc ter. Tambm a ttulo de exerccio, comece com a verso que funciona do programa e mova a definio de novaLinha para depois da definio de tresLinhas. O que acontece quando voc roda este programa?

Esta funo contm trs comandos, todos com recuo de dois espaos a partir da margem esquerda. J que o prximo comando no est endentado, Python reconhece que ele no faz parte da funo. Algumas coisas que observadas sobre este programa: devem ser

1. Voc pode chamar o mesmo procedimento repetidamente. Isso muito comum, alm de til. 2. Voc pode ter uma funo chamando outra funo; neste caso tresLinhas chama novaLinha.

3.8 Fluxo de execuo

Para assegurar que uma funo esteja definida Pode no estar claro, at agora, de que antes do seu primeiro uso, preciso saber em que vale o esforo de criar novas funes - existem ordem os comandos so executados, o que vrias razes, mas este exemplo demonstra duas chamado de fluxo de execuo . delas: A execuo sempre comea com o Criar uma nova funo permite que voc primeiro comando do programa. Os comandos so coloque nome em um grupo de comandos. executados um de cada vez, pela ordem, de cima As funes podem simplificar um programa para baixo. ao ocultar uma computao complexa por trs de um simples comando cujo nome As definies de funo no alteram o pode ser uma palavra em portugus, em vez fluxo de execuo do programa, mas lembre-se que de algum cdigo misterioso. comandos dentro da funo no so executados at a funo ser chamada. Embora no seja comum, Criar uma nova funo pode tornar o voc pode definir uma funo dentro de outra. programa menor, por eliminar cdigo Neste caso, a definio mais interna no repetido. Por exemplo, um atalho para executada at que a funo mais externa seja 'imprimir' nove novas linhas consecutivas chamada. chamar tresLinhas trs vezes. Chamadas de funo so como um Como exerccio, escreva uma funo desvio no fluxo de execuo. Em vez de ir para o chamada noveLinhas que use tresLinhas para prximo comando, o fluxo salta para a primeira imprimir nove linhas em branco. Como voc linha da funo chamada, executa todos os poderia imprimir vinte e sete novas linhas? comandos l e ento volta atrs para retomar de onde havia deixado. Parece muito simples, at a hora em que voc lembra que uma funo pode chamar outra. Enquanto estiver no meio de uma funo, o Reunindo os fragmentos de cdigo da Seo 3.6, o programa poderia ter de executar os comandos em uma outra funo. Mas enquanto estivesse programa completo fica assim: executando esta nova funo, o programa poderia def novaLinha() : ter de executar ainda outra funo!

3.7 Definies e uso

print

def tresLinhas() : novaLinha() novaLinha() novaLinha()

Felizmente, Python adepto de monitorar a posio onde est, assim, cada vez que uma funo se completa, o programa retoma de onde tinha parado na funo que a chamou. Quando chega ao fim do programa, ele termina. Qual a moral dessa histria srdida? Captulo 3: Funes #29

Como pensar como um cientista da Computao usando Python Quando voc ler um programa, no o leia de cima para baixo. Em vez disso, siga o fluxo de execuo.
>>> imprimeDobrado(miguel) Eric, the half a bee. Eric, the half a bee.

3.9 Parmetros e argumentos


Algumas das funes nativas que voc j usou requerem argumentos, aqueles valores que controlam como a funo faz seu trabalho. Por exemplo, se voc quer achar o seno de um nmero, voc tem que indicar qual nmero . Deste modo, sin recebe um valor numrico como um argumento.

N.T.: "Eric, the half a bee" uma msica do grupo humorstico britnico Monty Python. A linguagem Python foi batizada em homenagem ao grupo e, por isso, os programadores gostam de citar piadas deles em seus exemplos.

Repare numa coisa importante: o nome da varivel que passamos como um argumento (miguel) no tem nada a ver com o nome do parmetro (bruno). No importa de que modo o valor foi chamado de onde veio (do 'chamador'); aqui, em imprimeDobrado, chamamos a todo Algumas funes recebem mais de um mundo de bruno. argumento. Por exemplo, pow recebe dois argumentos, a base e o expoente. Dentro da funo, os valores que lhe so passados so atribudos a 3.10 Variveis e parmetros so locais variveis chamadas parmetros. Veja um exemplo de uma funo Quando voc cria uma varivel local dentro de uma definida pelo usurio, que recebe um parmetro: funo, ela s existe dentro da funo e voc no def imprimeDobrado(bruno): pode us-la fora de l. Por exemplo:
print bruno, bruno

Esta funo recebe um nico argumento concat = parte1 + parte2 e o atribui a um parmetro chamado bruno. O valor imprimeDobrado(concat) do parmetro (a essa altura, no sabemos qual ser) Esta funo recebe dois argumentos, impresso duas vezes, seguido de uma nova linha. Estamos usando bruno para mostrar que o nome do concatena-os, e ento imprime o resultado duas parmetro deciso sua, mas claro que melhor vezes. Podemos chamar a funo com duas strings: escolher um nome que seja mais ilustrativo. A funo imprimeDobrado funciona para qualquer tipo que possa ser impresso:
>>> imprimeDoobrado('Spam') Spam Spam >>> imprimeDobrado(5) 5 5 >>> imprimeDobrado(3.14159) 3.14159 3.14159 >>> canto1 = 'Pie Jesu domine, ' >>> canto2 = 'dona eis requiem. ' >>> concatDupla(canto1, canto2) Pie Jesu domine, Dona eis requiem. Pie Jesu domine, \ Dona eis requiem.

def concatDupla(parte1, parte2)

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

Na primeira chamada da funo, o argumento uma string. Na segunda, um inteiro. Na terceira um float.

Parmetros so sempre locais. Por exemplo, fora da funo imprimeDobrado, no As mesmas regras de composio que se existe alguma coisa chamada bruno. Se voc tentar aplicam a funes nativas tambm se aplicam s utiliz-la, Python vai reclamar. funes definidas pelo usurio, assim, podemos usar qualquer tipo de expresso como um argumento para imprimeDobrado: Para entender que variveis podem ser usadas aonde, s vezes til desenhar um diagrama da pilha. Como os diagramas de estado, diagramas da Como acontece normalmente, a pilha mostram o valor de cada varivel, mas expresso avaliada antes da execuo da funo, tambm a funo qual cada varivel pertence. assim imprimeDobrado imprime Cada funo representada por um SpamSpamSpamSpam SpamSpamSpamSpam em frame (quadro). Um frame uma caixa com o nome vez de 'Spam'*4 'Spam'*4. de uma funo ao lado dela e os parmetros e Como exerccio, escreva um chamada a variveis da funo dentro dela. O diagrama de imprimeDobrado que imprima 'Spam'*4 'Spam'*4. pilha para o exemplo anterior tem a seguinte Dica: strings podem ser colocadas tanto entre aparncia: aspas simples quanto duplas e o tipo de aspas que no for usado para envolver a string pode ser usado dentro da string, como parte dela. Tambm podemos usar uma varivel como argumento:
>>> miguel = 'Eric, the half a bee.' >>> imprimeDobrado('Spam'*4) SpamSpamSpamSpam SpamSpamSpamSpam >>> imprimeDobrado(math.cos(math.pi)) -1.0 -1.0

3.11 Diagramas da pilha

Captulo 3: Funes #30

Como pensar como um cientista da Computao usando Python no produz resultado em uma expresso tal como novaLinha() + 7? 3. Voc pode escrever funes que produzem resultados, ou est preso a funes como novaLinha e imprimeDobrado? A resposta para a terceira questo afirmativa e ns vamos fazer isso no Captulo 5. A ttulo de exerccio, responda as outras duas questes testando-as. Se tiver dvida sobre o que vlido ou invlido em Python, tente buscar a resposta perguntando ao interpretador. A ordem da pilha mostra o fluxo de execuo. imprimeDobrado foi chamado por concatDupla, e concatDupla foi chamado por __main__ (principal), que um nome especial para a funo mais no topo. Quando voc cria uma varivel fora de qualquer funo, ela pertence __main__. Cada parmetro se refere ao mesmo valor que o seu argumento correspondente. Assim, parte1 tem o mesmo valor de canto1, parte2 tem o mesmo valor de canto2 e bruno tem o mesmo valor de concat. Se um erro acontece durante uma chamada de funo, Python imprime o nome da funo, e o nome da funo que a chamou, e o nome da funo que chamou a que chamou, percorrendo todo o caminho de volta a __main__. Por exemplo, se tentssemos acessar concat de dentro de imprimeDobrado, teramos um NameError:
Traceback (innermost last): File "teste.py", line 13, in __main__ concatDupla(canto1, canto2) File "teste.py", line 5, in concatDupla imprimeDobrado(concat) File "teste.py", line 9, in imprimeDobrado print concat NameError: concat

3.13 Glossrio
chamada de funo (function call) Comando que executa uma funo. Consiste do nome da funo seguido de uma lista de argumentos entre parnteses.

argumento Valor fornecido a uma funo (argument) quando ela chamada. Este valor atribudo ao parmetro correspondente na funo. valor de retorno (return value) O resultado da funo. Se uma chamada de funo usada como expresso, o valor de retorno o valor da expresso.

converso de Comando explcito que pega um tipo (type valor de um tipo e devolve o valor conversion) correspondente em outro tipo. coercividade Uma converso de tipo que ocorre de tipo (type automaticamente, de acordo com coercion) as regras de coercividade do Python. mdulo Arquivo que contm uma coleo (module) de funes e classes relacionadas entre si. notao de A sintaxe para chamar uma funo ponto (dot que est em outro mdulo, notation) especificando o nome do mdulo, seguido por um ponto (.) e o nome da funo. funo Seqncia de comandos nomeada, (function) que realiza alguma tarefa til. As funes podem ou no receber parmetros e podem ou no retornar valores. definio de funo (function definition) Comando que cria uma nova funo, especificando seu nome, parmetros e comandos que ela executa.

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

3.12 Funes com resultados


A essa altura, voc deve ter percebido que algumas das funes que estamos usando, tais como as funes matemticas, produzem resultados. Outras funes, como novaLinha, executam uma ao, mas no retornam um valor. O que levanta algumas questes: 1. O que acontece se voc chama uma funo e no faz nada com o resultado (por exemplo, no atribui o resultado a uma varivel ou o usa como parte de uma expresso maior)? 2. O que acontece se voc usa uma funo que

fluxo de A ordem na qual os comandos so execuo executados durante a execuo do (flow of programa. execution) parmetro Nome usado numa funo para (parameter) referir-se ao valor passado como argumento. varivel Varivel definida dentro da funo. local (local Uma varivel local s pode ser variable) usada dentro da funo onde foi

Captulo 3: Funes #31

Como pensar como um cientista da Computao usando Python definida. diagrama da Representao grfica da pilha de pilha (stack funes, suas variveis e os valores diagram) aos quais elas se referem. frame Retngulo no diagrama da pilha que representa uma chamada de funo. Contm as variveis locais e os parmetros da funo. traceback Lista de funes que esto em execuo, impressa quando um erro de execuo ocorre.

Captulo 3: Funes #32

Como pensar como um cientista da Computao usando Python

Captulo 4: Condicionais e recursividade

4.1 O operador mdulo

se de que = um operador de atribuio e == um operador de comparao. Tambm no existem coisas como =< ou =>.

O operador mdulo trabalha com inteiros (e expresses que tm inteiros como resultado) e produz o resto da diviso do primeiro pelo segundo. 4.3 Operadores lgicos Em Python, o operador mdulo um smbolo de porcentagem (%). A sintaxe a mesma que a de Existem trs operadores lgicos: and, or, not (e, ou, outros operadores: no). A semntica (significado) destes operadores >>> quociente = 7 / 3 similar aos seus significados em ingls (ou >>> print quociente portugus). Por exemplo, x > 0 and x < 10 verdadeiro somente se x for maior que 0 e menor 2 que 10. >>> resto = 7 % 3
>>> print resto 1

Ento, 7 dividido por 3 2 e o resto 1.

n%2 == 0 or n%3 == 0 verdadeiro se qualquer das condies for verdadeira, quer dizer, se o nmero n for divisvel por 2 ou por 3.

Finalmente, o operador lgico not nega O operador mdulo se revela surpreendentemente til. Por exemplo, voc pode uma expresso booleana, assim, not(x > y) checar se um nmero divisvel por outro - se x % y verdadeiro se (x > y) for falso, quer dizer, se x for menor ou igual a y. d zero, ento x divisvel por y. Voc tambm pode extrair o algarismo ou algarismos mais direita de um nmero. Por exemplo, x % 10 resulta o algarismo mais direita de x (na base 10). Similarmente, x % 100 resulta nos dois dgitos mais direita. A rigor, os operandos de operadores lgicos deveriam ser expresses booleanas, mas Python no muito rigoroso. Qualquer nmero diferente de zero interpretado como verdadeiro (True):
>>> >>> 1 >>> >>> 0 x = 5 x and 1 y = 0

4.2 Expresses booleanas

y and 1 Uma expresso booleana uma expresso que verdadeira (true) ou falsa (false). Em Python, uma expresso que verdadeira tem o valor 1, e uma Em geral, esse tipo de coisa no expresso que falsa tem o valor 0. considerado de bom estilo. Se voc precisa O operador == compara dois valores e comparar um valor com zero, deve faz-lo explicitamente. produz uma expresso booleana: >>> 5 == 5 True >>> 5 == 6 False

4.4 Execuo condicional

Para poder escrever programas teis, quase sempre precisamos da habilidade de checar condies e mudar o comportamento do programa de acordo com elas. As instrues condicionais nos do essa habilidade. A forma mais simples a instruo if O operador == um dos operadores de (se): comparao; os outros so: if x > 0 No primeiro comando, os dois operadores so iguais, ento a expresso avalia como True (verdadeiro); no segundo comando, 5 no igual a 6, ento temos False (falso).
x x x x x != y > y < y >= y <= y # # # # # x x x x x diferente de y maior que y menor que y maior ou igual a y menor ou igual a y print "x positivo"

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

Embora esses operadores Assim como outras instrues provavelmente sejam familiares a voc, os smbolos compostas, a instruo if constituda de um em Python so diferentes dos smbolos da cabealho e de um bloco de instrues: matemtica. Um erro comum usar um sinal de igual sozinho (=) em vez de um duplo (==). Lembre- CABECALHO: Captulo 4: Condicionais e recursividade #33

Como pensar como um cientista da Computao usando Python


PRIMEIRO COMANDO ... ULTIMO COMANDO print x, " menor que", y elif x > y: print x, " maior que", y else: print x, "e", y, "so iguais"

O cabealho comea com uma nova linha e termina com dois pontos (:). Os comandos ou instrues endentados que seguem so chamados de bloco . A primeira instruo no endentada marca o fim do bloco. Um bloco de comandos dentro de um comando composto ou instruo composta chamado de corpo do comando. No existe limite para o nmero de instrues que podem aparecer no corpo de uma instruo if, mas tem que haver pelo menos uma. Ocasionalmente, til ter um corpo sem nenhuma instruo (usualmente, como um delimitador de espao para cdigo que voc ainda no escreveu). Nesse caso, voc pode usar o comando pass, que no faz nada.

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

Cada condio checada na ordem. Se a primeira falsa, a prxima checada, e assim por diante. Se uma delas verdadeira, o ramo correspondente executado, e a instruo termina. Um segundo formato da instruo if a execuo Mesmo que mais de uma condio seja verdadeira, alternativa, na qual existem duas possibilidades e a apenas o primeiro ramo verdadeiro executa. condio determina qual delas ser executada. A sintaxe se parece com: Como exerccio, coloque os exemplos acima em funes chamadas comparar(x, y) e if x % 2 == 0: executar(escolha).

4.5 Execuo alternativa

print x, " par" else: print x, " impar"

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

4.7 Condicionais aninhados

Para qualquer valor de x, imprimeParidade exibe uma mensagem Embora a endentao das instrues apropriada. Quando voc a chama, pode fornecer torne a estrutura aparente, condicionais aninhados uma expresso de resultado inteiro como um tornam-se difceis de ler rapidamente. Em geral, argumento: uma boa idia evitar o aninhamento quando for possvel. >>> imprimeParidade(17)
>>> imprimeParidade(y+1)

O condicional mais externo tem dois ramos. O primeiro ramo contm uma nica instruo de sada. O segundo ramo contm outra instruo if, que por sua vez tem dois ramos. Os dois ramos so ambos instrues de sada, embora pudessem conter instrues condicionais tambm.

4.6 Condicionais encadeados


s vezes existem mais de duas possibilidades e precisamos de mais que dois ramos. Uma condicional encadeada uma maneira de expressar uma computao dessas:
if x < y:

Operadores lgicos freqentemente fornecem uma maneira de simplificar instrues condicionais aninhadas. Por exemplo, podemos reescrever o cdigo a seguir usando uma nica condicional:
if 0 < x: if x < 10: print "x um nmero positivo de um s algarismo."

A instruo print executada somente se a fizermos passar por ambos os condicionais,

Captulo 4: Condicionais e recursividade #34

Como pensar como um cientista da Computao usando Python ento, podemos usar um operador and:
if 0 < x and x < 10: print "x um nmero positivo de um s algarismo."

funo da seguinte maneira:


>>> contagemRegressiva(3)

A execuo de contagemRegressiva comea com n=3, e desde que n no 0, produz Esses tipos de condio so comuns, como sada o valor 3, e ento chama a si mesma... assim, Phython prov uma sintaxe alternativa que A execuo de contagemRegressiva similar notao matemtica: comea com n=2, e desde que n no 0, produz como sada o valor 2, e ento chama a si mesma... if 0 < x < 10:
print "x um nmero positivo de um s algarismo."

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 A contagemRegressiva que tem n=2 A contagemRegressiva que tem n=1

4.8 A instruo return

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

retorna.

E ento estamos de volta em __main__ (que viagem!). Assim, a sada completa se parece com:
3 2 1 Fogo!

A funo imprimeLogaritmo recebe um parmetro de nome x. A primeira coisa que ela faz Como um segundo exemplo, d uma checar se x menor ou igual a 0, neste caso ela exibe uma mensagem de erro e ento usa return olhada novamente nas funes novaLinha e para sair da funo. O fluxo de execuo tresLinhas: imediatamente retorna ao ponto chamador, quer dizer, de onde a funo foi chamada, e as linhas def novaLinha(): print restantes da funo no so executadas. Lembre-se que para usar uma funo do mdulo de matemtica, math, voc tem de importlo.
def tresLinhas(): novaLinha() novaLinha() novaLinha()

Muito embora isso funcione, no seria muito til se precisssemos gerar como sada 2 novas linhas, ou 106. Uma alternativa melhor seria J mencionamos que vlido uma funo chamar esta: outra funo, e voc viu vrios exemplos disso. Mas def nLinhas(n): ainda no tnhamos dito que tambm vlido uma if n > 0: funo chamar a si mesma. Talvez no seja bvio print porque isso bom, mas trata-se de uma das coisas nLinhas(n-1) mais mgicas e interessantes que um programa pode fazer. Por exemplo, d uma olhada na seguinte Esse programa similar a funo: contagemRegressiva; sempre que n for maior que 0, ele gera como sada uma nova linha e ento chama def contagemRegressiva(n): a si mesmo para gerar como sada n-1 linhas if n == 0: adicionais. Deste modo, o nmero total de novas print "Fogo!" linhas 1 + (n-1) que, se voc estudou lgebra else: direitinho, vem a ser o prprio n.

4.9 Recursividade

O processo de uma funo chamando a si mesma chamado de recursividade, e tais contagemRegressiva espera que o funes so ditas recursivas. parmetro, n, seja um inteiro positivo. Se n for 0, ela produz como sada a palavra "Fogo!". De outro modo, ela produz como sada n e ento chama uma funo de nome contagemRegressiva -- ela mesma -passando n-1 como argumento. O que acontece se chamarmos essa Captulo 4: Condicionais e recursividade #35

print n contagemRegressiva(n-1)

Como pensar como um cientista da Computao usando Python alcanada:


File "<stdin>", line 2, in recursiva (98 repetitions omitted) File "<stdin>", line 2, in recursiva RuntimeError: Maximum recursion depth exceeded

4.10 Diagramas de pilha para funes recursivas


Na Seo 3.11, usamos um diagrama de pilha para representar o estado de um programa durante uma chamada de funo. O mesmo tipo de diagrama pode ajudar a interpretar uma funo recursiva.

Este traceback um pouco maior do que aquele que vimos no captulo anterior. Quando o Toda vez que uma funo chamada, erro ocorre, existem 100 quadros recursiva na Python cria um novo quadro (frame) para a funo, pilha! que contm as variveis locais e parmetros da Como exerccio, escreva uma funo funo. Para uma funo recursiva, ter que existir com recursividade infinita e rode-a no mais de um quadro na pilha ao mesmo tempo. interpretador Python. Esta figura mostra um diagrama de pilha para contagemRegressiva, chamada com n = 3:

4.12 Entrada pelo teclado


Os programas que temos escrito at agora so um pouco crus, no sentido de no aceitarem dados entrados pelo usurio. Eles simplesmente fazem a mesma coisa todas as vezes. Python fornece funes nativas que pegam entradas pelo teclado. A mais simples chamada raw_input. Quando esta funo chamada, o programa pra e espera que o usurio digite alguma coisa. Quando o usurio aperta a tecla Enter ou Return, o programa prossegue e a funo raw_input retorna o que o usurio digitou como uma string:
>>> entrada = raw_input() O que voc est esperando? >>> print entrada O que voc est esperando?

Antes de chamar raw_input, uma boa Como de costume, no topo da pilha est o quadro para __main__. Ele est vazio porque nem idia exibir uma mensagem dizendo ao usurio o criamos qualquer varivel em __main__ nem que ele deve entrar. Esta mensagem uma deixa passamos qualquer valor para ele. (prompt). Podemos suprir uma deixa como um argumento para raw_input: Os quatro quadros contagemRegressiva tm valores diferentes para o parmetro n. A parte >>> nome = raw_input("Qual... o seu nome? ") mais em baixo na pilha, onde n=0, chamada de Qual... o seu nome? Arthur, Rei dos Bretes! caso base. Ele no faz uma chamada recursiva, >>> print nome ento no h mais quadros. Arthur, Rei dos Bretes! Como exerccio, desenhe um diagrama Se esperamos que a entrada seja um de pilha para nLinhas chamada com n=4. inteiro, podemos usar a funo input:

4.11 Recursividade infinita


Se uma recursividade nunca chega ao caso base, ela prossegue fazendo chamadas recursivas para sempre, e o programa nunca termina. Isto conhecido como recursividade infinita, e geralmente no considerada uma boa idia. Aqui est um programa mnimo com uma recursividade infinita:
def recursiva(): recursiva()

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

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

Na maioria dos ambientes de Para evitar esse tipo de erro, geralmente programao, um programa com recursividade bom usar raw_input para pegar uma string e, infinita na verdade no roda para sempre. Python ento, usar funes de converso para converter reporta uma mensagem de erro quando a para outros tipos. profundidade mxima de recursividade Captulo 4: Condicionais e recursividade #36

Como pensar como um cientista da Computao usando Python composto cabealho e um corpo. O cabealho (compound termina com um dois-pontos (:). O statement) corpo endentado em relao ao cabealho. bloco (block) Grupo de comandos consecutivos com a mesma endentao. corpo (body) O bloco que se segue ao cabealho em um comando composto. aninhamento Estrutura de programa dentro da como um comando (nesting) outra, condicional dentro de um bloco de outro comando condicional. recursividade O processo de chamar a prpria (recursion) funo que est sendo executada. caso base Bloco de comando condicional (base case) numa funo recursiva que no resulta em uma chamada recursiva. recurso infinita (infinite recursion) Funo que chama a si mesma recursivamente sem nunca chegar ao caso base. Aps algum tempo, uma recurso infinita causa um erro de execuo.

4.13 Glossrio
operador mdulo (modulus operator) Operador denotado por um smbolo de porcentagem (%), que trabalha com inteiros e retorna o resto da diviso de um nmero por outro.

expresso Uma expresso que verdadeira booleana ou falsa. (boolean expression) operador de Um dos operadores que compara comparao dois valores: ==, !=, >, <, >=, e <=. (comparison operator) operador Um dos operadores que combina lgico (logical expresses booleanas: and, or, e operator) not. comando Comando que controla o fluxo de condicional execuo dependendo de alguma (conditional condio. statement) condio A expresso booleana que qual bloco ser (condition) determina executado num comando condicional. comando Comando que consiste de um

deixa Indicao visual que diz ao (prompt) usurio que o programa est esperando uma entrada de dados.

Captulo 4: Condicionais e recursividade #37

Como pensar como um cientista da Computao usando Python

Captulo 5: Funes frutferas

5.1 Valores de retorno


Algumas das funes nativas do Python que temos usado, como as funes matemticas, produziram resultados. Chamar a funo gerou um novo valor, o qual geralmente atribumos uma varivel ou usamos como parte de uma expresso:

exemplo:
def valorAbsoluto(x): if x < 0: return -x elif x > 0: return x

Este programa no est correto porque se x for 0, nenhuma das condies ser verdadeira, e = math.exp(1.0) e a funo terminar sem encontrar um comando altura = raio * math.sin(angulo) return. Neste caso, o valor de retorno ser um valor Mas at agora, nenhuma das funes especial chamado None: que ns mesmos escrevemos retornou um valor. Neste captulo, iremos escrever funes None que retornam valores, as quais chamaremos de Como exerccio, escreva uma funo funes frutferas, ou funes que do frutos, na falta de um nome melhor. O primeiro exemplo compare que retorne 1 se x > y, 0 se x == y e -1 se x < area, que retorna a rea de um crculo dado o seu y. raio:
import math def area(raio): temp = math.pi * raio**2 return temp >>> print valorAbsoluto(0)

5.2 Desenvolvimento de programas


Neste ponto, voc deve estar apto a olhar para funes completas e dizer o que elas fazem. Tambm, se voc vem fazendo os exerccios, voc escreveu algumas pequenas funes. Conforme escrever funes maiores, voc pode comear a ter mais dificuldade, especialmente com erros em tempo de execuo (erros de runtime) ou erros semnticos.

J vimos a instruo return antes, mas em uma funo frutfera a instruo return inclui um valor de retorno . Esta instruo significa: "Retorne imediatamente desta funo e use a expresso em seguida como um valor de retorno". A expresso fornecida pode ser arbitrariamente Para lidar com programas de crescente complicada, de modo que poderamos ter escrito complexidade, vamos sugerir uma tcnica chamada esta funo de maneira mais concisa: desenvolvimento incremental. A meta do def area(raio): desenvolvimento incremental evitar sees de return math.pi * raio**2 depurao (debugging) muito longas pela adio e Por outro lado, variveis temporrias teste de somente uma pequena quantidade de como temp muitas vezes tornam a depurao mais cdigo de cada vez. fcil. Como exemplo, suponha que voc s vezes til ter mltiplos comandos queira encontrar a distncia entre dois pontos, dados pelas coordenadas (x1,y1) e (x2,y2). Pelo return, um em cada ramo de uma condicional: teorema de Pitgoras, a distncia :
def valorAbsoluto(x): if x < 0: return -x else: return x

distancia = x2 x1 2 y2 y1 2

O primeiro passo considerar como deveria ser uma funo distancia em Python. Em outras palavras, quais so as entradas (parmetros) J que estes comandos return esto em e qual a sada (valor de retorno)? ramos alternativos da condicional, apenas um ser executado. To logo um seja executado, a funo Neste caso, os dois pontos so as termina sem executar qualquer instruo ou entradas, os quais podemos representar usando comando subseqente. quatro parmetros. O valor de retorno a distncia, que um valor em ponto flutuante. O cdigo que aparece depois de uma instruo return, ou em qualquer outro lugar que o J podemos escrever um esboo da fluxo de execuo jamais alcance, chamado cdigo funo: morto (dead code). Em uma funo frutfera, uma boa return 0.0 idia assegurar que todo caminho possvel dentro Obviamente, esta verso da funo no do programa encontre uma instruo return. Por computa distncias; ela sempre retorna zero. Mas Captulo 5: Funes frutferas #38
def distancia(x1, y1, x2, y2):

Como pensar como um cientista da Computao usando Python ela est sintaticamente correta, e vai rodar, o que instruo return. significa que podemos test-la antes de torn-la Enquanto for iniciante, voc deve mais complicada. acrescentar apenas uma ou duas linhas de cdigo Para testar a nova funo, vamos de cada vez. Conforme ganhar mais experincia, cham-la com valores hipotticos: voc se ver escrevendo e depurando pedaos maiores. De qualquer modo, o processo de >>> distancia(1, 2, 4, 6) desenvolvimento incremental pode poupar um 0.0 bocado de tempo de depurao. Escolhemos estes valores de modo que a Os aspectos chave do processo so: distncia horizontal seja igual a 3 e a distncia vertical seja igual a 4; deste modo, o resultado 5 (a 1. Comece com um programa que funciona e hipotenusa de um tringulo 3-4-5). Quando testamos faa pequenas mudanas incrementais. Em uma funo, til sabermos qual o resultado qualquer ponto do processo, se houver um correto. erro, voc saber exatamente onde ele est. Neste ponto, j confirmamos que a 2. Use variveis temporrias para manter funo est sintaticamente correta, e podemos valores intermedirios de modo que voc comear a adicionar linhas de cdigo. Depois de possa exibi-los e chec-los. cada mudana adicionada, testamos a funo de 3. Uma vez que o programa funcione, voc novo. Se um erro ocorre em qualquer ponto, pode querer remover algum cdigo muleta, sabemos aonde ele deve estar: nas linhas ou andaime (scaffolding) ou consolidar adicionadas mais recentemente. mltiplos comandos dentro de expresses Um primeiro passo lgico nesta compostas, mas somente se isto no tornar o computao encontrar as diferenas x2 - x1 e y2 programa difcil de ler. y1. Ns iremos guardar estes valores em variveis Como um exerccio, use o temporrias chamadas dx e dy e imprimi-las: desenvolvimento incremental para escrever uma def distancia(x1, y1, x2, y2): funo chamada hipotenusa que retorna a medida dx = x2 - x1 da hipotenusa de um tringulo retngulo dadas as dy = y2 - y1 medidas dos dois catetos como parmetros. Registre cada estgio do desenvolvimento print "dx vale", dx incremental conforme voc avance. print "dy vale", dy
return 0.0

Se a funo estiver funcionando, as sadas devero ser 3 e 4. Se assim, sabemos que a 5.3 Composio funo est recebendo os parmetros corretos e realizando a primeira computao corretamente. Se Conforme voc poderia esperar agora, voc pode no, existem poucas linhas para checar. chamar uma funo de dentro de outra. Esta Em seguida, computaremos a soma dos habilidade chamada de composio. quadrados de dx e dy: Como um exemplo, vamos escrever uma funo que recebe dois pontos, o centro de um def distancia(x1, y1, x2, y2): crculo e um ponto em seu permetro, e calcula a dx = x2 - x1 rea do crculo. dy = y2 - y1 Assuma que o ponto do centro est guardado nas variveis xc e yc, e que o ponto do permetro est nas variveis xp e yp. O primeiro encontrar o raio do crculo, o qual a Note que removemos os comandos print passo distncia entre os dois pontos. Felizmente, temos que havamos escrito no passo anterior. Cdigo uma funo, distancia, que faz isto: como este chamado de andaime porque ajuda a escrever o programa, mas no parte do produto Raio = distancia(xc, yc, xp, yp) final. O segundo passo encontrar a rea de De novo, ns vamos rodar o programa um crculo com o raio dado e retorn-la: neste estgio e checar a sada (que deveria ser 25). resultado = area(raio)
dquadrado = dx**2 + dy**2 print "dquadrado vale: ", dquadrado return 0.0

Finalmente, se ns tnhamos importado o mdulo matemtico math, podemos usar a funo sqrt para computar e retornar o resultado:
def distancia(x1, x2, y1, y2): dx = x2 - x1 dy = y2 - y1 dquadrado = dx**2 + dy**2 resultado = math.sqrt(dquadrado) return resultado

return resultado

Juntando tudo numa funo, temos:


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

Chamamos esta funo de area2 para distinguir da funo area, definida anteriormente. S pode existir uma nica funo com um Se isto funcionar corretamente, voc determinado nome em um determinado mdulo. conseguiu. Caso contrrio, talvez fosse preciso As variveis temporrias raio e imprimir (exibir) o valor de resultado antes da Captulo 5: Funes frutferas #39

Como pensar como um cientista da Computao usando Python resultado so teis para o desenvolvimento e para depurao (debugging), mas uma vez que o programa esteja funcionando, podemos torn-lo mais conciso atravs da composio das chamadas de funo: subconjunto uma linguagem de programao completa, o que significa que qualquer coisa que possa ser computada pode ser expressa nesta linguagem. Qualquer programa j escrito pode ser reescrito usando somente os aspectos da linguagem que voc aprendeu at agora (usualmente, voc def area2(xc, yc, xp, yp): precisaria de uns poucos comandos para controlar return area(distancia(xc, yc, xp, yp)) dispositivos como o teclado, mouse, discos, etc., mas Como exerccio, escreva uma funo isto tudo). inclinacao(x1, y1, x2, y2) que retorne a inclinao Provar esta afirmao um exerccio (ou coeficienteAngular?) de uma linha dados os nada trivial, que foi alcanado pela primeira vez pontos (x1, y1) e (x2, y2). Depois use esta funo em uma funo chamada cortaY(x1, y1, x2, y2) que por Alan Turing, um dos primeiros cientistas da retorne a interseo da linha com o eixo y, dados os computao (algum poderia dizer que ele foi um matemtico, mas muitos dos primeiros cientistas da pontos (x1, y1) e (x2, y2). computao comearam como matemticos). Por isso, ficou conhecido como Tese de Turing. Se voc fizer um curso em Teoria da Computao, voc ter chance de ver a prova. 5.4 Funes booleanas Para te dar uma idia do que voc pode Funes podem retornar valores booleanos, o que fazer com as ferramentas que aprendeu a usar at muitas vezes conveniente por ocultar testes agora, vamos avaliar algumas funes matemticas complicados dentro de funes. Por exemplo: recursivamente definidas. Uma definio recursiva similar uma definio circular, no sentido de def ehDivisivel(x, y): que a definio faz referncia coisa que est sendo If x % y == 0: definida. Uma verdadeira definio circular no return True # verdadeiro (true), divisvel muito til:
else: return False # falso (false), no divisvel

O nome desta funo ehDivisivel (" Se voc visse esta definio em um divisvel"). comum dar a uma funo booleana nomes que soem como perguntas sim/no. dicionrio, ficaria confuso. Por outro lado, se voc ehDivisivel retorna ou True ou False para indicar se procurasse pela definio da funo matemtica fatorial, voc encontraria algo assim: x ou no divisvel por y.

vorpal: adjetivo usado para descrever algo que vorpal.

Podemos tornar a funo mais concisa 0! = 1 se tirarmos vantagem do fato de a condio da n! = n.(n-1)! instruo if ser ela mesma uma expresso booleana. Esta definio diz que o fatorial de 0 1, Podemos retorn-la diretamente, evitando e que o fatorial de qualquer outro valor, n, n totalmente o if: multiplicado pelo fatorial de n-1.
def ehDivisivel(x, y): return x % y == 0

ao:

Assim, 3! (l-se "3 fatorial" ou "fatorial de 3") 3 vezes 2!, o qual 2 vezes 1!, o qual 1 Esta sesso mostra a nova funo em vezes 0!. Colocando tudo isso junto, 3! igual 3 vezes 2 vezes 1 vezes 1, o que 6.

Se voc pode escrever uma definio recursiva de alguma coisa, voc geralmente pode escrever um programa em Python para execut-la. O primeiro passo decidir quais so os parmetros para esta funo. Com pouco esforo, voc dever Funes booleanas so freqentemente concluir que fatorial recebe um nico parmetro: usadas em comandos condicionais:
>>> ehDivisivel(6, 4) False >>> ehDivisivel(6, 3) True if ehDivisivel(x, y): print "x divisvel por y" else: print "x no divisvel por y" def fatorial(n):

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


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

Mas desnecessria.

comparao

Por outro lado, e esta a parte Como exerccio, escreva uma funo interessante, temos que fazer uma chamada estaEntre(x, y, z) que retorne True se y < x < z ou recursiva para encontrar o fatorial de n-1 e ento False se no. multiplic-lo por n:
def fatorial(n): if n == 0: return 1 else: recursivo = fatorial(n-1) resultado = n * recursivo

5.5 Mais recursividade


At aqui, voc aprendeu apenas um pequeno subconjunto da linguagem Python, mas pode ser que te interesse saber que este pequeno

Captulo 5: Funes frutferas #40

Como pensar como um cientista da Computao usando Python divisvel por outro. Uma vez que nos convencemos O fluxo de execuo para este programa que esta funo est correta -- ao testar e examinar similar ao fluxo de contagemRegressiva na Seo o cdigo -- podemos usar a funo sem examinar o cdigo novamente. 4.9. Se chamarmos fatorial com o valor 3: O mesmo tambm verdadeiro para J que 3 no 0, tomamos o segundo programas recursivos. Quando voc tem uma ramo e calculamos o fatorial de n-1 ... chamada recursiva, em vez de seguir o fluxo de J que 2 no 0, tomamos o segundo execuo, voc poderia assumir que a chamada recursiva funciona (produz o resultado correto) e ramo e calculamos o fatorial de n-1 ... ento perguntar-se, "Assumindo que eu possa J que 1 no 0, tomamos o segundo encontrar o fatorial de n-1, posso calcular o fatorial ramo e calculamos o fatorial de n-1 ... de n?" Neste caso, claro que voc pode, J que 0 0, tomamos o primeiro ramo e multiplicando por n. retornamos 1 sem fazer mais qualquer chamada Naturalmente, um pouco estranho que recursiva. uma funo funcione corretamente se voc ainda O valor retornado (1) multiplicado por nem terminou de escrev-la, mas por isso que se chama voto de confiana! n, que 1, e o resultado retornado.
return resultado

O valor retornado (1) multiplicado por n, que 2, e o resultado retornado.

O valor retornado (2) multiplicado por n, que 1, e o resultado, 6, se torna o valor de No exemplo anterior, usamos variveis temporrias retorno da chamada de funo que iniciou todo o para explicitar (spell out XXX) os passos e tornar o processo. cdigo mais fcil de depurar, mas poderamos ter Eis o diagrama de pilha para esta economizado algumas linhas: seqncia de chamadas de funo: def fatorial(n):
if n == 0: return 1 else: return n * fatorial(n-1)

5.7 Mais um exemplo

De agora em diante, tenderemos a utilizar um formato mais conciso, mas recomendamos que voc use a verso mais explcita enquanto estiver desenvolvendo cdigo. Quando ele estiver funcionando, voc pode enxug-lo se estiver se sentindo inspirado. Depois de fatorial, o exemplo mais comum de uma funo matemtica definida Os valores de retorno so mostrados recursivamente fibonacci, a qual tem a seguinte sendo passados de volta para cima da pilha. Em definio: cada quadro, o valor de retorno o valor de fibonacci(0) = 1 resultado, o qual o produto de n por recursivo.
fibonacci(1) = 1 fibonacci(n) = fibonacci(n-1) + fibonacci(n-2); def fibonacci(n):

5.6 Voto de confiana (Leap of faith)

Traduzido em Python, parecer assim:

Seguir o fluxo de execuo uma maneira de ler if n == 0 or n == 1: programas, mas que pode rapidamente se return 1 transformar em um labirinto. Uma alternativa o else: que chamamos de "voto de confiana". Quando voc return fibonacci(n-1) + fibonacci(n-2) tem uma chamada de funo, em vez de seguir o Se voc tentar seguir o fluxo de fluxo de execuo, voc assume que a funo funciona corretamente e retorna o valor execuo aqui, mesmo para valores bem pequenos de n, sua cabea explodir. Mas, de acordo com o apropriado. voto de confiana, se voc assume que as duas De fato, voc est agora mesmo chamadas recursivas funcionam corretamente, praticando este voto de confiana ao usar as ento claro que voc ter o resultado correto ao funes nativas. Quando voc chama math.cos ou junt-las. math.exp, voc no examina a implementao destas funes. Voc apenas assume que elas funcionam porque as pessoas que escreveram as 5.8 Checagem de tipos bibliotecas nativas eram bons programadores. O mesmo tambm verdade quando voc chama uma de suas prprias funes. Por O que acontece se chamamos fatorial e damos a ela exemplo, na Seo 5.4, escrevemos a funo 1.5 como argumento?: chamada ehDivisivel que determina se um nmero >>> fatorial (1.5) Captulo 5: Funes frutferas #41

Como pensar como um cientista da Computao usando Python


RuntimeError: Maximum recursion depth exceeded

Parece um caso de recursividade infinita. Mas o que ser que de fato? Existe um caso base -- quando n == 0. O problema que o valor de n nunca encontra o caso base. Na primeira chamada recursiva, o valor de n 0.5. Na prxima, ele igual a -0.5. Da em diante, ele se torna cada vez menor, mas jamais ser 0. Temos ento duas alternativas. Podemos tentar generalizar a funo fatorial para que funcione com nmeros em ponto flutuante, ou fazemos fatorial realizar a checagem de tipo de seus parmetros. A primeira chamada funo gamma e est um pouco alm do escopo deste livro. Sendo assim, ficaremos com a segunda.

(fruitful function) valor de O valor entregue como resultado retorno de uma chamada de funo. (return value) varivel Uma varivel usada para guardar temporria um valor intermedirio em um (temporary clculo complexo. variable) cdigo morto Parte de um programa que nunca (dead code) pode ser executada, muitas vezes por que ela aparece depois de uma instruo return. None Um valor especial em Python, retornado por funes que no possuem uma instruo return ou tm uma instruo return sem argumento.

Podemos usar type para comparar o tipo do parmetro com o tipo de um valor inteiro conhecido (como 1). Ao mesmo tempo em que fazemos isto, podemos nos certificar tambm de que desenvolvimen Uma estratgia de o parmetro seja positivo: to incremental desenvolvimento de programas (incremental que evita a depurao ao def fatorial (n): development) adicionar e testar somente uma if type(n) != type(1): pequena quantidade de cdigo de print "Fatorial somente definido para cada vez.
inteiros." return -1 elif n < 0: print "Fatorial somente definido para inteiros\ positivos." return -1 elif n ==0: return 1 else: return n * fatorial(n-1)

andaime Cdigo usado durante o (scaffolding) desenvolvimento do programa, mas que no faz parte do produto final. guardio Uma condio que checa e circunstncias que (guardian) manipula poderiam causar um erro.

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

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

5.9 Glossrio
funo Uma funo que produz um valor frutfera de retorno. Captulo 5: Funes frutferas #42

Como pensar como um cientista da Computao usando Python

Captulo 5: Funes frutferas #43

Como pensar como um cientista da Computao usando Python

Captulo 6: Iterao

6.1 Reatribuies
Como voc fazer mais Uma nova referir-se a antigo).:
bruno print bruno print

6.2 O comando while


Os computadores so muito utilizados para automatizar tarefas repetitivas. Repetir tarefas idnticas ou similares sem cometer erros uma coisa que os computadores fazem bem e que as pessoas fazem poorly.

talvez j tenha descoberto, permitido de uma atribuio mesma varivel. atribuio faz uma varivel existente um novo valor (sem se referir mais ao

Vimos dois programas, nLinhas e contagemRegressiva, que usam recursividade (recurso) para fazer a repetio, que tambm chamada iterao . Porque a iterao muito comum, Python tem vrias caractersticas para A sada deste programa 5 7, porque na torn-la mais fcil. A primeira delas em que vamos primeira vez que bruno impresso, seu valor 5 e dar uma olhada o comando while. na segunda vez, seu valor 7. A vrgula no final do Aqui est como fica contagemRegressiva primeiro comando print suprime a nova linha no final da sada, que o motivo pelo qual as duas com um comando while: sadas aparecem na mesma linha.
= 5 bruno, = 7 bruno

Veja uma diagrama de estado:

reatribuio

em

um

def contagemRegressiva(n): while n > 0: print n n = n-1 print "Fogo!"

Desde que removemos a recursiva, esta funo no recursiva. Com a reatribuio torna-se ainda mais importante distinguir entre uma operao de atribuio e um comando de igualdade. Como Python usa o sinal de igual ( = ) para atribuio, existe a tendncia de lermos um comando como a = b como um comando de igualdade. Mas no ! Em primeiro lugar, igualdade comutativa e atribuio no . Por exemplo, em matemtica, se a = 7 ento 7 = a. Mas em Python, o comando a = 7 permitido e 7 = a no . Alm disso, em matemtica, uma expresso de igualdade sempre verdadeira. Se a = b agora, ento, a ser sempre igual a b. Em Python, um comando de atribuio pode tornar duas variveis iguais, mas elas no tm que permanecer assim:
a = 5 b = a # a e b agora so iguais b = 3 # a e b no so mais iguais

chamada

Voc quase pode ler o comando while como se fosse Ingls. Ele significa, "Enquanto (while) n for maior do que 0, siga exibindo o valor de n e diminuindo 1 do valor de n. Quando chegar a 0, exiba a palavra Fogo!". Mais formalmente, aqui est o fluxo de execuo para um comando while: 1. Teste a condio, resultando 0 ou 1. 2. Se a condio for falsa (0), saia do comando while e continue a execuo a partir do prximo comando. 3. Se a condio for verdadeira (1), execute cada um dos comandos dentro do corpo e volte ao passo 1. O corpo consiste de todos os comandos abaixo do cabealho, com a mesma endentao.

Este tipo de fluxo chamado de um loop (ou lao) porque o terceiro passo cria um "loop" ou um lao de volta ao topo. Note que se a A terceira linha muda o valor de a mas condio for falsa na primeira vez que entrarmos no muda o valor de b, ento, elas no so mais no loop, os comandos dentro do loop jamais sero iguais. (Em algumas linguagens de programao, executados. um smbolo diferente usado para atribuio, como <- ou :=, para evitar confuso.) O corpo do loop poderia alterar o valor de uma ou mais variveis de modo que Embora a reatribuio seja eventualmente a condio se torne falsa e o loop freqentemente til, voc deve us-la com cautela. termine. Se no for assim, o loop se repetir para Se o valor das variveis muda freqentemente, isto sempre, o que chamado de um loop infinito . Uma pode fazer o cdigo difcil de ler e de depurar. fonte de diverso sem fim para os cientistas da computao a observao de que as instrues da Captulo 6: Iterao #44

Como pensar como um cientista da Computao usando Python embalagem de shampoo, "Lave, enxge, repita" computadores usam tabelas de valores para um loop infinito. conseguir uma resposta aproximada e ento realizar clculos para melhorar a aproximao. Em No caso de contagemRegressiva, alguns casos, tm havido erros nas tabelas podemos provar que o loop terminar porque underlying, o caso mais famoso sendo o da tabela sabemos que o valor de n finito, e podemos ver usada pelo processador Pentium da Intel para que o valor de n diminui dentro de cada repetio executar a diviso em ponto-flutuante. (iterao) do loop, ento, eventualmente chegaremos ao 0. Em outros casos, isto no to Embora uma tabela de logaritmos no simples de afirmar: seja mais to til quanto j foi um dia, ela ainda d um bom exemplo de iterao. O seguinte programa def sequencia(n): gera uma seqncia de valores na coluna da while n != 1: esquerda e seus respectivos logaritmos na coluna da print n, direita:
if n%2 == 0: n = n/2 else: n = n*3+1 # n par # n impar x = 1.0 while x < 10.0: print x, '\t', math.log(x) x = x + 1.0

A condio para este loop n != 1, ento A string '\t' representa um caracter de o loop vai continuar at que n seja 1, o que tornar tabulao. a condio falsa. Conforme caracteres e strings vo sendo Dentro de cada repetio (iterao) do loop, o programa gera o valor de n e ento checa se mostrados na tela, um ponteiro invisvel chamado ele par ou impar. Se ele for par, o valor de n cursor marca aonde aparecer o prximo dividido por 2. Se ele for impar, o valor substitudo caractere. Depois de um comando print, o cursor por n*3+1. Por exemplo, se o valor inicial (o normalmente vai para o incio de uma nova linha. argumento passado para seqncia) for 3, a O caractere de tabulao desloca o seqncia resultante ser 3, 10, 5, 16, 8, 4, 2, 1. cursor para a direita at que ele encontre uma das J que n s vezes aumenta e s vezes marcas de tabulao. Tabulao til para fazer diminui, no existe uma prova bvia de que n colunas de texto line up, como na sada do jamais venha a alcanar 1, ou de que o programa programa anterior: termine. Para alguns valores particulares de n, 1.0 0.0 podemos provar o trmino. Por exemplo, se o valor 2.0 0.69314718056 inicial for uma potncia de dois, ento o valor de n 3.0 1.09861228867 ser par dentro de cada repetio (iterao) do loop at que alcance 1. O exemplo anterior termina com 4.0 1.38629436112 5.0 1.60943791243 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!
6.0 7.0 8.0 9.0 1.79175946923 1.94591014906 2.07944154168 2.19722457734

Se estes valores parecem odd, lembre-se que a funo log usa a base e. J que potncias de Como um exerccio, reescreva a funo dois so to importantes em cincia da computao, nLinhas da seo 4.9 usando iterao em vez de ns freqentemente temos que achar logaritmos recurso. referentes base 2. Para fazermos isso, podemos usar a seguinte frmula:

6.3 Tabelas
Uma das coisas para qual os loops so bons para gerar dados tabulares. Antes que os computadores estivessem readily disponveis, as pessoas tinham que calcular logaritmos, senos, cossenos e outras funes matemticas mo. Para tornar isto mais fcil, os livros de matemtica continham longas tabelas listando os valores destas funes. Criar as tabelas era demorado e entediante, e elas tendiam a ser cheias de erros. Alterando o comando de sada para:
print x, '\t', math.log(x)/math.log(2.0)

o que resultar em:


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

Quando os computadores entraram em cena, uma das reaes iniciais foi "Isto timo! Podemos usar computadores para geras as tabelas, assim no haver erros." Isto veio a se tornar verdade (na maioria das vezes) mas shortsighted. Rapidamente, porm, computadores e calculadoras tornaram-se to pervasivos que as tabelas ficaram Podemos ver que 1, 2, 4 e 8 so potncias obsoletas. de dois porque seus logaritmos na base 2 so Bem, quase. Para algumas operaes, os nmeros redondos. Se precisssemos encontrar os Captulo 6: Iterao #45

Como pensar como um cientista da Computao usando Python logaritmos de outras potncias de dois, poderamos modificar o programa deste modo:
x = 1.0 while x < 100.0: print x, '\t', math.log(x)/math.log(2.0) x = x * 2.0 i = i + 1 print

A primeira linha inicializa a varivel chamada i, a qual age como um contador ou varivel de controle do loop . Conforme o loop executado, o valor de i incrementado de 1 a 6. Quando i for 7, o loop termina. A cada repetio Agora, em vez de somar algo a x a cada (iterao) do loop, mostrado o valor de 2*i, iterao do loop, o que resulta numa seqncia seguido de trs espaos. aritmtica, ns multiplicamos x por algo, resultando De novo, a vrgula no comando print numa seqncia geomtrica. O resultado : suprime a nova linha. Depois que o loop se 1.0 0.0 completa, o segundo comando print inicia uma nova linha. 2.0 1.0
4.0 8.0 16.0 32.0 64.0 2.0 3.0 4.0 5.0 6.0

A sada do programa :
2 4 6 8 10 12

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

Por causa do caractere de tabulao entre as colunas, a posio da segunda coluna no depende do nmero de dgitos na primeira coluna.

6.5 Encapsulamento e generalizao

Tabelas de logaritmos podem no ser mais teis, mas para cientistas da computao, Encapsulamento o processo de wrapping um conhecer as potncias de dois ! pedao de cdigo em uma funo, permitindo que voc tire vantagem de todas as coisas para as quais Como um exerccio, modifique este as funes so boas. Voc j viu dois exemplos de programa de modo que ele produza as potncias de encapsulamento: imprimeParidade na seo 4.5; e dois acima de 65.535 (ou seja, 216). Imprima e eDivisivel na seo 5.4 memorize-as. Generalizao significa tomar algo que O caractere de barra invertida em '\t' especfico, tal como imprimir os mltiplos de 2, e indica o incio de uma seqncia de escape. torn-lo mais geral, tal como imprimir os mltiplos Seqncias de escape so usadas para representar de qualquer inteiro. caracteres invisveis como de tabulao e de nova linha. A seqncia \n representa uma nova linha. Esta funo encapsula o loop anterior e generaliza-o para imprimir mltiplos de n: Uma seqncia de escape pode aparecer em qualquer lugar em uma string; no exemplo, a def imprimeMultiplos(n): seqncia de escape de tabulao a nica coisa i = 1 dentro da string. while i <= 6: Como voc acha que se representa uma barra invertida em uma string? string que Como um exerccio, escreva um nica
print n*i, '\t ', i = i + 1 print

produza esta sada.

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

6.4 Tabelas de duas dimenses (ou bidimensionais)

Com o argumento 4, a sada :

Uma tabela de duas dimenses uma tabela em que Agora voc provavelmente pode voc l o valor na interseo entre uma linha e uma coluna. Uma tabela de multiplicao um bom adivinhar como imprimir uma tabela de chamando imprimeMultiplos exemplo. Digamos que voc queira imprimir uma multiplicao repetidamente com argumentos diferentes. De fato, tabela de multiplicao de 1 a 6. podemos usar um outro loop: Uma boa maneira de comear escrever um loop que imprima os mltiplos de 2, i = 1 while i <= 6: todos em uma linha:
i = 1 while i <= 6: print 2*i, ' imprimeMultiplos(i) i = i + 1

',

Note o quanto este loop parecido com aquele dentro de imprimeMultiplos. Tudo o que fiz Captulo 6: Iterao #46

Como pensar como um cientista da Computao usando Python foi substituir o comando print pela chamada funo. A sada deste programa uma tabela de multiplicao:
1 2 3 4 5 6 2 4 6 8 10 12 3 6 9 12 15 18 4 8 12 16 20 24 5 10 15 20 25 30 6 12 18 24 30 36

6.6 Mais encapsulamento


O valor de i em imprimeTabMult vai de Para demonstrar de novo o encapsulamento, vamos pegar o cdigo do final da seo 6.5 e acondicion- 1 a 6. No diagrama, i agora 3. Na prxima iterao do loop i ser 4. A cada iterao do loop, lo, envolv-lo em uma funo: imprimeTabMult chama imprimeMultiplos com o valor corrente de i como argumento. O valor def imprimeTabMult(): atribudo ao parmetro n. i = 1 Dentro de imprimeMultiplos, o valor de i vai de 1 a 6. No diagrama, i agora 2. Mudar esta varivel no tem efeito sobre o valor de i em Este processo um plano de imprimeTabMult. desenvolvimento comum. Ns desenvolvemos comum e perfeitamente legal ter cdigo escrevendo linhas de cdigo fora de variveis locais diferentes com o mesmo nome. Em qualquer funo, ou digitando-as no interpretador. particular, nomes como i e j so muito usados para Quando temos o cdigo funcionando, extramos ele variveis de controle de loop. Se voc evitar utilize o embalamos em uma funo. los em uma funo s porque voc j os usou em Este plano de desenvolvimento outro lugar, voc provavelmente tornar seu particularmente til se voc no sabe, quando voc programa mais difcil de ler. comea a escrever, como dividir o programa em funes. Esta tcnica permite a voc projetar enquanto desenvolve. 6.8 Mais generalizao Como um outro exemplo de generalizao, imagine que voc precise de um programa que possa imprimir uma tabela de multiplicao de qualquer Voc pode estar pensando como podemos utilizar a tamanho, no apenas uma tabela de seis por seis. mesma varivel, i, em ambos, imprimeMultiplos e Voc poderia adicionar um parmetro a imprimeTabMult. Isto no causaria problemas imprimeTabMult: quando uma das funes mudasse o valor da def imprimeTabMult(altura): varivel?
while i <= 6: imprimeMultiplos(i) i = i + 1

6.7 Variveis locais

A resposta no, porque o i em imprimeMultiplos e o i em imprimeTabMult no so a mesma varivel.

i = 1 while i <= altura: imprimeMultiplos(i) i = i + 1

Ns substitumos o valor 6 pelo Variveis criadas dentro de uma definio de funo so locais; voc no pode parmetro altura. Se chamarmos imprimeTabMult acessar uma varivel local de fora da funo em com o argumento 7, ela mostra: que ela "mora". Isto significa que voc livre para 2 3 4 5 6 ter mltiplas variveis com o mesmo nome, desde 1 2 4 6 8 10 12 que elas no estejam dentro da mesma funo. O diagrama de pilha para este programa mostra que duas variveis chamadas i no so a mesma varivel. Elas podem se referir a valores diferentes e alterar o valor de uma no afeta outra.
3 4 5 6 7 6 8 10 12 14 9 12 15 18 21 12 16 20 24 28 15 20 25 30 35 18 24 30 36 42

Isto bom, exceto que ns provavelmente quereramos que a tabela fosse quadrada - com o mesmo nmero de linhas e colunas. Para fazer isso, adicionamos outro parmetro a imprimeMultiplos para especificar quantas colunas a tabela deveria ter. S para confundir, chamamos este novo

Captulo 6: Iterao #47

Como pensar como um cientista da Computao usando Python parmetro de altura, demonstrando que diferentes funes podem ter parmetros com o mesmo nome (como acontece com as variveis locais). Aqui est o programa completo:
def imprimeMultiplos(n, altura): i = 1 while i <= altura: print n*i, 't', i = i + 1 print def imprimeTabMult(altura): i = 1 while i <= altura: imprimeMultiplos(i, altura) i = i + 1

Dar um nome para uma seqncia de comandos torna seu programa mais fcil de ler e de depurar. Dividir um programa longo em funes permite que voc separe partes do programa, depure-as isoladamente, e ento as componha em um todo. Funes facilitam tanto recurso quanto iterao. Funes bem projetadas so freqentemente teis para muitos programas. Uma vez que voc escreva e depure uma, voc pode reutiliz-la.

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

6.10 Glossrio
reatribuio quando mais de um valor (multiple atribudo a mesma varivel assignment 1) durante a execuo do programa. iterao execuo repetida de um conjunto comandos/instrues (iteration) de (statements) usando uma chamada recursiva de funo ou um lao (loop). comando/instruo ou lao (loop) um conjunto de comandos/instrues que executam repetidamente at que uma condio de interrupo seja atingida. lao infinito um lao em que a condio de (infinite interrupo nunca ser atingida. loop) corpo (body) o conjunto de comandos/instrues que pertencem a um lao. varivel de uma varivel usada como parte da lao (loop condio de interrupo do lao. variable) tabulao um carcter especial que faz com (tab) que o cursor mova-se para a prxima parada estabelecida de tabulao na linha atual. nova-linha um carcter especial que faz com (newline) que o cursor mova-se para o incio da prxima linha.

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

para:
imprimeTabMult(i, i)

e voc ter:
1 2 3 4 5 6 7 4 6 8 10 12 14

9 12 15 18 21

16 20 24 28

25 30 35

36 42

cursor um marcador invisvel que (cursor) determina onde o prximo carcter var ser impresso.
49

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

sequncia de escape (escape sequence)

um carcter de escape () seguido por um ou mais caracteres imprimveis, usados para definir um carcter no imprimvel.

6.9 Funes

encapsular quando um programa grande e dividido em (encapsulate) complexo componentes (como funes) e

H pouco tempo mencionamos "todas as 1 N.T.: O termo multiple assignment (ou atribuio coisas para as quais as funes so boas." mltipla) usado com mais frequncia para Agora, voc pode estar pensando que coisas descrever a sintaxe a = b = c. Por este motivo exatamente so estas. Aqui esto algumas optamos pelo termo reatribuio no contexto da delas:
seo 6.1 desse captulo.

Captulo 6: Iterao #48

Como pensar como um cientista da Computao usando Python estes so isolados um do outro (pelo uso de variveis locais, por exemplo). generalizar quando algo que especfico (generalize) desnecessariamente (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 desenvolvim ento (developmen t plan) um processo definido para desenvolvimento de um programa. Neste captulo, ns demonstramos um estilo de desenvolvimento baseado em escrever cdigo para executar tarefas simples e especficas, usando encapsulamento e generalizao.

Captulo 6: Iterao #49

Como pensar como um cientista da Computao usando Python

Captulo 7: Strings

7.1 Um tipo de dado composto

voc pode ficar tentado a fazer alguma coisa assim:


comprimento = len(fruta) ultima = fruta[comprimento]

# ERRO! At aqui, vimos trs diferentes tipos de dado: int, No vai funcionar. Isto vai causar o float e string. Strings so qualitativamente diferentes dos outros dois tipos porque so feitas de seguinte erro em tempo de execuo (runtime error): IndexError: string index out of range. pedaos menores - caracteres. (ErroDeIndice: ndice da string fora do intervalo). A Tipos que consistem de pedaos razo que no existe 6 letra em "banana". J que menores so chamados tipos de dados compostos. comeamos a contar do zero, as seis letras so Dependendo do que estejamos fazendo, pode ser numeradas de 0 a 5. Para pegar o ltimo caractere, que precisemos tratar um tipo de dado composto temos que subtrair 1 de comprimento: como uma coisa nica, ou pode ser que queiramos comprimento = len(fruta) acessar suas partes. Esta ambigidade til.

O operador colchete seleciona um nico caractere de uma string.:


>>> fruta = "banana" >>> letra = fruta[1] >>> print letra

ultima = fruta[comprimento-1]

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

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

7.3 Travessia e o loop for


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

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

Este loop percorre a string e exibe cada letra em sua prpria linha. A condio do loop indice < len(fruta), assim, quando ndice igual ao comprimento da string, a condio se torna falsa, e o corpo do loop no executado. O ltimo caractere A expresso entre colchetes chamada acessado aquele com o ndice len(fruta)-1, que de ndice. Um ndice especifica um membro de um vem a ser o ltimo caractere da string. conjunto ordenado, neste caso o conjunto de Como um exerccio, escreva uma funo caracteres da string. O ndice indica aquele membro que voc quer, da seu nome. Ele pode ser qualquer que tome uma string como argumento e devolva suas letras de trs para frente, uma por linha. expresso inteira. Usar um ndice para percorrer um conjunto de valores to comum que Python oferece uma sintaxe alternativa simplificada - o 7.2 Comprimento loop for: A funo len retorna o nmero de caracteres de uma string:
>>> fruta = "banana" >>> len(fruta) 6 for char in fruta: print char

A cada vez atravs do loop, o prximo caractere da string atribudo varivel char. O loop continua at que no reste mais caracteres. O exemplo seguinte mostra como usar

Para pegar a ltima letra de uma string, Captulo 7: Strings #50

Como pensar como um cientista da Computao usando Python concatenao e um loop for para gerar uma srie abecedrio. "Abecedrio" se refere a uma srie ou lista na qual os elementos aparecem em ordem alfabtica. Por exemplo, no livro de Robert McCloskey's Make Way for Ducklings, os nomes dos "ducklings" so Jack, Kack, Lack, Mack, Nack, Ouack, Pack e Quack. O loop seguinte, produz como sada aqueles nomes, em ordem:
prefixos = "JKLMNOPQ" sufixo = "ack" for letra in prefixos: print letra + sufixo 'ban' >>> fruta[3:] 'ana'

O que voc acha de s[:] significa?

7.5 Comparao de strings


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

A sada deste programa :


Jack Kack Lack Mack Nack Oack Pack Qack

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


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

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

7.4 Fatias de strings

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

Uma maneira comum de resolver este Um segmento de uma string chamado de uma problema converter as strings para um formato fatia. Selecionar uma fatia similar a selecionar um padro, seja todas minsculas, ou todas maisculas, caractere: antes de realizar a comparao. Um problema mais difcil fazer o programa perceber que zebras no >>> s = "Pedro, Paulo e Maria" so frutas. >>> print s[0:5]
Pedro >>> print s[7:12] Paulo >>> print s[16:21] Maria

7.6 Strings so imutveis

tentador usar o operador [] no lado esquerdo de O operador [n:m] retorna a parte da uma expresso de atribuio, com a inteno de string do "n-simo" caractere ao "m-simo" alterar um caractere em uma string. Por exemplo: caractere, incluindo o primeiro mas excluindo o saudacao = "Al, mundo!" ltimo. Este comportamento no intuitivo; ele faz # ERRO! mais sentido se voc imaginar os ndices apontando saudacao[0] = 'E' para os intervalos entre os caracteres, como no print saudacao seguinte diagrama: Em vez de produzir a sada El, Mundo!, este cdigo produz o erro em tempo de execuo (runtime error): TypeError: object doesn't support item assignment (ErroDeTipo: objeto no d suporte atribuio de item.) Strings so imutveis, o que significa que voc no pode mudar uma string que j existe. O melhor que voc pode fazer criar uma nova string que seja uma variao da original: Se voc omitir o primeiro ndice (antes dos dois pontos ":"), a fatia comea do incio da string. Se voc omitir o segundo ndice, a fatia vai at o final da string. Assim:
>>> fruta = "banana" >>> fruta[:3] 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.

Captulo 7: Strings #51

Como pensar como um cientista da Computao usando Python

7.7 Uma funo find (encontrar)


O que faz a seguinte funo?:
def find(str, ch): indice = 0 while indice < len(str): if str[indice] == ch: return indice indice = indice + 1 return -1

7.9 O mdulo string


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

O mdulo string inclui uma funo chamada find (encontrar) que faz a mesma coisa que a funo que escrevemos. Para cham-la, temos que especificar o nome do mdulo e o nome da Num certo sentido, find (encontrar) o funo usando a notao de ponto.: oposto do operador []. Em vez de pegar um ndice e extrair o caractere correspondente, ela pega um >>> fruta = "banana" caractere e encontra (finds) em qual ndice aquele >>> indice = string.find(fruta, "a") caractere aparece. Se o caractere no encontrado, >>> print indice a funo retorna -1. 1 Este exemplo demonstra um dos Este o primeiro exemplo que vemos de uma instruo return dentro de um loop. Se benefcios dos mdulos - eles ajudam a evitar str[indice] == ch, a funo retorna imediatamente, colises entre nomes de funes nativas e nomes de funes definidas pelo usurio. Usando a notao de abandonando o loop prematuramente. ponto podemos especificar que verso de find Se o caractere no aparece na string, (encontrar) ns queremos. ento o programa sai do loop normalmente e De fato, string.find mais generalizada retorna -1. que a nossa verso. Primeiramente, ela pode Este padro de computao s vezes encontrar substrings, no apenas caracteres: chamado de travessia "eureka", porque to logo ele encontra (find) o que est procurando, ele pode >>> string.find("banana", "na") 2 gritar "Eureka!" e parar de procurar. Alm disso, ela recebe um argumento Como um exerccio, modifique a funo find (encontrar) de modo que ela receba um adicional que especifica o ndice pelo qual ela deve terceiro parmetro, o ndice da string por onde ela comear sua procura: deve comear sua procura. >>> string.find("banana", "na", 3)
4

7.8 Iterando e contando


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

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

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

7.10 Classificao de caracteres


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

Este programa demonstra um outro padro de computao chamado de contador . A varivel contador inicializada em 0 e ento incrementada cada vez que um a encontrado. (Incrementar o mesmo que aumentar em um; o oposto de decrementar, e no tem relao com excremento, que um substantivo.) Quando se sai do loop, contador guarda o resultado - o nmero total de a's.

A string string.lowercase contm todas as letras que o sistema considera como sendo minsculas. Similarmente, string.uppercase contm todas as letras maisculas. Tente o seguinte e veja o Como um exerccio, encapsule este que voc obtm: cdigo em uma funo chamada contaLetras, e generalize-a de modo que possa aceitar uma string >>> print string.lowercase >>> print string.uppercase e uma letra como parmetros. Como um segundo exerccio, reescreva Ns podemos usar essas constantes e esta funo de modo que em vez de percorrer a string, ela use a verso com trs parmetros de find (encontrar) para classificar caracteres. Por exemplo, se find(lowercase, ch) retorna um valor find (encontrar) da seo anterior. outro que no -1, ento ch deve ser minsculo:
>>> print string.digits

Captulo 7: Strings #52

Como pensar como um cientista da Computao usando Python incrementa aumentar o valor de uma varivel r em 1. Como uma alternativa, podemos tirar (increment ) vantagem do operador in, que determina se um caractere aparece em uma string: decrement diminuir o valor de uma varivel em ar 1. def eMinusculo(ch): (decrement return ch in string.lowercase ) Ainda, como uma outra alternativa, podemos usar o operador de comparao: espaamen Qualquer um dos caracteres que to move o cursor sem imprimir def eMinusculo(ch): (whitespac caracteres visveis. A constante return 'a' <= ch <= 'z' e) string.whitespace contm todos os caracteres de espaamento. Se ch estiver entre a e z, ele deve ser uma letra minscula. Como um exerccio, discuta que verso de eMinusculo voc acha que ser a mais rpida. Voc pode pensar em outras razes alm da velocidade para preferir uma em vez de outra? Outra constante definida no mdulo string pode te surpreender quando voc executar um print sobre ela:
>>> print string.whitespace def eMinusculo(ch): return string.find(string.lowercase, ch) != -1

7.11 Glossrio2
tipo de dado composto (compound data type) Um tipo de dado em que os valores so compostos de componentes, ou elementos, que podem ser tratados como valores separados.

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

atravessar Iterar atravs dos elementos (traverse) definidos, executando uma operao similar em cada. ndice Uma varivel ou valor usado para (index) 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 (counter) alguma 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 branco (whitespace ) Qualquer caractere que move o cursor sem imprimir caracteres visveis. A constante string.whitespace contm todos os caracteres de espao em branco.

7.11 Glossrio
tipo de dado composto (compound data type) Um tipo de dado no qual o valor consiste de componentes, ou elementos, que so eles mesmos valores.

travessia Iterar atravs dos elementos de um (traverse) conjunto, realizando uma operao similar em cada um deles. ndice Uma varivel ou valor usados para (index) selecionar um membro de um conjunto ordenado, como um caractere em uma string. parte de uma string fatia (slice) Uma 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 coisa, usualmente (counter) alguma inicializada em zero e ento incrementada.

Captulo 7: Strings #53

Como pensar como um cientista da Computao usando Python

Captulo 7: Strings #54

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 lista so chamados elementos. Listas so similares a strings, que so conjuntos ordenados de caracteres, com a diferena que os elementos de uma lista podem possuir qualquer tipo. Listas e strings XXX e outras coisas que se comportam como conjuntos ordenados XXX so chamados seqncias.

'defenestrar'] >>> numeros = [17, 123] >>> vazio = [] >>> print vocabulario, numeros, vazio ['melhorar', 'castigar', 'defenestrar'] [17, 123] []

8.2 Acessado elementos

8.1 Valores da lista

A sintaxe para acessar os elementos de uma lista a mesma que a sintaxe para acessar os caracteres de Existem vrias maneiras de criar uma nova lista; a uma string XXX o operator colchete ([]). A expresso mais simples envolver os elementos em colchetes dentro dos colchetes especifica o ndice. Lembre-se que os ndices iniciam em 0: ([ e ]):
>>> [10, 20, 30, 40] >>> ['spam', 'bungee', 'swallow'] >>> print numeros[0] >>> numeros[1]= 5

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

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

Uma lista dentro de outra lista dita estar aninhada. Listas que contm inteiros consecutivos so comuns, ento Python fornece uma maneira simples de cri-los:
>>> range(1,5) [1, 2, 3, 4]

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

Se voc tentar ler ou escrever um elemento que no existe, voc recebe um erro de tempo de execuo (runtime error):
>>> numeros[2]=5 IndexError: list assignment index out of range

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

Se existe um terceiro argumento, ele especifica o espao entre os valores sucessivos, que chamado de tamanho do passo. Este exemplo numeros[-1] o ltimo elemento da conta de 1 at 10 em passos de 2: lista, numeros[-2] o penltimo e numeros[-3] no existe. comum utilizar uma varivel de lao como um ndice da lista: Finalmente, existe uma lista especial que no contm elementos. Ela chamada lista >>> cavaleiros = ['guerra', 'fome', 'peste', vazia, e sua notao []. 'morte'] Com todas estas formas de criar listas, seria decepcionante se no pudssemos atribuir valores de listas a variveis ou passar listas como parmetros a funes. Felizmente, podemos.
>>> vocabulario = ['melhorar', 'castigar', \ i = 0 while i < 4: print cavaleiros[i] i = i + 1 >>> range(1, 10, 2) [1, 3, 5, 7, 9]

Este lao while conta de 0 at 4. Quando a varivel do lao i 4, a condio falha e o lao se

Captulo 8: Listas #55

Como pensar como um cientista da Computao usando Python encerra. Desta forma o corpo do lao executado somente quando i 0, 1, 2 e 3.

8.5 Listas e laos for

Em cada vez dentro do lao, a varivel i utilizada como um ndice para a lista, exibindo o i- O lao for que vimos na Seo 7.3 tambm funciona simo elemento. Este padro de computao com listas. A sintaxe generalizada de um lao for : chamado de percurso na lista. for VARIVEL in LISTA:
CORPO

8.3 Comprimento da lista

Esta declarao equivalente a:


>>> i = 0 while i < len(LIST): VARIABLE = LIST[i] XXX BODY i = i + 1

A funo len devolve o comprimento de uma lista. uma boa idia utilizar este valor como o limite superior de um lao ao invs de uma constante. Desta forma, se o tamanho da lista mudar, voc no precisar ir atravs de todo o programa O lao for mais conciso porque modificando todos os laos; eles funcionaro podemos eliminar a varivel do lao, i. Aqui est o corretamente para qualquer tamanho de lista: lao anterior escrito com um`lao for:
>>> cavaleiros = ['guerra', 'fome', 'peste', 'morte'] i = 0 while i < len(cavaleiros): print cavaleiros[i] i = i + 1 >>> for cavaleiro in cavaleiros: print cavaleiro

Quase se l como Portugus: "For (para cada) cavaleiro in (na lista de) cavaleiros, print (imprima o nome do) cavaleiro."

Qualquer expresso de lista pode ser A ltima vez que o corpo do lao utilizada num lao for: executado, i len(cavaleiros) - 1, que o ndice do ltimo elemento. Quando i igual a len(cavaleiros), >>> for numero in range(20): a condio falha e o corpo no executado, o que if numero % 2 == 0: uma boa coisa, porque len(cavaleiros) no um print numero ndice legal. Embora uma lista possa conter uma >>> for fruta in ["banana", "abacaxi", "laranja"]: outra lista, a lista aninhada ainda conta como um print "Eu gosto de comer " + fruta + "s!" elemento simples. O comprimento desta lista O primeiro exemplo exibe todos os quatro: nmeros pares entre zero e dezenove. O segundo exemplo expressa o entusiasmo por vrias frutas. >>> [`spam!', 1, ['Brie', 'Roquefort', \
'Pol l Veq'], [1, 2 3]]

Como um exerccio, escreva um lao que percorra a lista anterior e exiba o comprimento de 8.6 Operaes em listas cada elemento. O que acontece se voc manda um inteiro para len? O operador + concatena listas:

8.4 Membros de uma lista

in um operador lgico que testa se um elemento membro de uma seqncia. Ns o utilizamos na Similarmente, o operador * repete uma Seo 7.10 com strings, mas ele tambm funciona lista um nmero dado de vezes: com listas e outras seqncias:
>>> cavaleiros = ['guerra', 'fome', 'peste', 'morte'] >>> 'peste' in cavaleiros True >>> 'depravao' in cavaleiros False >>> [0, >>> [1, [0] * 4 0, 0, 0] [1, 2, 3] * 3 2, 3, 1, 2, 3, 1, 2, 3]

>>> >>> >>> >>> [1,

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

O primeiro exemplo repete [0] quatro vezes. O segundo exemplo repete a lista [1, 2, 3] trs Uma vez que 'peste' um membro da vezes. lista cavaleiros, o operador in devolve verdadeiro. Uma vez que depravao no est na lista, in devolve falso. 8.7 Fatiamento de listas Podemos utilizar tambm o not em combinao com o in para testar se um elemento A operao de fatiamento que vimos na Seo 7.4 no um membro de uma lista: tambm funciona sobre listas:
>>> ``depravao`` not in cavaleiros True >>> lista = ['a', 'b', 'c', 'd', 'e', 'f'] >>> lista[1:3]

Captulo 8: Listas #56

Como pensar como um cientista da Computao usando Python


['b', 'c'] >>> lista[:4] ['a', 'b', 'c', 'd'] >>> lista[3:] ['d', 'e', 'f'] >>> lista[:] ['a', 'b', 'c', 'd', 'e', 'f'] >>> lista = ['a', 'b', 'c', 'd', 'e', 'f'] >>> del lista[1:5] >>> print lista ['a', 'f']

Como de costume, fatias selecionam todos os elementos at, mas no incluindo, o segundo ndice.

8.8 Listas so mutveis

8.10 Ojetos e valores

Diferente das strings, as listas so mutveis, o que Se executamos estas declaraes de atribuio: significa que podemos modificar seus elementos. >>> a = "banana" Utilizando o operador colchete no lado esquerdo de >>> b = "banana" uma atribuio, podemos atualizar um de seus sabemos que a e b se referem a uma elementos: string com as letras banana. Mas no podemos dizer >>> fruta = ["banana", "abacaxi", "laranja"] se elas apontam para a mesma string.
>>> fruta[0] = "abacate" >>> fruta[-1] = "tangerina" >>> print fruta ['abacate', 'abacaxi', 'tangerina']

Existem dois possveis estados:

Com o operador de fatiamento podemos atualizar vrios elementos de uma vez: Em um caso, a e b se referem a duas coisas diferentes que possuem o mesmo valor. No segundo caso, elas se referem mesma coisa. Estas Tambm podemos remover elementos "coisas" possume nomes - elas so chamadas objetos. Um objeto algo ao qual uma varivel de uma lista atribuindo a lista vazia a eles: pode se referenciar.
>>> lista = ['a', 'b', 'c', 'd', 'e', 'f'] >>> lista[1:3] = [] >>> print lista ['a', 'd', 'e', 'f'] >>> lista = ['a', 'b', 'c', 'd', 'e', 'f'] >>> lista[1:3] = ['x', 'y'] >>> print lista ['a', 'x', 'y', 'd', 'e', 'f']

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

Todo objeto possui um identificador nico, que podemos obter com a funo id. Exibindo o identificador de a e b, podemos dizer se elas se referem ao mesmo objeto.
>>> id(a) 135044008 >>> id(b) 135044008

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

8.9 Remoo em lista


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

Ento o diagrama de estado fica assim:

Como voc deveria esperar, del trata valores negativos e causa erros de tempo de execuo se o ndice estiver fora da faixa.

a e b possuem o mesmo valor mas no Voc tambm pode utilizar uma faixa se referem ao mesmo objeto. como um ndice para del: Captulo 8: Listas #57

Como pensar como um cientista da Computao usando Python

8.11 Apelidos

8.13 Lista como parmetro

Uma vez que variveis se referem a objetos, se Passar uma lista como um argumento passa atribuimos uma varivel a uma outra, ambas as realmente uma referncia lista, no uma cpia da variveis se referem ao mesmo objeto: lista. Por exemplo, a funo cabeca pega uma lista como parmetro e devolve a cabea da lista, ou seja, >>> a = [1, 2, 3] seu primeiro elemento:
>>> b = a

Neste caso, o diagrama de estado se parece com isto:

>>> def cabeca(lista): return lista[0]

Eis como ela utilizada:


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

Uma vez que a lista possui dois nomes diferentes, a e b, dizemos que ela est "apelidada" (aliased). Mudanas feitas em um apelido afetam o outro nome:
>>> b[0] = 5 >>> print a [5, 2, 3]

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

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.

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

8.12 Clonando listas


Se queremos modificar uma lista e tambm manter uma cpia da original, preciamos ter condies de fazer uma cpia da prpria lista, no apenas uma referncia. Este processo algumas vezes chamado clonagem, para evitar a ambigidade da palavra "cpia".

utilizada:
>>> >>> >>> [2,

Aqui

est

maneira

como

ela

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

Se uma funo devolve uma lista, ela uma referncia lista. Por exemplo, cauda A maneira mas fcil de clonar uma lista devolve devolve uma lista que contm todos menos o utilizar o operador de fatia: primeiro elemento de uma determinada lista:
>>> >>> >>> [1, a = [1, 2, 3] b = a[:] print b 2, 3] >>> def cauda(lista): return lista[1:]

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

utilizada:
>>> >>> >>> [2,

Aqui

est

maneira

como

ela

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

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

Como exerccio, desenhe um diagrama de estado para``a`` e b antes e depois desta mudana.

8.14 Lista aninhadas


Uma lista aninhada uma lista que aparece como um elemento de uma outra lista. Nesta lista, o

Captulo 8: Listas #58

Como pensar como um cientista da Computao usando Python terceiro elemento uma lista aninhada: Um argumento opcional chamado um delimitador pode ser utilizado para especificar >>> lista = ["alo", 2.0, 5, [10, 20]] qual caracter utilizar como limites da palavra. O Se exibimos lista[3], obtemos [10, 20]. exemplo a seguir utiliza a string va: Para extrairmos um elemento de uma lista >>> string.split(poesia, 'va') aninhada, podemos agir em duas etapas:
>>> elem = lista[3] >>> elem[0] 10 ['O or', 'lho no car', 'lho...']

na lista.

Perceba que o delimitador no aparece

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

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

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

Como split, join recebe um delimitador que inserido entre os elementos:


>>> string.join(lista, '_') 'O_orvalho_no_carvalho...'

8.15 Matrizes
Listas aninhadas so freqentemente utilizadas para representar matrizes. Por exemplo, a matriz:

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

8.17 Glossrio
poderia ser representada como:
>>> matriz = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

lista (list) Uma coleo denominada de objetos, onde cada objeto identificado por um ndice. ndice Uma varivel inteira ou valor que (index) indica um elemento de uma lista. elemento Um dos valores em uma lista(ou seqncia). O operador (element) outra colchete seleciona elementos de uma lista. seqncia Qualquer um dos tipos de dados que (sequence) consiste de um conjunto ordenado de elementos, com cada elemento identificado por um ndice. Uma lista que um elemento de uma outra lista. O acesso seqencial elemento em uma lista. de cada

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

Ou podemos extrair um nico elemento da matriz utilinado a forma de duplo ndice:


>>> matriz[1][1] 5

O primeiro ndice seleciona a linha, e o lista segundo ndice seleciona a coluna. Embora esta aninhada maneira de representar matrizes seja comum, ela (nested list) no a nica possibilidade. Uma pequena variao utilizar uma lista de colunas ao invs de uma lista percurso na lista (list de linhas. traversal) Mais adiante veremos uma alternativa objeto mais radical utilizando um dicionrio. (object)

Um coisa a qual uma varivel pode se referir.

8.16 Strings e listas


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

apelidos Mltiplas variveis que contm (aliases) referncias ao mesmo objeto. clonar Criar um novo objeto que possui o (clone) mesmo valor de um objeto existente. Copiar a referncia a um objeto cria um apelido (alias) mas no clona o objeto. delimitador Um caracter uma string utilizados (delimiter) para indicar onde uma string deveria ser dividida(split).

Captulo 8: Listas #59

Como pensar como um cientista da Computao usando Python

Captulo 9: Tuplas

9.1 Mutabilidade e tuplas


At agora, voc tem visto dois tipos compostos: strings, que so compostos de caracteres; e listas, que so compostas de elementos de qualquer tipo. Uma das diferenas que notamos que os elementos de uma lista podem ser modificados, mas os caracteres em uma string no. Em outras palavras, strings so imutveis e listas so mutveis.

9.2 Atribuies de tupla


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

H um outro tipo em Python chamado Se voc tiver que fazer isso com tupla (tuple) que similar a uma lista exceto por ele frequncia, esta abordagem se torna incmoda. ser imutvel. Sintaticamente, uma tupla uma lista Python fornece uma forma de atribuio de tupla de valores separados por vrgulas: que resolve esse problema elegantemente:
>>> tupla = 'a', 'b', 'c', 'd', 'e'

Embora no seja necessrio, convencional colocar tuplas entre parnteses:

O lado esquedo uma tupla de variveis; o lado direito uma tupla de valores. Cada valor atribudo sua respectiva varivel. >>> tupla = ('a', 'b', 'c', 'd', 'e') Para criar uma tupla com um nico Todas as expresses do lado direito so avaliadas antes de qualquer das atribuies. Esta elemento, temos que incluir uma vrgula final: caracterstica torna as atribuies de tupla bastante versteis. >>> t1 = ('a',) Naturalmente, o nmero de variveis na esquerda e o nmero de valores na direita deve ser Sem a vrgula, Python entende ('a') como igual: uma string entre parnteses:
>>> t2 = ('a') >>> type(t2) <type 'string'> >>> a, b, c, d = 1, 2, 3 ValueError: unpack tuple of wrong size >>> type(t1) <type 'tuple'>

>>> a, b = b, a

Questes de sintaxe de lado, as 9.3 Tuplas como valores de retorno operaes em tuplas so as mesmas operaes das listas. O operador ndice seleciona um elemento da Funes podem retornar tuplas como valor de tupla. retorno. Por Exemplo, ns poderamos escrever >>> tupla = ('a', 'b', 'c', 'd', 'e') uma funo que troca dois parmetros entre si:
>>> tupla[0] 'a'

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


>>> tupla[1:3] ('b', 'c')

def troca(x, y): return y, x

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

Neste caso, no existe uma grande Mas se tentarmos modificar um dos vantagem em fazer de troca (swap) uma funo. De elementos de uma tupla, teremos um erro: fato, existe um perigo em tentar encapsular troca, o >>> tupla[0] = 'A' qual a tentao de cometer o seguinte erro:
TypeError: object doesn't support item assignment

Naturalmente, mesmo que no possamos modificar os elementos de uma tupla, podemos substitu-la por uma tupla diferente:
>>> tupla = ('A',) + tupla[1:] >>> tupla ('A', 'b', 'c', 'd', 'e')

def troca(x, y): x, y = y, x

# versao incorreta

forma:
troca(a, b)

Se ns chamarmos esta funo desta

ento a e x so apelidos para um mesmo valor. Mudar x dentro da funo troca, faz com que x se referencie a um valor diferente, mas sem efeito sobre a dentro de __main__. Do mesmo modo, a mudana em y no tem efeito sobre b. Captulo 9: Tuplas #60

Como pensar como um cientista da Computao usando Python Esta funo roda sem produzir uma Vamos realizar um teste desta funo mensagem de erro, mas ela no faz o que com uma lista de oito elementos. Para efeitos de pretendemos. Este um exemplo de um erro depurao, uma boa idia comear com uma lista semntico. pequena. Como exerccio, desenhe um diagrama de estado pra esta funo de modo que voc possa ver porque ela no funciona.
>>> listaAleatoria(8) 0.15156642489 0.498048560109 0.810894847068 0.360371157682 0.275119183077 0.328578797631 0.759199803101 0.800367163582

9.4 Nmeros aleatrios

A maioria dos programas de computador fazem a mesma coisa sempre que so executados, ento, podemos dizer que eles so determinsticos. Os nmeros gerados por random so Determinismo em geral uma coisa boa, se ns supostamente uniformemente distribudos, o que esperamos que um clculo d sempre o mesmo significa que cada valor tem uma probabilidade resultado. Entretanto, para algumas aplicaes igual de acontecer. queremos que o computador se torne imprevisvel. Se ns dividirmos a faixa de valores Jogos so um exemplo bvio, mas existem outros. possveis em intervalos do mesmo tamanho, e Fazer um programa realmente no- contarmos o nmero de vezes que um determinado determinstico se mostra no ser to fcil, mas valor aleatrio caiu em seu respectivo intervalo, ns existem maneiras de faz-lo ao menos parecer no- devemos obter o mesmo nmero aproximado de determinstico. Uma dessas maneiras gerar valores em cada um dos intervalos. nmeros aleatrios e us-los para determinar o Ns podemos testar esta teoria resultado de um programa. Python tem uma funo nativa que gera nmeros pseudo aleatrios, os escrevendo um programa que divida a faixa de quais no so verdadeiramente aleatrios no valores em intervalos e conte o nmero de valores sentido matemtico, mas para os nossos propsitos de cada intervalo. eles so. O mdulo random contm uma funo chamada random que retorna um nmero em 9.6 Contando ponto flutuante (floating-point number) entre 0.0 e 1.0. Cada vez que voc chama random, voc recebe Uma boa maneira de abordar problemas como esse o prximo nmero de uma longa srie. Para ver dividir o problema em subproblemas, e encontrar uma amostra, execute este loop: um subproblema que se enquadre em um padro de soluo computacional que voc j tenha visto import random antes. Neste caso, queremos percorrer uma lista de nmeros e contar o nmero de vezes que valor se encaixa em um determinado intervalo. Isso Para gerar um nmero aleatrio ente soa familiar. Na Seo 7.8, ns escrevemos um 0.0 e um limite superior, digamos superior, programa que percorria uma string e contava o nmero de vezes que uma determinada letra multiplique x por superior. aparecia. Como exerccio, gere um nmero Assim, podemos prosseguir copiando o aleatrio entre 'inferior' e 'superior'. programa original e adaptando-o para o problema Como exerccio adicional, gere um atual. O programa original era: nmero inteiro aleatrio entre 'inferior' e contador = 0 'superior', inclusive os dois extremos.
for i in range(10): x = random.random() print x

9.5 Lista de nmeros aleatrios


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

for letra in fruta: if letra == 'a': contador = contador + 1 print contador

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

Captulo 9: Tuplas #61

Como pensar como um cientista da Computao usando Python


print contador 0.5 to 0.625 0.625 to 0.75 0.75 to 0.875 0.875 to 1.0

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

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

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

9.7 Vrios intervalos


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

Com uma lista de 1000 valores, este cdigo vai produzir esta lista de quantidades de Mas com quatro intervalos, comea a valores em cada intervalo: ficar desconfortvel.: [138, 124, 128, 118, 130, 117, 114, 131]
intervalo1 intervalo2 intervalo3 intervalo4 = = = = noIntervalo(a, noIntervalo(a, noIntervalo(a, noIntervalo(a, 0.0, 0.25) 0.25, 0.5) 0.5, 0.75) 0.75, 1.0)

Existem aqui dois problemas. Um que temos que criar novos nomes de varivel para cada resultado. O outro que temos que calcular os limites de cada intervalo. Vamos resolver o segundo problema primeiro. Se o nmero de intervalos numeroDeIntervalos, ento a largura de cada intervalo 1.0 / numeroDeIntervalos.

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

9.8 Uma soluo em um s passo

Vamos usar um lao (loop) para calcular a faixa, ou largura, de cada intervalo. A varivel do Embora este programa funcione, ele no to eficiente quanto poderia ser. Toda vez que ele loop, i, conta de 0 at numeroDeIntervalos-1: chama noIntervalo, ele percorre a lista inteira. larguraDoIntervalo = 1.0 / numeroDeIntervalos Conforme o nmero de intervalos aumenta, a lista for i in range(numeroDeIntervalos): ser percorrida um bocado de vezes. Seria melhor fazer uma nica passagem pela lista e calcular para cada valor o ndice do intervalo ao qual o valor pertena. Ento podemos Para calcular o limite inferior (inferior) incrementar o contador apropriado. de cada intervalo, ns multiplicamos a varivel do Na seo anterior, pegamos um ndice, i, loop (i) pela largura do intervalo (larguraDoIntervalo). O limite superior (superior) e o multiplicamos pela larguraDoIntervalo para est exatamente uma "largura de intervalo" acima. encontrar o limite inferior daquele intervalo. Agora queremos pegar um valor entre 0.0 e 1.0 e Com numeroDeIntervalos = 8, o encontrar o ndice do intervalo ao qual ele se encaixa. resultado :
0.0 to 0.125 0.125 to 0.25 0.25 to 0.375 0.375 to 0.5 inferior = i * larguraDoIntervalo superior = inferior + larguraDoIntervalo print "do" inferior, "ao", superior

J que este problema o inverso do problema anterior, podemos imaginar que deveramos dividir por larguraDoIntervalo em vez de multiplicar. Esta suposio est correta. J Captulo 9: Tuplas #62 que larguraDoIntervalo = 1.0 /

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

histograma Uma lista de inteiros na qual cada (histogram) elemento conta o nmero de vezes que algo acontece.

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

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

tupla (tuple) Tipo sequencial similar as listas com exceo de que ele imutvel. Podem ser usadas Tuplas sempre que um tipo imutvel for necessrio, por exemplo uma "chave (key)" em um dicionrio Atribuio a Atribuio a todos os elementos de tupla (tuple uma tupla feita num nico comando assignment) de atribuo. A atribuio aos elementos ocorre em paralelo, e no em sequncia, tornando esta operao til para swap, ou troca recproca de valores entre variveis (ex: a,b=b,a). determinsti Um programa que realiza a mesma co coisa sempre que executado. (determinist ic) pseudo aleatrio (pseudoran dom) Uma sequncia de nmeros que parecem ser aleatrios mas so na verdade o resultado de uma computao "determinstica" Captulo 9: Tuplas #63

Como pensar como um cientista da Computao usando Python

Captulo 9: Tuplas #64

Como pensar como um cientista da Computao usando Python

Captulo 10: Dicionrios

Os tipos compostos que voce aprendeu - strings, os nomes de varias frutas e o numero de cada fruta listas e tuplas - utilizam inteiros como indices. Se em no estoque: voce tentar utilizar qualquer outro tipo como >>> inventario = {'abacaxis': 430, 'bananas': indice, voce receber um erro. Dicionrios sao similiares a outros tipos compostos exceto por eles poderem user qualquer tipo imutavel de dados como indice. Como exemplo, nos criaremos um dicionrio para traduzir palavras em Ingls para Espanhol. Para esse dicionrio, os indices sero strings. Uma maneira de criar um dicionario comecando com um dicionrio vazio e depois adiconando elementos. Um dicionrio vazio denotado assim {}:
>>> ing2esp = {} >>> ing2esp['one'] = 'uno' >>> ing2esp['two'] = 'dos' 312, \ 'laranjas': 525, 'peras': 217} >>> print inventario {'laranjas': 525, 'abacaxis': 430, 'peras': 217, \ 'bananas': 312}

Se alguem comprar todas as peras, podemos remover a entrada do dicionrio:


>>> del inventario['peras'] >>> print inventario {'laranjas': 525, 'abacaxis': 430, 'bananas': 312}

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

A primeira atribuio cria um dicionario chamado ing2esp; as outras atribuies adicionam novos elementos para o dicionrio. Nos podemos imprimir o valor corrente de um dicionario da maneira usual:
>>> print ing2esp {'one': 'uno', 'two': 'dos'}

A funo len tambm funciona com dicionrios; retornando o nmero de pares chavevalor:
>>> len(inventario) 4

Os elementos de um dicionrio aparecem em uma lista separada por vrgulas. Cada entrada contm um indice e um valor separado por dois-pontos. Em um dicionrio, os ndices sao chamados de chaves, entao os elementos so chamados de pares chave-valor.

10.2 Mtodos dos Dicionrios

Outra maneira de criar dicionrios fornecendo uma lista de pares chaves-valor Um mtodo parecido com uma funo - possui parametros e retorna valores - mas a sintaxe utilizando a mesma sintaxe da ltima sada. diferente. Por exemplo, o metodo keys recebe um >>> ing2esp = {'one': 'uno', 'two': 'dos', \ dicionrio e retorna uma lista com as chaves, mas 'three': 'tres'} em vez de usarmos a sintaxe de funo Se nos imprimirmos o valor de ing2esp keys(ing2esp), nos usamos a sintaxe de mtodo ing2esp.keys(): novamente, nos teremos uma surpresa:
>>> print ing2esp {'one': 'uno', 'three': 'tres', 'two': 'dos'} >>> ing2esp.keys() ['one', 'three', 'two']

Dessa forma o ponto especifica o nome Os pares chave-valor no esto em ordem! Felizmente, no a motivos para se da funo, keys, e o nome do objeto em que deve ser preocupar com a ordem, desde que os elementos do aplicada a funo, ing2esp. Os parenteses indicam dicionrio nunca sejam indexados com indices que esse mtodo no possui parameteros. inteiros. Podemos usar as chaves para buscar os Ao invs de chamarmos um mtodo, valores correspondentes: dizemos que ele invocado, nesse caso, ns podemos dizer que ns estamos invocando keys do >>> print ing2esp['two'] objeto ing2esp. 'dos' A chave 'two' retornou o valor 'dos' O mtodo values parecido; retorna a mesmo pensando que retornaria o terceiro par lista de valores de um dicionrio: chave-valor.
>>> ing2esp.values() ['uno', 'tres', 'dos']

10.1 Operaes dos Dicionrios


O comando del remove um par chave-valor de um dicionrio. Por exemplo, o dicionrio abaixo contem

O mtodo items retorna os dois, na forma de uma lista de tuplas - cada tupla com um par chave-valor:
>>> ing2esp.items()

Captulo 10: Dicionrios #65

Como pensar como um cientista da Computao usando Python


[('one','uno'), ('three','tres'), ('two','dos')]

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

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] ]

Se voce tentar chamar um mtodo sem especificar em qual objeto, voce obter um erro. Nesse caso, a mensagem de erro no muito til:
>>> has_key('one') NameError: has_key

10.3 Aliasing (XXX) e Copiar

Uma alternativa usarmos um dicionrio. Para as chaves, ns podemos usar tuplas que contm os nmeros da linha e a coluna. Abaixo uma representao em um dicinario da mesma matriz:
>>> matriz = {(0,3): 1, (2, 1): 2, (4, 3): 3}

Ns precisamos apenas de trs pares Uma vez que os dicionrios so mutveis, voce chave-valor, cada um sendo um elemento diferente precisa saber sobre Aliasing. Sempre que duas de zero da matriz. Cada chave uma tupla, e cada variveis referenciarem o mesmo objeto, quando valor um nmero inteiro. uma alterada, afeta a outra. Para acessarmos um elemento da Se voc quer modificar um dicionrio e matriz, nos utilizamos o operador []: continuar com uma copia original, utilize o mtodo copy. Por exemplo, opposites um dicionrio que >>> matriz[0,3] contm pares de antnimos: 1 Note que a sintaxe da representao de >>> opposites = {'up': 'down', 'right': 'wrong', \ um dicionrio no a mesma que a sintaxe usada 'true': 'false'} pela representao pelas listas. Em vez de usarmos >>> alias = opposities dois ndices inteiros, ns usamos apenas um ndice, >>> copy = opposities.copy() que uma tupla de inteiros. alias e opposites se referem ao mesmo Mas existe um problema. Se tentarmos objeto; copy se refere a um novo objeto igual ao dicionrio opposites. Se voc modificar o alias, buscar um elemento zero, obteremos um erro, pois no existe uma entrada no dicionrio para a chave opposites tambm ser alterado. especificada:
>>> alias['right'] = 'left' >>> opossites['right'] 'left' >>> matriz[1,3] KeyError: (1,3)

Se modificarmos copy, opposites no ser modificado:


>>> copy['right'] = 'privilege' >>> opposites['right'] 'left'

O mtodo get resolve esse problema:


>>> matriz.get((0,3), 0) 1

O primeiro parmetro a chave; o segundo o valor que get retornar caso no existe a chave no dicionrio:
>>> matriz.get((1,3), 0) 0

10.4 Matrizes Esparsas

get definitivamente melhora a Na seo 8.14, ns usamos uma lista de listas para semntica e a sintaxe do acesso a matrizes esparsas. representar uma matriz. Essa uma boa escolha se a matriz for principalmente de valores diferentes de zero, mas considerando uma matriz esparsa como 10.5 Hint essa: Se voc brincou com a funo fibonacci da seo 5.7, provvel que voc notou que quanto maior o nmero passado para a funo, mais tempo a funo demora para executar. Alm disso, o tempo da execuo aumenta rapidamente. Em uma das Captulo 10: Dicionrios #66

Como pensar como um cientista da Computao usando Python nossas mquinas, fibonacci(20) executa piscar de olhos. Mas quando tentamos calcular instantaneamente, fibonacci(30) demora cerca de fibonacci(50) , ns veremos um problema diferente: um segundo, e fibonacci(40) demora uma >>> fibonacci(50) eternidade. Para entender o porque, considere o A resposta, que voc ver em um grfico de chamadas para fibonacci com n=4: minuto, 20.365.011.074. O problema que esse nmero muito grande para guardarmos como um inteiro do Python 1. Isso overflow. Felizmente, esse problema tem uma soluo simples.
OverflowError: integer addition

10.6 Inteiros Longos


Python possui um tipo chamado long int que permite trabalharmos com qualquer tamanho de inteiros. Existem duas maneiras de criarmos um valor long int. A primeira escrever um inteiro seguido de um L no final:
>>> type(1L) <type 'long int'>

A outra maneira usarmos a funo long que converte um valor para um long int. long pode receber qualquer valor nmerico e at mesmo uma string de digitos: O grfico mostra a estrutura da funo, com linhas conectando cada execuo com a execuo que a chamou. No topo do grfico, fibonacci tem n=4, que chama fibonacci com n=3 e n=2. Em seguida, fibonacci com n=3 chama fibonacci com n=2 e n=1. E assim por diante.
>>> long(1) 1L >>> long(3.9) 3L >>> long('57') 57L

Todas as operaes matemticas Conte quantas vezes fibonacci(0) e fibonacci(1) so chamadas. Essa uma soluo funcionam com long int s, ento no precisamos ineficiente para o problema, e torna-se pior quando modificar muito para adaptar fibonacci: o parmetro recebido um nmero maior. Uma boa soluo guardar os valores >>> fibonacci(50) que j foram calculados armazenando-os em um 20365011074L dicionrio. Um valor previamente calculado que Somente trocando os valores iniciais de guardado para ser utilizado mais tarde chamado previous, conseguimos mudar o comportamento da de hint. Abaixo uma implementao de fibonacci fibonacci. Os dois primeiros numeros da sequncia usando hints: so long ints, ento todos os nmeros subsequentes da sequncia tambm sero. >>> previous = {0:1, 1:1}
>>> def fibonacci(n): if previous.has_key(n): return previous[n] else: newValue = fibonacci(n-1) + \ fibonacci(n-2) previous[n] = newValue return newValue >>> previous = {0: 1L, 1:1L}

Como exerccio, converta fatorial para produzir um inteiro longo como resultado.

10.7 Contando Letras

No captulo 7, escrevemos uma funo que contava o nmero de ocorrncias de uma letra em uma O dicionrio chamado previous guarda string. A verso mais comum desse problema os nmeros de Fibonacci que ns ja conhecemos. fazer um histograma das letras da string, ou seja, Ele comea com apenas dois pares: 0 possui 1; e 1 quantas vezes cada letra aparece na string. possui 1. Um histograma pode ser util para Sempre que fibonacci chamada, ela comprimir um arquivo de texto. Pois diferentes verifica o dicionrio para determinar se ele j letras aparecem com diferentes frequncias, possui o resultado. Se o resultado estiver ali, a podemos comprimir um arquivo usando pequenos funo pode retornar imediatamente sempre cdigos para letras comuns e longos cdigos para precisar fazer mais chamadas recursivas. Se o letras que aparecem em menor frequncia. resultado no estiver ali, ele calculado no newValue. O valor de newValue adicionado no Dicionrios fornecem uma maneira dicionrio antes da funo retornar. Usando essa verso de fibonacci, nossa mquina consegue calcular fibonacci(40) em um
1 N.T. A partir do Python 2. XXX este erro no ocorre mais, pois em caso de sobrecarga o valor inteiro automaticamente promovido para o tipo long.

Captulo 10: Dicionrios #67

Como pensar como um cientista da Computao usando Python elegante de gerar um histograma:
>>> letterCounts = {} >>> for letter in "Mississippi": ... letterCounts[letter] = letterCounts.get(letter,0) + 1 ... >>> letterCounts {'M': 1, 's': 4, 'p': 2, 'i': 4}

10.8 Glossrio
dicionrio Uma coleo de pares de chaves(dictionary) valores que so mapeados pelas chaves, para se obter os valores. As chaves podem ser qualquer tipo de dados imutavel, e os valores podem ser de qualquer tipo. chave (key) Um valor que usado para buscar uma entrada em um dicionrio. par chave- Um dos itens de um dicionrio. valor (keyvalue pair) mtodo Um tipo de funo que chamada (method) com uma sintaxe diferente e invocada no contexto de um objeto. invocar Chamar um mtodo. (invoke) hint O armazenamento temporrio de um valor pr-computado para evitar a computao redundante. overflow Um resultado numrico que muito grande para ser representado no formato numrico.

Comeamos com um dicionrio vazio. Para cada letra da string, achamos o contador (possivelmente zero) e o incrementamos. No final, o dicionrio contem pares de letras e as suas frequncias. mais atraente mostrarmos o histograma na ordem alfabtica. Podemos fazer isso com os mtodos items e sort:
>>> letterItems = letterCounts.items() >>> letterItems.sort() >>> print letterItems [('M', 1), ('i', 4), ('p', 2), ('s', 4)]

Voc ja tinha visto o mtodo items antes, mas sort o primeiro mtodo que voc se depara para aplicar em listas. Existem muitos outros mtodos de listas, incluindo append, extend, e reverse. Consulte a documentao do Python para maiores detalhes.

Captulo 10: Dicionrios #68

Como pensar como um cientista da Computao usando Python

Captulo 11: Arquivos e excees

Arquivos e excees

>>> f.write("de fechar o arquivo")

Fechar o arquivo diz ao sistema que terminamos de escrever (gravar) e que o arquivo Durante a execuo de um programa, seus dados est livre para ser lido: ficam na memria. Quando o programa termina, ou o computador desligado, os dados na memria >>> f.close() Agora podemos abrir o arquivo de novo, desaparecem. Para armazenar os dados permanentemente, voc tem que coloc-los em um desta vez para leitura, e ler o seu contedo para arquivo. Arquivos usualmente so guardados em uma string. Desta vez, o argumento modo ?r? para um disco rgido (HD), num disquete ou em um CD- leitura (?reading?): ROM. Quando existe um nmero muito Se tentarmos abrir um arquivo que no grande de arquivos, eles muitas vezes so existe, temos um erro: organizados dentro de diretrios (tambm chamados de ?pastas? ou ainda ?*folders*?). Cada >>> f = open("teste.cat", "r") arquivo identificado por um nome nico, ou uma IOError: [Errno 2] No such file or directory: \ combinao de um nome de arquivo com um nome 'teste.cat' de diretrio. Sem nenhuma surpresa, o mtodo read Lendo e escrevendo em arquivos, os l dados do arquivo. Sem argumentos, ele l todo o programas podem trocar informaes uns com os contedo do arquivo: outros e gerar formatos imprimveis como PDF. Trabalhar com arquivos muito >>> print texto parecido com trabalhar com livros. Para utilizar um Agora horade fechar o arquivo livro, voc tem que abr-lo. Quando voc termina, No existe espao entre ?hora? e ?de? voc tem que fech-lo. Enquanto o livro estiver porque ns no gravamos um espao entre as aberto, voc pode tanto l-lo quanto escrever nele. strings. Em qualquer caso, voc sabe onde voc est situado no livro. Na maioria das vezes, voc l o livro inteiro read tambm pode receber um em sua ordem natural, mas voc tambm pode argumento que indica quantos caracteres ler: saltar atravs de alguns trechos (skip around). Tudo isso se aplica do mesmo modo a arquivos. Para abrir um arquivo, voc especifica o nome dele e indica o que voc quer, seja ler ou escrever (gravar).
>>> f = open("teste.dat", "r") >>> print f.read(9) Agora h >>> texto = f.read() >>> f = open("teste.dat", "r")

Se no houver caracteres suficientes no arquivo, read retorna os caracteres restantes. Abrir um arquivo cria um objeto Quando chegamos ao final do arquivo, read retorna arquivo. Neste exemplo, a varivel f se referencia ao a string vazia: novo objeto arquivo.
>>> f = open("teste.dat", "w") >>> print f <open file "teste.dat", mode "w" at fe820> >>> print f.read(1000006) orade fechar o arquivo >>> print f.read()

A funo open recebe dois argumentos. >>> O primeiro o nome do arquivo, e o segundo o A funo seguinte, copia um arquivo, modo. Modo ?w? significa que estamos abrindo o lendo e gravando at cinqenta caracteres de uma arquivo para gravao (?*write*?, escrever). vez. O primeiro argumento o nome do arquivo Se no existir nenhum arquivo de nome original; o segundo o nome do novo arquivo: teste.dat, ele ser criado. Se j existir um, ele ser def copiaArquivo(velhoArquivo, novoArquivo): substitudo pelo arquivo que estamos gravando (ou f1 = open(velhoArquivo, "r") escrevendo). Quando executamos um comando print sobre o objeto arquivo, visualizamos o nome do arquivo, o modo e a localizao do objeto na memria. Para colocar dados dentro do arquivo, invocamos o mtodo write do objeto arquivo:
>>> f.write("Agora hora") f2 = open(novoArquivo, "w") while 1: texto = f1.read(50) if texto == "": break f2.write(texto) f1.close() f2.close() return

Captulo 11: Arquivos e excees #69

Como pensar como um cientista da Computao usando Python


f2.close() A comando break novo. O que ele faz saltar a execuo para fora do loop; o fluxo de return execuo passa para o primeiro comando depois do O comando continue termina a iterao loop. corrente do loop, mas continua iterando o loop. O Neste exemplo, o loop while infinito fluxo de execuo passa para o topo do loop, checa porque o valor 1 sempre verdadeiro. O nico a condio e prossegue conforme o caso. modo de sair do loop executando o break, o que Assim, se texto for a string vazia, o loop ocorre quando texto a string vazia, o que ocorre termina. Se o primeiro caractere de texto for o jogo quando alcanamos o fim do arquivo. da velha (? # ?), o fluxo de execuo passa para o topo do loop. Somente se ambas as condies falharem que texto ser copiado para dentro do novo arquivo. 11.1 Arquivos texto

Um arquivo texto um arquivo que contm caracteres imprimveis e espaos, organizados 11.2 Gravando variveis dentro de linhas separadas por caracteres de nova linha. J que Pyhton especialmente projetado para O argumento de write tem que ser uma string, processar arquivos texto, ele oferece mtodos que assim se quisermos colocar outros valores em um tornam esta tarefa mais fcil. arquivo, temos de convert-los para strings Para demonstrar, vamos criar um primeiro. A maneira mais fcil de fazer isso com a arquivo texto com trs linhas de texto separadas funo str: por caracteres de nova linha: >>> x = 52 Uma alternativa usar o operador de formatao %. Quando aplicado a inteiros, % o O mtodo readline l todos os caracteres operador mdulo. Mas quando o primeiro operador at, e incluindo, o prximo caractere de nova linha: uma string, % o operador de formatao. O primeiro operando a string de >>> f = open("teste.dat", "r") formatao , e o segundo operando uma tupla de >>> print f.readline() expresses. O resultado uma string que contm os linha um valores das expresses, formatadas de acordo com a string de formatao.
>>> >>> f = open("teste.dat", "w") >>> f.write("linha um\nlinha dois\nlinha trs\n") >>> f.close() >>> f.write(str(x))

readlines retorna todas restantes como uma lista de strings:


>>> print f.readlines() ['linha dois\012', 'linha trs\012']

as

Num exemplo simples, a seqncia de linhas formatao "??%d??" significa que a primeira expresso na tupla deve ser formatada como um inteiro. Aqui a letra d representa ?decimal?.
>>> carros = 52 >>> "%d" % carros '52'

Neste caso, a sada est em formado de lista, o que significa que as strings aparecem entre aspas e o caractere de nova linha aparece como a seqncia de escape 012. No fim do arquivo, readline retorna a string vazia e readlines retorna a lista vazia:
>>> print f.readline() >>> print f.readlines() []

O resultado a string ?52?, que no deve ser confundida com o valor inteiro 52. Uma seqncia de formatao pode aparecer em qualquer lugar na string de formatao, assim, podemos embutir um valor em uma seqncia:
>>> carros = 52 >>> "Em julho vendemos %d carros." % carros 'Em julho vendemos 52 carros.'

A seguir temos um exemplo de um programa de processamento de linhas. A seqncia de formatao "%f" filtraArquivo faz uma cpia de velhoArquivo, formata o prximo item da tupla como um nmero omitindo quaisquer linhas que comecem por #: em ponto flutuante, e "%s" formata o prximo como uma string: def filtraArquivo(velhoArquivo, novoArquivo):
f1 = open(velhoArquivo, "r") f2 = open(novoArquivo, "w") while 1: texto = f1.readline() if texto == "": break if texto[0] == '#': continue f2.write(texto) f1.close() >>> "Em %d dias fizemos %f milhes %s." % \ (34,6.1,'reais') 'Em 34 dias fizemos 6.100000 milhes de reais.'

Por padro, o formato flutuante exibe seis casas decimais.

de

ponto

O nmero de expresses na tupla tem que ser igual ao nmero de seqncias de formatao na string. Alm disso, os tipos das expresses tm que iguais aos da seqncia de formatao: Captulo 11: Arquivos e excees #70

Como pensar como um cientista da Computao usando Python


>>> "%d %d TypeError: >>> "%d" % TypeError: operation %d" % (1,2) not enough arguments for format string 'reais' illegal argument type for built-in \

escrevendo nele, o novo arquivo fica no diretrio corrente (seja l onde for que voc esteja quando rodar o programa). Do mesmo modo, quando voc abre um arquivo para leitura, Python procura por ele no diretrio corrente.

Se voc quiser abrir um arquivo que No primeiro exemplo, no existem expresses suficientes; no segundo, a expresso do esteja em algum outro lugar, voc tem que especificar o caminho (path) para o arquivo, o qual tipo errado. o nome do diretrio (ou folder) onde o arquivo Para um controle maior na formatao est localizado: de nmeros, podemos especificar o nmero de >>> f = open("/usr/share/dict/words", "r") dgitos como parte da seqncia de formatao: Este exemplo abre um arquivo chamado words que reside em um diretrio de nome dict, o qual reside em share, o qual reside em usr, o qual O nmero depois do sinal de reside no diretrio de mais alto nvel do sistema, porcentagem o nmero mnimo de espaos que o chamado /. valor ocupar. Se o valor fornecido tiver um Voc no pode usar / como parte do nmero menor de dgitos, espaos em branco sero adicionados antes para preencher o restante. Se o nome de um arquivo; ela um caractere reservado nmero de espaos for negativo, os espaos sero como um delimitador entre nomes de diretrios e nomes de arquivos. adicionados depois: O arquivo /usr/share/dict/words contm uma lista de palavras em ordem alfabtica, na qual a primeira palavra o nome de uma universidade Para nmeros em ponto-flutuante, Dinamarquesa. tambm podemos especificar o nmero de dgitos depois da vrgula:
>>> "%-6d" % 62 '62 ' >>> "%12.2f" % 6.1 ' 6.10' >>> "%6d" % 62 ' 62' >>> "%12f" % 6.1 ' 6,100000' >>> print f.readline() Aarhus

11.4 Pickling

Neste exemplo, o resultado reserva 12 Para colocar valores em um arquivo, voc tem que espaos e inclui dois dgitos depois da vrgula. Esta convert-los para strings. Voc j viu como fazer formatao til para exibir valores monetrios isto com str: com os centavos alinhados. Por exemplo, imagine um dicionrio que >>> f.write (str([1,2,3])) contm nomes de estudantes como chaves e O problema que quando voc l de salrios-hora como valores. Aqui est uma funo que imprime o contedo do dicionrio como um volta o valor, voc tem uma string. O Tipo original da informao foi perdido. De fato, voc no pode relatrio formatado: sequer dizer onde comea um valor e termina def relatorio(salarios): outro:
estudantes = salarios.keys() estudantes.sort() for estudante in estudantes: print "%-20s %12.02f" % (estudante, \ salarios[estudante]) >>> f.readline() ?12.3[1, 2, 3]? >>> f.write (str(12.3))

A soluo o pickling, assim chamado porque ?preserva? estruturas de dados. O mdulo pickel contm os comandos necessrios. Para us-lo, Para testar esta funo, criaremos um importe pickle e ento abra o arquivo da maneira pequeno dicionrio e imprimiremos o contedo: usual:
>>> salarios = {'maria': 6.23, 'joo': 5.45, \ 'josu': 4.25} >>> relatorio(salarios) joo 5.45 josu 4.25 maria 6.23 >>> import pickle >>> f = open(?test.pck?, ?w?)

Para armazenar uma estrutura de dados, use o mtodo dump e ento feche o arquivo do modo usual:
>>> pickle.dump(12.3, f)

Controlando a largura de cada valor, >>> pickle.dump([1,2,3], f) podemos garantir que as colunas ficaro alinhadas, desde que os nomes contenham menos que vinte e >>> f.close() Ento, podemos abrir o arquivo para um caracteres e os salrios sejam menores do que leitura e carregar as estruturas de dados que foram um bilho de reais por hora. descarregadas (dumped):

11.3 Diretrios
Quando voc cria um novo arquivo abrindo-o e

>>> f = open(?test.pck?, ?r?) >>> x = pickle.load(f) >>> x 12,3

Captulo 11: Arquivos e excees #71

Como pensar como um cientista da Computao usando Python


>>> type(x) <type ?float?> >>> y = pickle.load(f) >>> y [1, 2, 3] >>> type(y) <type ?list?> def existe(nomedoarquivo) try: f = open(nomedoarquivo) f.close() return 1 except: return 0

Cada vez que invocamos load, obtemos Voc pode usar mltiplos blocos except um nico valor do arquivo, completo com seu tipo para tratar diferentes tipos de excees. O Manual original. de Referncia de Python (Python Reference Manual) tem os detalhes. Se o seu programa detecta uma condio de erro, voc pode faz-lo lanar uma exceo. Aqui est um exemplo que toma uma do usurio e testa se o valor 17. Supondo Whenever que um erro em tempo de execuo entrada que 17 no seja uma entrada vlida por uma razo acontece, ele gera uma exceo. Usualmente, o qualquer, ns lanamos uma exceo. programa pra e Python exibe uma mensagem de erro. def entraNumero():

11.5 Excees

exceo:

Por exemplo, dividir por zero gera uma

O comando raise toma dois argumentos: Do mesmo modo, acessar um item de o tipo da exceo e informaes especficas sobre o lista inexistente: erro. ErroNumeroRuim um novo tipo de exceo que ns inventamos para esta aplicao. >>> a = [] Se a funo que chamou entraNumero trata o erro, ento o programa pode continuar; de Ou acessar uma chave que no est em outro modo, Pyhton exibe uma mensagem de erro e sai: um dicionrio:
>>> print a[5] IndexError: list index out of range >>> b = {} >>> print b[?what?] KeyError: what >>> entraNumero() Escolha um nmero: 17 ErroNumeroRuim: 17 um nmero ruim

>>> print 55/0 ZeroDivisionError: integer division or modulo

x = input (?Escolha um nmero: ?) if x == 17: raise ?ErroNumeroRuim?, ?17 um nmero ruim? return x

A mensagem de erro inclui o tipo da Em cada caso, a mensagem de erro tem duas partes: o tipo do erro antes dos dois pontos, e exceo e a informao adicional que voc especificidades do erro depois dos dois pontos. forneceu. Normalmente Python tambm exibe um ? Como um exerccio, escreva uma funo *traceback*? de onde estava a execuo do que use entraNumero para pegar um nmero do programa, mas ns temos omitido esta parte nos teclado e que trate a exceo ErroNumeroRuim. exemplos. s vezes queremos executar uma operao que pode causar uma exceo, mas no queremos que o programa pare. Ns podemos tratar a exceo usando as instrues try e except. Por exemplo, podemos pedir ao usurio um nome de arquivo e ento tentar abr-lo. Se o arquivo no existe, no queremos que o programa trave; queremos tratar a exceo:
nomedoarquivo = raw_input(?Entre com o nome do \ arquivo: ?) try: f = open (nomedoarquivo, ?r?) except: print ?No existe arquivo chamado?, nomedoarquivo

11.6 Glossrio
arquivo Uma entidade nomeada, (file) usualmente armazenada em um disco rgido (HD), disquete ou CDROM, que contm uma seqncia de caracteres. diretrio Uma coleo nomeada de arquivos, (directory) tambm chamado de pasta ou folder. caminho Uma seqncia de nomes de (path) diretrios que especifica a exata localizao de um arquivo. arquivo Um arquivo que contm caracteres texto (text organizados em linhas separadas file) por caracteres de nova linha. comando break (break statement) Um comando que fora a atual iterao de um loop a terminar. O fluxo de execuo vai para o topo do loop, testa a condio e prossegue conforme o caso.

A instruo try executa os comandos do primeiro bloco. Se no ocorrerem excees, ele ignora a instruo except. Se qualquer exceo acontece, ele executa os comandos do ramo except e continua. Podemos encapsular esta habilidade numa funo: existe toma um nome de arquivo e retorna verdadeiro se o arquivo existe e falso se no existe:

Captulo 11: Arquivos e excees #72

Como pensar como um cientista da Computao usando Python

Captulo 11: Arquivos e excees #73

Como pensar como um cientista da Computao usando Python

Captulo 12: Classes e objetos

12.1 Tipos compostos definidos pelo usurio


Depois de usarmos alguns tipos nativos do Python, estamos prontos para criar um tipo de dados: o Ponto. Considere o conceito matemtico de um ponto. Em duas dimenses, um ponto um par de nmeros (coordenadas) que so tratadas coletivamente como um objeto simples. Na notao matemtica, pontos so freqentemente escritos entre parnteses com vrgula separando as coordenadas. Por exemplo, (0, 0) representa a origem, e (x, y) representa o ponto x unidades direita, e y unidades acima da origem.

A varivel final agora contm uma referncia a um novo objeto da classe Ponto. Uma funo como Ponto, que cria novos objetos, chamada construtor .

12.2 Atributos
Podemos adicionar novos dados em uma instncia usando a notao de ponto (dot notation):
>>> final.x = 3.0 >>> final.y = 4.0

Uma maneira natural para representar um ponto em Python, com dois valores numricos O seguinte diagrama de estado mostra o em ponto flutuante. A questo, ento, como resultado destas atribuies: agrupar estes dois valores em um objeto composto. A maneira rpida e rasteira usar uma lista ou uma tupla, e para algumas aplicaes, esso pode ser a melhor escolha 1. Uma alternativa definir um novo tipo composto, tambm chamado uma classe. Esta abordagem envolve um pouco mais de esforo, mas ela tem vantagens que logo ficaro evidentes. Eis a definio de uma classe:
class Ponto: pass

Esta sintaxe similar sintaxe para acessar uma varivel de um mdulo, como math.pi ou string.uppercase. Neste caso, porm, estamos acessando um item de dado de uma instncia. Estes itens so chamados atributos.

A varivel final refere a um objeto Ponto, que contm dois atributos. Cada atributo faz referncia a um nmero em ponto flutuante.

Podemos ler o valor de um atributo Definies de classes podem aparecer usando a mesma sintaxe: em qualquer parte de um programa, mas elas >>> print final.y costuma ficar prximas do comeo do programa (aps os comandos import). As regras de sintaxe 4.0 para a definio de classes so as mesmas de outros >>> x = final.x >>> print x comandos compostos (veja Seo 4.4). A definio acima cria uma nova classe A expresso final.x significa, "V ao chamada Ponto. O comando pass no tem nenhum efeito; aqui ele necessrio porque um comando objeto final e pegue o valor de x". Neste caso, atribumos este valor a uma varivel cujo nome composto precisa ter algo no seu corpo. 'x'. No h conflito entre a varivel x e o atributo x. Quando criamos a classe Ponto, criamos O propsito da notao objeto.atributo identificar um novo tipo de dado, tambm chamado Ponto. Os a qual varivel voc est fazendo referncia de membros deste novo tipo so chamados instncias forma que no ambguo. deste tipo ou objetos. Criar uma nova instncia Voc pode usar a notao instanciar. Para instanciar o objeto Ponto, objeto.atributo como parte de qualquer expresso; invocamos a funo (adivinhou?) Ponto: assim os seguintes comandos so vlidos:
final = Ponto() print '(' + str(final.x) + ', ' + str(final.y) + ')' distAoQuadrado = final.x * final.x + final.y * \ final.y 3.0

1 N.T.: A linguagem Python tambm incorpora um tipo nativo 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 bidimensional.

A primeira linha imprime (3.0, 4.0); a segunda linha calcula o valor 25.0. tentador imprimir o valor do prprio objeto final:

Captulo 12: Classes e objetos #74

Como pensar como um cientista da Computao usando Python


>>> print final <__main__.Ponto instance at 80f8e70>

exemplo:
>>> p1 = Ponto() >>> p1.x = 3 >>> p1.y = 4 >>> p2 = Ponto() >>> p2.x = 3 >>> p2.y = 4 >>> p1 == p2 False

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 hexadecimal (base 16). Esta no provavelmente a forma mais informativa para mostrar um objeto Ponto. Logo voc ir ver como mudar isso.

Como exerccio, crie e imprima um Mesmo que p1 e p2 contenham as objeto Ponto, e ento use id para imprimir o identificador nico do objeto. Traduza a forma mesmas coordenadas, os dois no representam o hexadecimal para a forma decimal e confirme se mesmo objeto. Se atribuirmos p1 a p2, ento as duas variveis so pseudnimos do mesmo objeto. so compatveis.

12.3 Instncias como parmetros


Voc pode passar uma instncia como parmetro da forma usual. Por exemplo:
def mostrarPonto(p): print '(' + str(p.x) + ', ' + str(p.y) + ')'

>>> p2 = p1 >>> p1 == p2 True

Este tipo de igualdade chamado de um igualdade rasa porque ela compara somente as referncias e no o contedo dos objetos.

Para comparar o contedo dos objetos -igualdade profunda -- podemos escrever uma A funo mostrarPonto pega o ponto (p) funo chamada mesmoPonto: como um argumento e mostra-o no formato padro. def mesmoPonto(p1, p2) : Se voc chamar mostrarPonto(final), a sada ser return (p1.x == p2.x) and (p1.y == p2.y) (3.0, 4.0). Agora se criarmos dois diferentes Como um exerccio, re-escreva a funo objetos que contm os mesmos dados, podemos mesmoPonto para verificar se eles distncia da Seo 5.2 para receber dois pontos usar representam o mesmo ponto. como parmetros, ao invs de quatro nmeros.

12.4 O significado de "mesmo"


O significado da palavra "mesmo" parece perfeitamente claro at que voc pense a respeito, e ento voc percebe que h mais nesta palavra do que voc esperava.

>>> p1 = Ponto() >>> p1.x = 3 >>> p1.y = 4 >>> p2 = Ponto() >>> p2.x = 3 >>> p2.y = 4 >>> mesmoPonto(p1, p2) True

claro, se as duas variveis referirem Por exemplo, se voc diz "Cris e eu temos o mesmo carro", voc est dizendo que o ao mesmo objeto, elas tm igualdade rasa e carro de Cris e o seu so do mesmo fabricante e igualdade profunda. modelo, mas so dois carros diferentes. Se voc disser "Cris e eu temos a mesma me", voc est dizendo que a me de Cris e a sua, so a mesma pessoa1. Portanto a idia de 'semelhana' diferente 12.5 Retngulos dependendo do contexto. que desejemos uma classe para Quando falamos de objetos, h uma Digamos representar um retngulo. A questo , qual ambigidade similar. Por exemplo, se dois Pontos informao temos de prover para especificar um forem os mesmos, isto quer dizer que eles contm os retngulo? Para manter as coisas simples, assuma mesmos dados (coordenadas) ou que so realmente que o retngulo orientado verticalmente ou o "mesmo" objeto? horizontalmente, nunca em um ngulo.

Para verificar se duas referncias se algumas possibilidades: poderamos referem ao 'mesmo' objeto, use o operador '==' 2. Por especificar H o centro do retngulo (duas coordenadas) e seu tamanho (largura e altura); ou 1 Nem todos os idiomas tm este problema. Por poderamos especificar um dos lados e o tamanho; exemplo, em alemo h palavras diferentes para ou poderamos especificar dois lados opostos. A diferentes sentidos de "mesmo". "Mesmo carro" escolha convencional especificar o canto superior
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 #75

Como pensar como um cientista da Computao usando Python esquerdo do retngulo e o tamanho. classe: Novamente, vamos definir uma nova 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

class Rectangle: pass

E instanci-la:
box = Rectangle() box.width = 100.0 box.height = 200.0

As variveis dwidth e dheight indicam em quanto vamos aumentar o tamanho do retngulo em cada direo. Chamando este mtodo, teramos o mesmo efeito.

Por exemplo, poderamos criar um novo Este cdigo cria um novo objeto Retngulo com o nome de 'bob' e passar este nome Retngulo com dois atributos ponto-flutuante. Para para o mtodo growRect: especificar o canto superior esquerdo, podemos >>> bob = Rectangle() embutir um objeto dentro de um objeto!
box.corner = Ponto() box.corner.x = 0.0; box.corner.y = 0.0; >>> >>> >>> >>> >>> bob.width = 100.00 bob.height = 200.00 bob.corner.x = 0.0; bob.corner.y = 0.0; growRect(bob, 50, 100)

A expresso box.corner.x significa, "v ao objeto referenciado por 'box' e selecione o Enquanto growRect est sendo atributo 'corner'; ento v ao objeto 'corner' e deste, executado, o parmetro 'box' um alias (apelido) selecione o atributo de nome 'x'". para 'bob'. Qualquer mudana feita em 'box', tambm ir afetar 'bob'. A figura mostra o estado deste objeto: Como exerccio, escreva uma function (mtodo) com o nome de moveRect que pega um Rectangle e dois parmetros com o nome de 'dx' e 'dy'. Esta funo dever mudar a localizao do retngulo atravs da adio de 'dx' coordenada 'x' e da adio de 'dy' coordenada 'y'.

12.8 Copiando
Ao usar 'alias' - como fizemos na seo anterior podemos tornar o programa um pouco difcil de ler 12.6 Instancias como valores retornados ou entender, pois as mudanas feitas em um local, podem afetar inesperadamente um outro objeto. E Funes podem retornar instncias. Por exemplo, pode se tornar difcil de encontrar todas as findCenter pega um Retngulo como um argumento variveis que podem afetar um dado objeto. e retorna um Ponto que contem as coordenadas do Copiar um objeto freqentemente uma centro do retngulo: alternativa ao 'alias'. O modulo 'copy' contm uma def findCenter(box): funo chamada 'copy' que duplica um qualquer objeto. Veja: p = Ponto()
p.x = box.corner.x + box.width/2.0 p.y = box.corner.y + box.height/2.0

Para chamar esta funo, passe 'box' como um argumento e coloque o resultado em uma varivel.
>>> center = findCenter(box) >>> print mostrarPonto(center) (50.0, 100.0)

>>> >>> >>> >>> >>> >>> 0 >>> 1

import copy p1 = Ponto() p1.x = 3 p1.y = 4 p2 = copy.copy(p1) p1 == p2 mesmoPonto(p1, p2)

12.7 Objetos so mutveis

Podemos mudar o estado de um objeto fazendo uma Para copiar um simples objeto como um atribuio a um dos seus atributos. Por exemplo, para mudar o tamanho de um retngulo sem 'Ponto', que no contem nenhum objeto embutido, mudar sua posio, podemos modificar os valores 'copy' suficiente. Isto eh chamado 'shallow' copia. de sua largura e altura. Veja: Mas para um objeto como um 'Rectangle', que contem uma referencia para um box.width = box.width + 50 'Ponto', o mtodo 'copy' no ir executar box.height = box.height + 100 corretamente a copia. Ele ir copiar a referencia Poderamos encapsular este cdigo em para o objeto 'Ponto', portanto o que acontece aqui Captulo 12: Classes e objetos #76

Uma vez que importamos o modulo 'copy', podemos usar o mtodo 'copy' para criar um outro 'Ponto'. p1 e p2 no representam o mesmo ponto, mas eles contem os mesmo dados.

Como pensar como um cientista da Computao usando Python que os dois Rectangle (o novo e o antigo) iro fazer referencia a um simples 'Ponto'. Em outras palavras, se criarmos um 'box', c1, utilizando a forma usual, e depois fazer uma copia, c2, usando o mtodo 'copy', o diagrama de estado resultante ficar assim: construtor Um mtodo utilizado para criar (constructor) novos objetos. atributo Um dos itens de dados nomeados (attribute) que compem uma instncia. igualdade Igualdade de referncias; ocorre rasa (shallow quando duas referncias apontam equality) para o mesmo objeto. igualdade profunda (deep equality) o resultado no ser o que esperamos. Neste caso, invocando 'growRect' em um dos retngulos (c1), isto no ir afetar o outro retngulo (c2, neste exemplo). Mas se usarmos o mtodo 'moveRect' em qualquer um deles, isto ir inevitavelmente afetar o outro. Este comportamento confuso e propenso a erros! Mas felizmente o modulo 'copy' contem um mtodo chamado 'deepcopy' que copia no somente o objeto, mas tambm copia todo e qualquer objeto 'embutido' neste objeto. Por isto, voc no ficar surpreso porque este mtodo chama-se 'deepcopy' (copia profunda) no ? Veja como funciona:
>>> c2 = copy.deepcopy(c1)

Igualdade de valores; ocorre quando duas referncias apontam para objetos que tm o mesmo valor.

cpia rasa Ato de copiar o contedo de um (shallow objeto, incluindo as referncias a embutidos (XXX copy) objetos embedded); implementada pela funo copy do mdulo copy. cpia Ato de copiar o contedo de um profunda objeto, bem como dos objetos (deep copy) embutidos (XXX embedded), e dos objetos embutidos nestes, e assim por diante; implementada pela funo deepcopy do mdulo copy.

Agora, c1 e completamente separados.

c2

so

objetos

Podemos usar 'deepcopy' para reescrever 'growRect' sendo que ao invs de modificar um Rectangle existente, ele cria um novo que tem a mesma localizao do outro, mas com novas dimenses:
def growRect(box, dwidth, dheight): import copy newBox = copy.deepcopy(box) newBox.width = newBox.width + dwidth newBox.height = newBox.height + dheight return newBox

Como exerccio, re-escreva o mtodo 'moveRect' para ele criar e retornar um novo Rectangle ao invs de apenas modificar o antigo.

12.9 Glossrio
classe (class) Um tipo composto (XXX compound type) definido pelo usurio. Uma classe tambm pode ser visualizada como um molde que define a forma dos objetos que sero suas instncias. instanciar Criar uma instncia de uma classe. (instantiate) instncia Um objeto que pertence a uma (instance) classe. objeto Um tipo de dado composto utilizado para (object) comumente representar uma coisa ou um conceito do mundo real.

Captulo 12: Classes e objetos #77

Como pensar como um cientista da Computao usando Python

Captulo 12: Classes e objetos #78

Como pensar como um cientista da Computao usando Python

Captulo 13: Classes e funes

inicializa os seus atributos, e retorna uma referncia para o novo objeto. Isso chamado de funo pura pois ela no modifica nenhum dos Como exemplo de outro tipo definido pelo usurio, objetos que so passados como parmetros e no vamos definir uma classe chamada Horario que tem nenhum efeito colateral, como imprimir um grava os registros de horrio do dia. Eis a definio valor ou pegar entrada do usurio. da classe: Aqui est um exemplo de como usar esta funo. Ns vamos criar dois objetos Horario: class Horario: horarioAtual, que contm o horrio atual; e pass horarioDoPao, que contm a quantidade de tempo Podemos criar uma nova instncia de que a mquina de fazer po gasta para fazer po. Horario e determinar atributos para horas, minutos Ento vamos usar somaHorario para tentar saber e segundos: quando o po estar pronto. Se voc no tiver terminado de escrever imprimirHorario ainda, de horario = Horario() uma olhada na seo 14.2 antes de voc continuar horario.horas = 11 isso:

13.1 Horario

horario.minutos = 59 horario.segundos = 30

O diagrama de estado para o objeto Horario parece com isso:

>>> >>> >>> >>> >>> >>> >>> >>>

horarioAtual = Horario() horarioAtual.horas = 9 horarioAtual.minutos = 14 horarioAtual.segundos = 30 horarioDoPao = Horario() horarioDoPao.horas = 3 horarioDoPao.minutos = 35 horarioDoPao.segundos = 0

Como exerccio, escreva uma funo A sada deste programa 12:49:30, o que 'imprimirHorario' que tenha como argumento um correto. Por outro lado, existem casos onde o objeto Horario e imprima-o na forma resultado no correto. Voc pode pensar em horas:minutos:segundos. algum ? Como um segundo exerccio, escreva O problema que esta funo no lida uma funo booleana que tenha como argumento com casos onde o nmero de segundos ou minutos dois objetos Horario, h1 e h2, e retorne verdadeiro (1) se h1 vem depois de h2 cronologicamente, do acrescentado em mais de sessenta. Quando isso acontece, temos de "transportar" os segundos extras contrrio, retorne falso (0). para a coluna dos minutos ou os minutos extras na coluna das horas.

>>> horarioTermino = somaHorario(horarioAtual, \ horarioDoPao) >>> imprimirHorario(horarioTermino)

13.2 Funes Puras


Nas prximas sesses, vamos escrever duas verses de uma funo chamada adicionaHorario, que calcula a soma de dois horrios. Elas vo demonstrar 2 tipos de funes: funes puras e funes modificadoras. Segue somaHorario: uma verso rudimentar de

funo:

Aqui est a segunda verso corrigida da

def somaHorario(t1, t2): soma = Horario() soma.horas = t1.horas + t2.horas soma.minutos = t1.minutos + t2.minutos soma.segundos = t1.segundos + t2.segundos if soma.segundos >= 60: soma.segundos = soma.segundos - 60 soma.minutos = soma.minutos + 1 if soma.minutos >= 60: soma.minutos = soma.minutos - 60 soma.horas = soma.horas + 1 return soma

def somaHorario(h1, h2): soma = Horario() soma.horas = h1.horas + h2.horas soma.minutos = h1.minutos + h2.minutos soma.segundos = h1.segundos + h2.segundos return soma

A funo cria um novo objeto Horario,

Captulo 13: Classes e funes #79

Como pensar como um cientista da Computao usando Python Apesar desta funo estar correta, ela est comeando a ficar grande. Depois vamos sugerir uma aproximao alternativa que rende um cdigo menor. Clique aqui para feedback incrementar como uma funo pura, e escreva chamadas de funes para as duas funes. Clique aqui para feedback

13.3 Modificadores
Existem momentos quando til para uma funo modificar um ou mais dos objetos que ela recebe como parmetro. Usualmente, quem est chamando a funo mantm uma referncia para os objetos que ele passa, de forma que quaisquer mudanas que a funo faz so visveis para quem est chamando. Funes que trabalham desta forma so chamadas modificadores.

13.4 O que melhor ?


Qualquer coisa que pode ser feita com modificadores tambm podem ser feitas com funes puras. De fato, algumas linguagens de programao permitem apenas funes puras. Existe alguma evidncia que programas que usam funes puras so desenvolvidos mais rapidamente e so menos propensos a erros que programas que usam modificadores. No entanto, modificadores as vezes so convenientes, e em alguns casos, programao funcional menos eficiente.

incrementar, que adiciona um nmero dado de segundos para um objeto Horario, poderia Em geral, recomendamos que voc ser escrito quase naturalmente como um escreva funes puras sempre que for necessrio e modificador. Um rascunho rudimentar da funo recorrer para modificadores somente se existir uma seria algo parecido com isso: grande vantagem. Esta aproximao poderia ser chamada de um estilo de programao funcional. def incrementar(horario, segundos): Clique aqui para feedback
horario.segundos = \ horario.segundos + segundos

if horario.segundos >= 60: horario.segundos = \ horario.segundos - 60 horario.minutos = horario.minutos + 1 if horario.minutos >= 60: horario.minutos = \ horario.minutos - 60 horario.horas = horario.horas + 1

13.5 Desenvolvimento Prototipado versus Desenvolvimento Planejado


Neste captulo, demonstramos uma aproximao para o desenvolvimento de programas que chamamos de desenvolvimento prototipado. Em cada caso, escrevemos um rascunho rudimentar (ou prottipo) que executou os clculos bsicos e ento, o testamos em uns poucos casos, corrigindo as falhas que fomos encontrando.

A primeira linha executa a operao Embora esta aproximao possa ser bsica; o resto lida com os caso especiais que vimos eficaz, ela pode conduzir a cdigo que antes. desnecessariamente complicado pois trata de Esta funo est correta ? O que muitos casos especiais e no confivel, pois aconteceria se o parmetro segundos for muito difcil saber se voc encontrou todos os erros. maior que sessenta ? Nesse caso, no suficiente Uma alternativa o desenvolvimento transportar apenas uma vez; teramos de continuar planejado, onde uma viso de alto nvel do fazendo isso at que segundos seja menor que problema pode tornar a codificao muito mais sessenta. Uma soluo seria substituir os comando fcil. Nesse caso, a abstrao que um objeto if por comandos while: Horario realmente um nmero de trs digitos na base 60! O componente segundo a "coluna dos def incrementar(horario, segundos): uns", o componente minuto a "coluna do 60", e o horario.segundos = \ componente hora a "coluna do 360". horario.segundos + segundos
while horario.segundos >= 60: horario.segundos = horario.segundos horario.minutos = horario.minutos + 1 while horario.minutos >= 60: horario.minutos = \ horario.minutos - 60 horario.horas = horario.horas + 1

- 60

Quando ns escrevemos somaHorario e incrementar, ns estvamos efetivamente fazendo adies em base 60, que o motivo pelo qual tinhamos de transportar de uma coluna para a prxima. Essa observao sugere uma outra aproximao para todo o problema - ns podemos converter um objeto Horario em um nmero simples e levar vantagem do fato de que um computador sabe como fazer aritmtica com nmeros. A seguinte funo converte o objeto Horario em um inteiro:
def converterParaSegundos(t): minutos = t.horas * 60 + t.minutos segundos = minutos * 60 + t.segundos return segundos

Esta funo agora esta correta, mas no a soluo mais eficiente. Como um exerccio, reescreva esta funo de maneira que ela no contenha nenhum loop. Como um segundo exerccio, reescreva

Captulo 13: Classes e funes #80

Como pensar como um cientista da Computao usando Python Agora, tudo que precisamos uma Primeiramente, considere alguma coisa maneira de converter de um inteiro para um objeto que no seja um algoritmo. Quando voc aprendeu Horario: a multiplicar nmeros de um dgito, voc provavelmente memorizou a tabela de def criarHorario(segundos): multiplicao. Como resultado, voc memorizou 100 horario = Time() solues especficas. Esse tipo de conhecimento no horario.horas = segundos/3600 algoritmo. Mas se voc "preguioso", voc provavelmente trapaceou por ter aprendido alguns truques. Por exemplo, para encontrar o produto de n e 9, voc pode escrever n-1 como o primeiro dgito e 10-n como o segundo dgito. Este truque um Voc deve ter que pensar um pouco soluo genrica para multiplicar qualquer nmero para se convencer que esta tcnica de converter de de um dgito por 9. Isso um algoritmo! uma base para outra correta. Assumindo que voc De modo parecido, as tcnicas que voc est convencido, voc pode usar essas funes para aprendeu para somar com transporte, subtrao reescrever somaHorario: com emprstimo, e diviso longa so todas algoritmos. Uma das caractersticas dos algoritmos def somaHorario(t1, t2): que eles no requerem nenhuma inteligncia para segundos = \ serem executados. Eles so processos mecnicos no converterParaSegundos(t1) + qual cada passo segue o ltimo de acordo com um converterParaSegundos(t2) conjunto simples de regras. Na nossa opinio, preocupante que Esta verso muito mais curta que a original, e muito mais fcil para demonstrar que humanos gastem tanto tempo na escola aprendendo est correta (assumindo, como sempre, que as a executar algoritmos que, literalmente, no requerem inteligncia. funes que so chamadas esto corretas). Por outro lado, o processo de projetar Como um exerccio, reescreva algoritmos interessante, intelectualmente incrementar da mesma forma. Clique aqui para desafiante, e uma parte central daquilo que feedback chamamos programao. Algumas das coisas que as pessoas fazem naturalmente, sem dificuldade ou conscincia, so as mais difceis de se expressar atravs de algoritmos. Entender a linguagem Algumas vezes, converter de base 60 para base 10 e natural um bom exemplo. Todos ns fazemos isso, voltar mais difcil do que simplesmente lidar com mas at hoje ningum conseguiu explicar como horrios. Converso de base mais abstrata; nossa fazemos isso, pelo menos no na forma de intuio para lidar com horrios melhor. algoritmo. Clique aqui para feedback. Mas se conseguirmos abstrair horrios como nmeros de base 60 e investirmos em criar as funes de converso (converterParaSeguntos e 13.8 Glossrio criarHorario), ns conseguimos um programa que menor, fcil de ler e depurar, e mais confivel. funo pura (pure Uma funo que no modifica tambm fcil para adicionar function) nenhum dos objetos que ela funcionalidades depois. Por exemplo, imagine recebe como parmetro. A subtrair dois Horarios para encontrar a durao maioria das funes puras entre eles. Uma aproximao ingnua seria frutfera. implementar subtrao com emprstimo. Usando as modificador Uma funo que muda um ou funes de converso ser mais fcil e (modifier) mais dos objetos que ela provavelmente estar correto. recebe como parmetros. A Ironicamente, algumas vezes fazer um maioria dos modificadores problema mais difcil (ou mais genrico) o torna nula. mais simples (porque existem alguns poucos casos estilo de Um estilo de programao especiais e poucas oportunidades para errar). programao onde a maioria das funes Clique aqui para feedback funcional so puras. (functional programming 13.7 Algoritmos style)
return criarHorario(segundos) segundos = segundos - horario.horas * 3600 horario.minutos = segundos/60 segundos = segundos - horario.minutos * 60 horario.segundos = segundos return horario

13.6 Generalizao

Quando voc escreve uma soluo genrica para uma classe de problemas, ao contrrio de uma soluo especfica para um nico problema, voc escreveu um algoritmo. Ns mencionamos isso antes mas no definimos cuidadosamente. Isso no fcil para definir, ento vamos tentar definir demonstrando algumas situaes.

desenvolvimento prototipado (prototype development)

Uma maneira de desenvolver programas comeando com um prottipo e gradualmente melhorando-o.

desenvolvimento Uma maneira de desenvolver planejado programas que envolvem

Captulo 13: Classes e funes #81

Como pensar como um cientista da Computao usando Python (planned uma percepo de alto nvel problema e mais development) do planejamento do que desenvolvimento incremental ou desenvolvimento prototipado. algoritmo Um conjunto de instrues (algorithm) para resolver uma classe de problemas usando um processo mecnico, no inteligente.

Captulo 13: Classes e funes #82

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 unificadas...

A sintaxe para a chamada do mtodo diferente da sintaxe para a chamada de uma funo.

Nas prximas sees, vamos pegar as funes dos dois captulos anteriores e transform14.1 Caractersticas da orientao a objetos las em mtodos. Esta transformao puramente mecnica: voc pode consegu-la simplesmente uma seqncia de passos. Se voc se sentir Python uma linguagem de programao seguindo confortvel de uma forma para a orientada a objetos , o que significa que ela tem outra, voc convertendo estar apto para escolher a melhor caractersticas que suportam a programao forma para seja o l o que for que voc estiver orientada a objetos . fazendo. No fcil definir programao orientada a objetos, mas temos visto already algumas de suas caractersticas: 14.2 exibeHora (printTime)

Programas so construdos sobre definies de objetos e definies de funes, e a No captulo 13, definimos uma classe chamada maioria das computaes expressa em Horrio (Time) e voc escreveu uma funo termos de operaes sobre objetos. chamada exibeHora (printTime), que deve ter Cada definio de objeto corresponde a ficado mais ou menos assim: algum objeto ou conceito do mundo real, e class Horario: as funes que operam com aqueles objetos pass correspondem maneira como os objetos do mundo real interagem.
def exibeHora(time)

Por exemplo, a classe Tempo, definida print str(time.horas) + ?:? + \ no captulo 13 corresponde maneira como as str(time.minutos) + ?:? + \ pessoas registram as horas do dia, e as funes que str(time.segundos) definimos correspondem aos tipos de coisas que as Para chamar esta funo, passamos um pessoas fazem com times. Do mesmo modo, as classes Ponto e Retngulo correspondem aos objeto Time como um parmetro: conceitos matemticos de um ponto e de um >>> horaCorrente = Hora() retngulo. At aqui, no tiramos vantagem das >>> horaCorrente.minutos = 14 caractersticas fornecidas por Python que suportam >>> horaCorrente.segundos = 30 a programao orientada a objetos. Estritamente >>> exibeHora(horaCorrente) falando, estas caractersticas no so necessrias. Para fazer de exibeHora um mtodo, Na maior parte das vezes, elas fornecem uma sintaxe alternativa para as coisas que j fizemos, tudo o que temos a fazer mover a definio da mas em muitos casos, a alternativa mais concisa e funo para dentro da definio da classe. Note a convm mais acuradamente estrutura do mudana na endentao: programa. class Horario:
def exibeHora(time): Por exemplo, no programa Time, no print str(time.horas) + ?:? + \ existe uma conexo bvia entre a definio da str(time.minutos) + ?:? + \ classe e a definio da funo que segue. Com alguma investigao, fica aparente que toda funo str(time.segundos) toma pelo menos um objeto Time como um Agora podemos chamar exibeHora parmetro. usando a natao de ponto: Esta observao a motivao por trs >>> horaCorrente.exibeHora() dos mtodos. J temos visto alguns mtodos, tais Como usual, o objeto no qual o mtodo como keys (chaves) e values (valores), os quais foram invocados em dicionrios. Cada mtodo invocado aparece antes do ponto e o nome do associado com uma classe e intended para ser mtodo aparece depois do ponto. invocado em instncias daquela classe. O objeto no qual o mtodo invocado Mtodos so simplesmente como atribudo ao primeiro parmetro, ento, neste caso, horaCorrente atribudo ao parmetro time. funes, com duas diferenas: Por conveno, o primeiro parmetro de Mtodos so definidos dentro da definio de uma classe para tornar explcita a relao um mtodo chamado self. A razo para isto um pouco convoluted, mas baseada numa metfora entre a classe e o mtodo. til. >>> horaCorrente.horas = 9

Captulo 14: Classes e mtodos #83

Como pensar como um cientista da Computao usando Python A sintaxe para uma chamada de funo, exibeHora(horaCorrente), sugere que a funo um agente ativo. Diz algo como, ?Ei, exibeHora! Aqui est um objeto para voc exibir.? Na programao orientada a objetos, os objetos so agentes ativos. Uma chamado do tipo horaCorrente.exibeHora() diz ?Ei, horaCorrente! Por favor exiba-se a si mesmo!? mtodo na classe ?Time?.

14.10 Glossrio
linguagem Uma linguagem que prov orientada a caractersticas tais como classes objetos definidas pelo usurio e herana, que facilitam a programao orientada a objetos.

Esta mudana de perspectiva pode ser mais polida, mas no fica bvio que seja til. Nos exemplos que temos visto at aqui, pode ser que no seja. Mas s vezes, deslocar a responsabilidade das programao Um estilo de programao na qual orientada a os dados e as operaes que os funes para cima dos objetos torna possvel objetos manipulam esto organizados em escrever funes mais versteis, e torna mais fcil classes e mtodos. manter e reutilizar o cdigo. mtodo Uma funo que definida dentro de uma definio de classe e chamada em instncias desta 14.3 Um outro exemplo classe. Vamos converter incremento (da Seo 13.3) em um mtodo. Para poupar espao, deixaremos de fora mtodos definidos previamente(anteriormente?), mas voc deve mant-los em sua verso:
class Time: #previous method definitions here... def increment(self, segundos): self.seconds = seconds + self.seconds while self.segundos >= 60: self.seconds = self.segundos - 60 self.minutes = self.minutos + 1 while self.minutes >= 60: self.minutes = self.minutos - 60 self.hours = self.horas + 1

override (sem traducao; termo consagrado) mtodo de inicializao (tambem chamado de construtor)

Substituir uma definio j pronta. Exemplos incluem substituir um parmetro padro por um argumento particular e substituir um mtodo padro, fornecendo um novo mtodo com o mesmo nome. Um mtodo especial que invocado automaticamente quando um novo objeto criado e que inicializa os atributos deste objeto.

sobrecarga Estender a funcionalidade dos de operador operadores nativos (+, -, *, >, <, etc.) de forma que eles funcionem tambm com tipos definidos pelo usurio. produto Operao definida na lgebra escalar linear que multiplica dois pontos (com coordenadas (x,y,z)) e retorna um valor numrico. multiplica Operao definida na lgebra o por escalar linear que multiplica cada uma das coordenadas de um ponto por um valor numrico. polimrfica Uma funo que pode operar com mais de um tipo. Se todas as operaes de uma funo pode ser aplicadas a um certo tipo, ento a funo pode ser aplicada a este tipo.

A transformao puramente mecnica ? movemos a definio do mtodo para dentro da definio da classe e mudamos o nome do primeiro parmetro. Agora podemos como um mtodo:
horaCorrente.incremento(500)

chamar

incremento

De novo, o objeto no qual o mtodo chamado gets atribui ao primeiro parmetro, self. O segundo parmetro, segundo toma(gets) o valor 500. Como um exerccio, converta ? converteParaSegundos? (da Seo 13.5) para um

Captulo 14: Classes e mtodos #84

Como pensar como um cientista da Computao usando Python

Captulo 15: Conjuntos de objetos

15.1 Composio
At agora, voc vio diversos exemplos de composio. Um dos primeiros exemplos foi o uso de uma invocao de mtodo como parte de uma expresso. Outro exemplo a estrutura aninhada dos comandos: voc pode pr um comando if dentro de um lao while, dentro de outro comando if, e assim por diante.

Uma caracterstica bvia deste mapeamento que os naipes so mapeados para inteiros na ordem, de modo que ns podemos comparar naipes pela comparao de inteiros. O mapeamento de posies bastante bvio. Cada uma das posies numricas mapeia para o inteiro correspondente e, as cartas com figura so mapeadas conforme abaixo:

Valete -> 11

Rainha -> 12 Tendo visto este padro, e tendo aprendido a respeito de listas e objetos, voc no Rei -> 13 deveria ficar surpreso em aprender que voc pode O motivo pelo qual ns estamos usando criar listas de objetos. Voc tambm pode criar obejtos que contm listas (como atritos); voc pode notao matemtica para estes mapeamentos que criar listas que contm listas; voc pode criar eles no so parte do programa Python. Eles so parte do projeto do programa, mas eles nunca objetos que contm objetos; e assim por diante. aparecem explicitamente no cdigo. A definio de Neste captulo e no prximo, voc ir classe para o tipo Carta fica parecida com esta: ver alguns exemplos destas combinaes, usando class Carta: objetos Carta como exemplo.

15.2 Objetos Carta

def __init__(self, naipe=0, posicao=0): self.naipe = naipe self.posicao = posicao

Como sempre, ns fornecemos um mtodo de inicializao que recebe um parmetro Se voc no estiver familiarizado com jogos de opcional para cada atributo. cartas, agora um bom momento para conseguir um baralho, ou ento esse captulo pode no fazer Para criar um objeto que representa o 3 muito sentido. H 52 cartas em um baralho, cada de Paus, usa-se este comando: uma das quais pertence a um dos quatro naipes e a uma das treze posies. Os naipes so Espadas, tresDePaus = Carta(0, 3) Copas, Ouros e Paus (em ordem descendente no O primeiro argumento, 0, representa o bridge). As posies so s, 2, 3, 4, 5, 6, 7, 8, 9, 10, naipe de Paus. Valete, Rainha e Rei. Dependendo do jogo, a posio do s pode ser maior do que a do Rei ou menor do que a do 2. Se quisermos definir um novo objeto para representar uma carta, bvio que os atributos devem ser posicao e naipe. No to bvio so os tipos aos quais devem pertencer os atributos. Uma possibilidade usar strings contendo palavras como "Espada" para naipes e "Rainha" para posies. Um problema com esta implementao que no seria fcil comparar cartas para ver qual possui o maior naipe ou posio. Uma alternativa usar inteiros para codificar as posies e naipes. "Codificar", neste caso, no significa o mesmo que as pessoas normalmente pensam, que criptografar ou traduzir para um cdigo secreto. O que um cientista da computao quer dizer com "codificar" "definir um mapeamento entre uma seqncia de nmeros e os itens que eu quero representar". Por exemplo:

15.3 Atributos de classe e o mtodo __str__

Para imprimir objetos Carta de uma maneira que as pessoas possam facilmente ler, ns gostaramos de mapear os cdigos inteiros para palavras. Uma forma natural de fazer isso usar listas de strings. Ns atribumos estas listas para atributos de classe no topo da definio de classe:
class Carta: listaDeNaipes = ["Paus", "Ouros", "Copas", "Espadas"] listaDePosicoes = ["narf", "s", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Valete", "Rainha", "Rei"] # mtodo init omitido def __str__(self): return (self.listaDePosicoes[self.posicao] + " de " + self.ListaDeNaipes[self.naipe])

Espadas -> 3 Copas -> 2 Ouros -> 1 Paus -> 0

Um atributo de classe definido fora de qualquer mtodo, e ele pode ser acessado por Captulo 15: Conjuntos de objetos #85

Como pensar como um cientista da Computao usando Python quaisquer mtodos da classe. exemplo, os inteiros e os nmeros de ponto flutuante so totalmente ordenados. Alguns conjuntos so no-ordenados, o que significa que no existe maneira significativa de dizer que um elemento maior que o outro. Por exemplo, as frutas so no-ordenadas, e por isso que no podemos comparar mas e laranjas.

Dentro de __str__, ns podemos usar listaDeNaipes e listaDePosicoes para mapear os valores numricos de naipe e posicao para strings. Por exemplo, a expresso self.listaDeNaipes[self.naipe] significa "use o atributo naipe do objeto self como um ndice para o atributo de classe chamado listaDeNaipes, e O conjunto de cartas de jogo selecione a string apropriada". parcialmente ordenado, o que significa que s vezes voc pode comparar cartas, e s vezes no. Por O motivo para o "narf" no primeiro exemplo, voc sabe que o 3 de Paus maior do que elemento em listaDePosicoes preencher o lugar do o 2 de Paus, e que o 3 de Ouros maior do que o 3 0-simo elemento da lista, que nunca ser usado. As de Paus. Mas qual o melhor, o 3 de Paus ou o 2 de nicas posies vlidas so de 1 a 13. Este item Ouros? Um tem uma posio maior, mas o outro desperdiado no inteiramente necessrio. Ns tem um naipe maior. poderamos ter iniciado com 0, como normal. Porm, menos confuso codificar 2 como 2, 3 como Para tornar as cartas comparveis, voc 3, e assim por diante. tem que decidir o que mais importante: posio ou naipe. Para ser honesto, a escolha arbitrria. Por Com os mtodos que ns temos at questo de escolha, ns iremos dizer que naipe agora, ns podemos criar e imprimir cartas: mais importante, porque um baralho de cartas novo vem ordenado com todas as cartas de Paus juntas, >>> carta1 = Carta(1, 11) seguidas pelas de Ouros, e assim por diante. >>> print carta1 Com essa deciso, ns podemos escrever Atributos de classe como listaDeNaipes __cmp__: so compartilhados por todos os objetos Carta. A def __cmp__(self, other): vantagem disso que ns podemos usar qualquer # verificar os naipes objeto Carta para acessar os atributos de classe:
Valete de Ouros >>> carta2 = Carta(1, 3) >>> print carta2 3 de Ouros >>> print carta2.listaDeNaipes[1] Ouros if self.naipe > other.naipe: return 1 if self.naipe < other.naipe: return -1 # as cartas tm o mesmo naipe... verificar as posies if self.posicao > other.posicao: return 1 if self.posicao < other.posicao> return -1 # as posies so iguais... um empate return 0

A desvantagem que se ns modificarmos um atributo de classe, isso afetar cada instncia da classe. Por exemplo, se ns Nesta ordenao, Ases so menores do decidirmos que "Valete de Ouros" deveria realmente que 2. se chamar "Valete de Baleias Rodopiantes", ns Como um exerccio, modifique poderamos fazer isso: ``__cmp__``, de modo que os Ases sejam maiores >>> carta1.listaDeNaipes = "Baleias Rodopiantes" do que os Reis.
>>> print carta1 3 de Baleias Rodopiantes

O problema que todos os Ouros se tornam Baleias Rodopiantes:


>>> print carta2 3 de Baleias Rodopiantes

15.5 Baralhos

Agora que ns temos objetos para representar Cartas, o prximo passo lgico definir uma classe Normalmente, no uma boa idia para representar um Baralho. claro que um baralho formado por cartas; portanto, cada objeto modificar atributos de classe. Baralho ir conter uma lista de cartas como um atributo.

15.4 Comparando cartas

A seguir, damos uma definio para a classe Baralho. O mtodo de inicializao cria o atributo cartas e gera o conjunto padro de 52 Para tipos primitivos, existem operadores cartas: condicionais (<, >, ==, etc.) que comparam valores e determinam quando um maior que, menor que ou classe Baralho igual a outro. Para tipos definidos pelo usurio, ns def __init__(self): podemos sobrescrever o comportamento dos self.cartas = [] operadores pr-definidos fornecendo um mtodo for naipe in range(4): __cmp__. Por conveno, __cmp__ recebe dois for posicao in range(1, 14): parmetros, self e other, e retorna 1 se o primeiro self.cartas.append(Carta(naipe, posicao)) objeto for maior, -1 se o segundo objeto for maior, e A maneira mais fcil de popular o 0 se eles forem iguais. baralho com um lao aninhado. O lao externo Alguns tipos so totalmente ordenados, enumera os naipes de 0 at 3. O lao interno o que significa que ns podemos comparar enumera as posies de 1 at 13. Como o lao quaisquer dois elementos e dizer qual o maior. Por externo repete quatro vezes e o lao interno 13 Captulo 15: Conjuntos de objetos #86

Como pensar como um cientista da Computao usando Python vezes, o nmero total de vezes que o corpo Baralho, que se parece com: executado 52 (13 vezes quatro). Cada iterao cria uma nova instncia de Carta com o naipe e posio >>> baralho = Baralho() >>> print Baralho atuais e a inclui na lista cartas. O mtodo append trabalha sobre listas mas no, obviamente, sobre tuplas.
s de Paus 2 de Paus 3 de Paus 4 de Paus 5 de Paus 6 de Paus 7 de Paus 8 de Paus 9 de Paus 10 de Paus Valete de Paus Rainha de Paus Rei de Paus s de Ouros

15.6 Imprimindo o baralho


Como sempre, quando ns definimos um novo tipo de objeto, ns gostaramos de ter um mtodo para imprimir o contedo de um objeto. Para imprimir um Baralho, ns percorremos a lista e imprimimos cada Carta:
class Baralho: ... def imprimirBaralho(self): for carta in self.cartas: print carta

E assim por diante. Mesmo que o resultado aparea em 52 linhas, uma string longa que contm newlines.

Aqui, e a partir daqui, as reticncias (...) indicam que ns omitimos os outros mtodos da classe. Como uma alternativa a imprimirBaralho, ns poderamos escrever um mtodo __str__ para a classe Baralho. A vantagem de __str__ que ela mais flexvel. Em vez de apenas imprimir o contedo de um objeto, ela gera uma representao em string que outras partes do programa podem manipular antes de imprimir ou armazenar para uso posterior. Abaixo, uma verso de __str__ que devolve uma representao em string de um Baralho. Para adicionar um pouco de estilo, ela distribui as cartas em uma cascata, na qual cada carta indentada um espao a mais do que a carta anterior:
class Baralho: ... def __str__(self): s = "" for i in range(len(self.cartas)): s = s + " "*i + str(self.cartas[i]) + "\n" return s

15.7 Embaralhando
Se um baralho estiver perfeitamente embaralhado, ento cada carta tem a mesma probabilidade de aparecer em qualquer lugar no baralho, e qualquer localizao no baralho tem a mesma probabilidade de conter qualquer carta. Para embaralhar as cartas, ns usaremos a funo randrange do mdulo random. Com dois argumentos inteiros, a e b, randrange escolhe um inteiro aleatrio no intervalo a <= x < b. Como o limite superior estritamente menor que b, ns podemos usar o comprimento de uma lista como o segundo parmetro, e ns garantimos que o ndice sempre ser vlido. Por exemplo, esta expresso escolhe o ndice de uma carta aleatria em um baralho:
random.randrange(0, len(self.cartas))

Uma maneira fcil de embaralhar as cartas percorrer a lista e trocar cada carta por outra escolhida aleatoriamente. possvel que a carta seja trocada por ela mesma, mas isso no problema. Na verdade, se ns exclussemos essa Este exemplo demonstra diversas possibilidade, a ordem das cartas no seria caractersticas. Primeiro, em vez de percorrer totalmente aleatria: self.cartas e atribuir cada carta a uma varivel, ns estamos usando i como uma varivel de lao e um class Baralho: ndice para a lista de cartas. ... Segundo, ns estamos usando o operador de multiplicao de strings para indentar cada carta com um espao adicional com relao anterior. A expresso " "*i produz um nmero de espaos igual ao valor atual de i.
def embaralhar(self): import random nCartas = len(self.cartas) for i in range(nCartas): j = random.randrange(i, nCartas) self.cartas[i], self.cartas[j] = self.cartas[j], self.cartas[i]

Terceiro, em vez de usar o comando print para imprimir as cartas, ns usamos a funo Em vez de assumir que existem 52 str. Passar um objeto como um argumento para str cartas no baralho, ns obtivemos o comprimento equivale a invocar o mtodo __str__ sobre o objeto. real da lista e o guardamos na varivel nCartas. Finalmente, ns estamos usando a Para cada carta no baralho, ns varivel s como um acumulador. Inicialmente, s a string vazia. A cada repetio do lao, uma nova escolhemos uma carta aleatria dentre as cartas string gerada e concatenada com o valor antigo de que ainda no foram embaralhadas. Ento, ns s para obter um novo valor. Quando o lao termina, trocamos a carta atual (i) pela carta selecionada (j). s contm a representao em string completa do Para trocar as cartas, ns usamos uma atribuio de Captulo 15: Conjuntos de objetos #87

Como pensar como um cientista da Computao usando Python tupla, como visto na Seo 9.2:
self.cartas[i], self.cartas[j] = self.cartas[j], self.cartas[i]

Como exerccio, reescreva esta linha de cdigo sem usar uma atribuio de seqncia.

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 (accumulato para acumular uma srie de para, por exemplo, r) valores, concaten-los em uma string ou som-los a uma soma em andamento.

15.8 Removendo e distribuindo cartas


Outro mtodo que pode ser til para a classe Baralho removerCarta. Ele recebe uma carta como parmetro, remove-a do baralho e retorna verdadeiro (1), se a carta estava no baralho e falso (0), caso contrrio:
class Baralho: ... def removerCarta(self, carta): if carta in self.cartas: self.cartas.remove(carta) return 1 else return 0

O operador in retorna verdadeiro se o primeiro operando estiver contido no segundo, que deve ser uma lista ou uma tupla. Se o primeiro operando for um objeto, Python usa o mtodo __cmp__ do objeto para determinar igualdade com os itens da lista. Como o mtodo __cmp__ da classe Carta verifica por igualdade profunda, o mtodo removerCarta tambm testa por igualdade profunda. Para distribuir as cartas, ns iremos remover e devolver a carta do topo. O mtodo de lista pop fornece uma maneira conveniente de fazer isso:
class Baralho: ... def distribuirCarta(self): return self.cards.pop()

Na verdade, pop remove a ltima carta da lista. Portanto, ns estamos realmente distribuindo as cartas do fim para o incio do baralho. Uma ltima operao que ns poderamos querer a funo booleana estahVazio, que retorna verdadeiro se o baralho no contm cartas:
class Baralho: ... def estahVazio(self): return (len(self.cartas) == 0)

15.9 Glossrio
codificar Representar um conjunto de valores (encode) usando outro conjunto de valores, construindo um mapeamento entre eles. atributo de Uma varivel que definida dentro classe (class de uma definio de classe, mas atribute) fora de qualquer mtodo. Atributos Captulo 15: Conjuntos de objetos #88

Como pensar como um cientista da Computao usando Python

Captulo 15: Conjuntos de objetos #89

Como pensar como um cientista da Computao usando Python

Capitulo 16: Herana

pquer, podemos classificar uma mo (trinca, flush, etc.) ou compar-la com outra mo. No jogo de bridge, podemos querer computar a quantidade de Uma das caractersticas mais marcantes das pontos que h numa mo, a fim de fazer um lance. linguagens orientadas a objetos a herana. Essa situao sugere o uso de herana. Herana a habilidade de definir uma nova classe Se Mao uma subclasse de Baralho, ter todos os que uma verso modificada de uma classe mtodos de Baralho, e novos mtodos podem ser existente. adicionados. A principal vantagem dessa Na definio de classe, o nome da classe caracterstica que voc pode adicionar novos pai aparece entre parnteses: mtodos a uma classe sem ter que modificar a classe existente. Chama-se "herana" porque a nova class Mao(Baralho): classe herda todos os mtodos da classe existente. pass Ampliando a metfora, podemos dizer que a classe Esse comando indica que a nova classe existente s vezes chamada de classe me (parent). A nova classe pode ser chamada de classe Mao herda da classe existente Baralho. filha ou, simplesmente, "subclasse". O construtor de Mao inicializa os atributos da mo, que so nome e cartas. A string A herana uma caracterstica poderosa. Alguns programas que seriam nome identifica essa mo, provavelmente pelo complicados sem herana podem ser escritos de nome do jogador que est segurando as cartas. O forma simples e concisa graas a ela. E a herana nome um parmetro opcional com a string vazia tambm pode facilitar o reuso do cdigo, uma vez como valor default. cartas a lista de cartas da que voc pode adaptar o comportamento de classes mo, inicializada com uma lista vazia existentes sem ter que modific-las. Em alguns class Mao(Baralho): casos, a estrutura da herana reflete a natureza real def __init__(self, nome=""): do problema, tornando o programa mais fcil de self.cartas = [] entender.

16.1 Herana

Por outro lado, a herana pode tornar um programa seja difcil de ler. Quando um mtodo invocado, s vezes no est claro onde procurar sua definio. A parte 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 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.

self.nome = nome

Em praticamente todos os jogos de cartas, necessario adicionar e remover cartas do baralho. Remover cartas j est resolvido, uma vez que Mao herda removerCarta de Baralho. Mas precisamos escrever adicionarCarta:
class Mao(Baralho): #... def adicionarCarta(self,carta): self.cartas.append(carta)

De novo, a elipse indica que omitimos Nesse captulo, vamos demonstrar o uso outros mtodos. O mtodo de listas append adiciona de herana como parte de um programa que joga a nova carta no final da lista de cartas. uma variante de Mico. Um dos nossos objetivos escrever um cdigo que possa ser reutilizado para implementar outros jogos de cartas.

16.3 Dando as cartas

16.2 Uma mo de cartas

Para quase todos os jogos de baralho, preciso representar uma mo de cartas. Uma mo de cartas similar a um mao de baralho. Porque ambos so formados por uma srie de cartas e ambos requerem operaes, como, adicionar e remover O mtodo distribuir deve ser bem geral, cartas. Fora isso, a habilidade de embaralhar a mo j que diferentes jogos tero diferentes e o baralho tambm so teis. requerimentos. Podemos querer distribuir o Mas, ao mesmo tempo, a mo tambm baralho inteiro de uma vez s ou adicionar uma diferente do baralho. Dependendo do jogo que est carta a cada mo. sendo jogado, precisamos realizar algumas distribuir recebe dois argumentos, uma operaes nas mos de cartas que no fazem sentido para o baralho inteiro. Por exemplo, no lista (ou tupla) de mos e o numero total de cartas a Capitulo 16: Herana #90

Agora que temos uma classe Mao, queremos distribuir cartas de Baralho para mos de cartas. No imediatamente bvio se esse mtodo deve ir na classe Mao ou na classe Baralho, mas como ele opera num nico baralho e (possivelmente) em vrias mos de cartas, mais natural coloc-lo em Baralho.

Como pensar como um cientista da Computao usando Python serem dadas. Se no houver cartas suficientes no baralho, o mtodo d todas as cartas e pra:
class Baralho: #... def distribuir(self, maos, nCartas=999): nMaos = len(maos) for i in range(nCartas): if self.estahVazia(): break # interromper se acabaram as cartas carta = self.pegarCarta() # pegar a carta do topo mao = maos[i % nMaos] # quem deve receber agora? mao.adicionarCarta(carta) # adicionar a carta mao Baralho.__str__(self)

Inicialmente, s uma string que identifica a mo. Se a mo estiver vazia, o programa acrescenta as palavras est vazia e retorna o resultado. Se no, o programa acrescenta a palavra contm e a representao de string do Baralho, computada pela invocao do mtodo __str__ na classe Baralho em self. Pode parecer estranho enviar self, que se refere Mao corrente, para um mtodo Baralho, mas isso s at voce se lembrar que um Mao um tipo de Baralho. Objetos Mao podem fazer tudo que os objetos Baralho fazem, entao, permitido passar uma instncia de Mao para um mtodo Baralho.

Em geral, sempre permitido usar uma O segundo parmetro, nCartas, opcional; o default um nmero grande, o que na instncia de uma subclasse no lugar de uma prtica significa que todas as cartas do baralho instncia de uma classe me. sero dadas se este parmetro for omitido. A varivel do lao i vai de 0 a nCartas-1. A cada volta do lao, uma carta removida do 16.5 A classe JogoDeCartas baralho, usando o mtodo de lista pop, que remove e retorna o ltimo item na lista. A classe JogoDeCartas toma conta de algumas bsicas comuns a todos os jogos, como, criar O operador mdulo (%) permite dar tarefas o baralho e embaralh-lo: cartas em ao redor da mesa (uma carta de cada vez para cada mo). Quando i igual ao numero de class JogoDeCartas: mos na lista, a expresso i % nMaos volta para o def __init__(self): comeo da lista (ndice 0). self.baralho = Baralho()
self.baralho.embaralhar()

Este o primeiro dos casos que vimos at agora em que o mtodo de inicializao realiza uma computao significativa, para alm de Para exibir o contedo de uma mo, podemos tirar inicializar atributos. vantagem dos mtodos exibirBaralho e __str__ Para implementar jogos especficos, herdados de Baralho. Por exemplo: podemos herdar de JogoDeCartas e adicionar caracteristicas para o novo jogo. Como exemplo, >>> baralho = Baralho() vamos escrever uma simulao de Mico. >>> baralho.embaralhar()

16.4 Exibindo a mao

Antes de mais nada, a Dama de paus removida do baralho, para que a Dama de espadas Nao l uma grande mo, mas tem fique sem par. A Dama de espadas ento faz o papel potencial para um straight flush. do mico. As 51 cartas que sobram so distribuidas Embora seja conveniente herdar os aos jogadores em ao redor da mesa (uma carta de mtodos existentes, h outras informacoes num cada vez para cada mo). Depois que as cartas objeto Mao que podemos querer incluir quando ao foram dadas, os jogadores devem fazer todos os exib-lo. Para fazer isso, podemos fornecer um casais possveis que tiverem na mo, e em seguida mtodo __str__ para a classe Mao que sobrescreva o descart-los na mesa. da classe Baralho: Quando ningum mais tiver nenhum par para descartar, o jogo comea. Na sua vez de class Mao(Baralho) jogar, o jogador pega uma carta (sem olhar) do #... vizinho mais proximo esquerda, que ainda tiver def __str__(self): cartas. Se a carta escolhida casar com uma carta s = "Mao " + self.nome que ele tem na mo, ele descarta esse par. Quando if self.estahVazia(): todos os casais possveis tiverem sido feitos, o return s + " est vazia\n" jogador que tiver sobrado com a Dama de espadas na mo perde o jogo. else:
return s + " contm\n" +

>>> mao = Mao("fabio") >>> baralho.distribuir([mao], 5) >>> print mao Mo fabio contm 2 de espadas 3 de espadas 4 de espadas s de copas 9 de paus

O objetivo do jogo livrar-se das cartas que estiverem na mo. Para fazer isso, preciso combinar cartas formando pares ou casais que tenham a mesma cor e o mesmo nmero ou figura. Por exemplo, o 4 de paus casa com o 4 de espadas porque os dois naipes so pretos. O Valete de copas combina com o Valete de ouros porque ambos so vermelhos.

Em nossa simulao computacional do Capitulo 16: Herana #91

Como pensar como um cientista da Computao usando Python jogo, o computador joga todas as mos. Infelizmente, algumas nuances do jogo presencial se perdem. Num jogo presencial, o jogador que est com o mico na mo pode usar uns truques para induzir o vizinho a pegar a carta, por exemplo, segurando-a mais alto que as outras, ou mais baixo, ou se esforando para que ela no fique em destaque. J o computador simplesmente pega a carta do vizinho aleatoriamente...
Valete de ouros 10 de ouros 10 de copas >>> mao.descartarCasais() Mo fabio: 7 de espadas faz par com 7 de paus Mo fabio: 8 de espadas faz par com 8 de paus Mo fabio: 10 de ouros faz par com 10 de copas >>> print mao Mo fabio contm s de espadas 2 de ouros 6 de copas Rainha de paus 7 de ouros 5 de paus Valete de ouros

16.6 Classe MaoDeMico


Uma mo para jogar Mico requer algumas habilidades para alem das habilidades gerais de uma Mao. Vamos definir uma nova classe, MaoDeMico, que herda de Mao e prov um mtodo adicional chamado descartarCasais:
class MaoDeMico(Mao): def descartarCasais(self): conta = 0 cartasIniciais = self.cartas[:] for carta in cartasIniciais: casal = Carta(3 - carta.naipe, carta.valor) if casal in self.cartas: self.cartas.remove(carta) self.cartas.remove(casal) print "Mao %s: %s casais %s" % (self.nome,carta,casal) conta = conta + 1 return conta

Observe que no existe um mtodo __init__ para a classe MaoDeMico. Ele herdado de Mao.

16.7 Classe Mico


Agora podemos focar nossa ateno no jogo em si. Mico uma subclasse de JogoDeCartas com um novo mtodo chamado jogar que recebe uma lista de jogadores como argumento.

J que __init__ herdado de JogoDeCartas, um novo objeto Mico contm um Comeamos fazendo uma cpia da lista novo baralho embaralhado: de cartas, para poder percorrer a cpia enquanto class Mico(JogoDeCartas): removemos cartas do original. Uma vez que def jogar(self, nomes): self.cartas modificada no lao, no queremos us# remover a Dama de paus la para controlar o percurso. Python pode ficar bem self.baralho.removerCarta(Carta(0,12)) confuso se estiver percorrendo uma lista que est mudando! Para cada carta na mo, verificamos qual a carta que faz par com ela e vamos procurla. O par da carta tem o mesmo valor (nmero ou figura) e naipe da mesma cor. A expresso 3 carta.naipe transforma um paus (naipe 0) numa espadas (naipe 3) e um ouros (naipe 1) numa copas (naipe 2). Voc deve analisar a frmula at se convencer de que as operaes opostas tambm funcionam. Se o par da carta tambem estiver na mo, ambas as cartas so removidas. O exemplo a seguir demonstra como usar descartarCasais:
>>> jogo = JogoDeCartas() >>> mao = MaoDeMico("fabio") >>> jogo.baralho.distribuir([mao], 13) >>> print mao mo fabio contm s de espadas 2 de ouros 7 de espadas 8 de paus 6 de copas 8 de espadas 7 de paus Rainha de paus 7 de ouros 5 de paus # fazer uma mo para cada jogador self.maos = [] for nome in nomes : self.maos.append(MaoDeMico(nome)) # distribuir as cartas self.baralho.distribuir(self.maos) print "---------- As cartas foram dadas" self.exibirMaos() # remover casais iniciais casais = self.removerTodosOsCasais() print "---------- Os pares foram descartados, o jogo comea" self.exibirMaos() # jogar at que 25 casais se formem vez = 0 numMaos = len(self.maos) while casais < 25: casais = casais + self.jogarVez(vez) vez = (vez + 1) % numMaos print "---------- Fim do jogo" self.exibirMaos()

separadas

Algumas etapas do jogo foram em mtodos. removerTodosOsCasais

Capitulo 16: Herana #92

Como pensar como um cientista da Computao usando Python percorre a lista de mos e invoca descartarCasais causaria um erro em outra parte do programa. em cada uma: Felizmente, podemos provar que isso nunca vai acontecer (desde que o fim do jogo seja detectado class Mico(JogoDeCartas): corretamente).
#... def removerTodosOsCasais(self): conta = 0 for mao in self.maos: conta = conta + mao.descartarCasais() return conta

No mencionamos o mtodo exibirBaralhos. Esse voc mesmo pode escrever.

A sada a seguir produto de uma forma reduzida do jogo, onde apenas as 15 cartas mais altas do baralho (do 10 para cima) foram Como exerccio, escreva ``exibirMaos`` dadas, para trs jogadores. Com esse baralho reduzido, a jogada pra depois que 7 combinaes que percorre ``self.maos`` e exibe cada mo. foram feitas, ao invs de 25: conta uma acumulador que soma o >>> import cartas nmero de pares em cada mo e retorna o total. Quando o nmero total de pares alcana 25, 50 cartas foram removidas das mos, o que significa que sobrou s uma carta e o jogo chegou ao fim. A varivel vez mantm controle sobre de quem a vez de jogar. Comea em 0 e incrementa de um em um; quando atinge numMaos, o operador mdulo faz ela retornar para 0. O mtodo jogarVez recebe um argumento que indica de quem a vez de jogar. O valor de retorno o nmero de pares feitos durante essa rodada:
class Mico(JogoDeCartas): #... def jogarVez(self, i): if self.maos[i].estahVazia(): return 0 vizinho = self.buscarVizinho(i) novaCarta = self.maos[vizinho].pegarCarta() self.maos[i].adicionarCarta(novaCarta) print "Mao", self.maos[i].nome, "pegou", novaCarta conta = self.maos[i].descartarCasais() self.maos[i].embaralhar() return conta >>> jogo = cartas.Mico() >>> jogo.jogar(["Alice","Jair","Clara"]) ---------- As cartas foram dadas Mo Alice contm Rei de copas Valete de paus Rainha de espadas Rei de espadas 10 de ouros Mo Jair contm Rainha de copas Valete de espadas Valete de copas Rei de ouros Rainha de ouros Mo Clara contm Valete of ouros Rei de paus 10 de espadas 10 de copas 10 de paus Mo Jair: Dama de copas faz par com Dama de ouros Mo Clara: 10 de espadas faz par com 10 de paus ---------- Os pares foram descartados, o jogo comea Mo Alice contm Rei de copas Valete de paus Rainha de espadas Rei de espadas 10 de ouros Mo Jair contm Valete de espadas Valete de copas Rei de ouros Mo Clara contm Valete de ouros Rei de paus 10 de copas Mo Mo Mo Mo Mo Alice pegou o Rei de ouros Alice: Rei de copas faz par com Rei de ouros Jair pegou 10 de copas Clara pegou Valete de paus Alice pegou Valete de copas

Se a mo de um jogador estiver vazia, ele est fora do jogo, ento, ele no faz nada e retorna 0. Do contrrio, uma jogada consiste em achar o primeiro jogador esquerda que tenha cartas, pegar uma carta dele, e tentar fazer pares. Antes de retornar, as cartas na mo so embaralhadas, para que a escolha do prximo jogador seja aleatria. O mtodo buscarVizinho comea com o jogador imediatamente esquerda e continua ao redor da mesa at encontrar um jogador que ainda tenha cartas:
class Mico(JogoDeCartas): #... def buscarVizinho(self, i): numMaos = len(self.maos) for next in range(1,numMaos): vizinho = (i + next) % numMaos if not self.maos[vizinho].estahVazia(): return vizinho

Se buscarVizinho alguma vez circulasse pela mesa sem encontrar cartas, retornaria None e

Capitulo 16: Herana #93

Como pensar como um cientista da Computao usando Python


Mo Jair pegou Valete de ouros Mo Clara pegou Dama de espadas Mo Alice pegou Valete de ouros Mo Alice: Valete de copas faz par com Valete de ouros Mo Jair pegou Rei de paus Mo Clara pegou Rei de espadas Mo Alice pegou 10 de copas Mo Alice: 10 de ouros faz par com 10 de copas Mo Jair pegou Dama de espadas Mo Clara pegou Valete de espadas Mo Clara: Valete de paus faz par com Valete de espadas Mo Jair pegou Rei de espadas Mo Jeff: Rei de paus faz par com Rei de espadas ---------- Fim do jogo Mo Alice est vazia Mo Jair contm Rainha de espadas

Mo Clara est vazia Ento, o Jair perdeu.

16.8 Glossrio
herana Habilidade de definir uma (inheritance) nova classe que a verso modificada de uma classe definida anteriormente. classe me A classe de quem a classe filha (parent class) herda. classe filho (child Um nova classe criada class) herdando de uma classe existente; tambm chamada de "subclasse".

Capitulo 16: Herana #94

Como pensar como um cientista da Computao usando Python

Captulo 17: Listas encadeadas

17.1 Referncias Embutidas

Ns temos visto exemplos de atributos que Este cdigo cria trs ns, mas ns ainda referenciam outros objetos, que so chamados no temos uma lista ainda porque os ns no esto referncias embutidas (veja a Seo 12.8). Uma ligados. O diagrama de estado parecido com este: estrutura de dados comum, a lista ligada, tira vantagem desta caracterstica. Listas ligadas so constitudas de ns (nodos), onde cada n contm uma referncia para o prximo n na lista. Alm disto, cada n contm uma unidade de dados chamada a carga. Uma lista ligada considerada uma estrutura de dados recorrente porque ela tem uma definio recorrente. Uma lista ligada :

>>> no1 = No(1) >>> no2 = No(2) >>> no3 = No(3)

Uma lista vazia, representada por None, ou Um n que contm um objeto carga e uma referncia para uma lista ligada.

Para ligar os ns, temos que fazer o primeiro n da lista referir ao segundo e o segundo n referir ao terceiro:
>>> no1.proximo = no2 >>> no2.proximo = no3

A referncia do terceiro n None, que Estruturas de dados recorrentes so indica que ele o final da lista. Agora o diagrama de estado se parece com: adequadas para mtodos recorrentes.

17.2 A classe No (Node)


Como usual quando se escreve uma nova classe, ns comearemos com os mtodos de inicializao e __str__ de modo que podemos testar o mecanismo Agora voc sabe como criar ns e ligbsico de se criar e mostrar o novo tipo: los em uma lista. O que pode estar menos claro neste ponto por qu.
class No: def __init__(self, carga=None, proximo=None): self.carga = carga self.proximo = proximo def __str__(self): return str(self.carga)

17.3 Listas como Colees

Listas so teis porque elas provm um modo de montar mltiplos objetos em uma nica entidade, algumas vezes chamada uma coleo. No exemplo, Como de costume, os parmetros para o o primeiro n da lista serve como uma referncia mtodo de inicializao so opcionais. Por omisso para toda a lista. (default), ambos, a carga e a ligao, proximo, so definidas como None. Para passar uma lista como um parmetro, voc apenas tem que passar uma A representao string de um n referncia ao primeiro n. Por exemplo, a funo simplesmente a representao string da carga. imprimeLista toma um nico n como um Como qualquer valor pode ser passado para a argumento. Iniciando com o cabea da lista, ela funo str, ns podemos armazenar qualquer valor imprime cada n at que chegue ao fim: em uma lista. Para testar a implementao at agora, ns criamos um No e o imprimimos:
>>> no = No("teste") >>> print no teste def imprimeLista(no): while no: print no, no = no.proximo print

Para chamar este mtodo, ns passamos Para ficar interessante, ns precisamos uma referncia ao primeiro no: uma lista com mais do que um n:
>>> imprimeLista(no1)

Captulo 17: Listas encadeadas #95

Como pensar como um cientista da Computao usando Python


1 2 3 >>> imprimeDeTrasParaFrente(no1)

Dentro de imprimeLista ns temos uma 3 2 1 referncia para o primeiro n da lista, mas no h O resultado a lista de trs para frente. variveis que refiram aos outros ns. Ns temos que Voc pode se perguntar por qu usar o valor proximo de cada n para alcanar o imprimeLista e imprimeDeTrasParaFrente so prximo n. funes e no mtodos da classe No. A razo que Para percorrer uma lista ligada, ns queremos usar None para representa a lista comum usar uma varivel lao como no para vazia e no legal invocar um mtodo sobre None. referir a cada um dos ns sucessivamente. Esta limitao torna complicado escrever cdigo de manipulao de lista em estilo orientado a objeto Este diagrama mostra o valor de lista e limpo. os valores que no assume: Podemos provar que imprimeDeTrasParaFrente sempre termina? Em outras palavras, ir ela sempre atingir o caso base? De fato, a resposta no. Algumas listas faro este mtodo falhar.

17.5 Listas Infinitas


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. No h nada que impea um n de referenciar de volta um n anterior na lista, incluindo ele mesmo. Por exemplo, esta figura mostra uma lista com dois ns, um dos quais refere-se a si mesmo:

17.4 Listas e Recorrncia


natural expressar muitas operaes de listas utilizando mtodos recorrentes. Por exemplo, o seguinte um algoritmo recorrente para imprimir uma lista de trs para frente. 1. Separe a lista em dois pedaos: o primeiro n (chamado a cabea); e o resto (chamado o rabo). Se ns invocarmos imprimeLista nesta lista, ele ficar em lao para sempre. Se ns invocarmos imprimeDeTrasParaFrente, ele 3. Imprima a cabea. recorrer infinitamente. Este tipo de Logicamente, o Passo 2, a chamada comportamento torna as listas infinitas difceis de recorrente, assume que ns temos um modo de se lidar. imprimir a lista de trs para frente. Mas se ns A despeito disto, elas ocasionalmente assumimos que a chamada recorrente funciona -- o passo de f -- ento podemos nos convencer de que so teis. Por exemplo, podemos representar um nmero como uma lista de dgitos e usar uma lista o algoritmo funciona. infinita para representar uma frao repetente. Tudo o que precisamos so um caso Mesmo assim, problemtico que no base e um modo de provar que para qualquer lista, provar que imprimeLista e ns iremos, ao final, chegar no caso base. Dada a possamos definio recorrente de uma lista, um caso base imprimeDeTrasParaFrente terminem. O melhor que podemos fazer a afirmao hipottica, "Se a lista natural a lista vazia, representada por None: no contm laos, ento este mtodo terminar." def imprimeDeTrasParaFrente(lista): Este tipo de hiptese chamado uma pr-condio. if lista == None : return Ele impe uma limitao sobre um dos parmetros e descreve o comportamento do mtodo se a cabeca = lista limitao satisfeita. Voc ver mais exemplos em rabo = lista.proximo breve. imprimeDeTrasParaFrente(rabo) 2. Imprima o rabo de trs para frente.
print cabeca,

A primeira linha trata o caso base fazendo nada. As prximas duas linhas dividem a lista em cabeca e rabo. As duas ltimas linhas imprimem a lista. A vrgula no final da ltima linha impede o Python de imprimir uma nova linha aps cada n. Ns invocamos invocamos o imprimeLista: este mtodo

17.6 O Teorema da Ambigidade Fundamental

Uma parte de imprimeDeTrasParaFrente pode ter como gerado surpresa:

Captulo 17: Listas encadeadas #96

Como pensar como um cientista da Computao usando Python


cabeca = lista rabo = lista.proximo >>> 1 2 >>> >>> 2 >>> 1 3 imprimeLista(no1) 3 removido = removeSegundo(no1) imprimeLista(removido)

Aps a primeira atribuio, cabeca e lista tm o mesmo tipo e o mesmo valor. Ento por que ns criamos uma nova varivel?

imprimeLista(no1) A razo que as duas variveis tm diferentes papis. Quando pensamos em cabeca, pensamos como uma referncia a um nico n, e Este diagrama de estado mostra o efeito quando pensamos em lista o fazemos como uma da operao: referncia ao primeiro n da lista. Estes "papis" no so parte do programa; eles esto na mente do programador.

Em geral no podemos dizer olhando para o programa qual o papel que uma varivel tem. Esta ambigidade pode ser til, mas tambm pode tornar os programas difceis de serem lidos. Usamos freqentemente nomes de variveis como no e lista para documentar como pretendemos usar O que acontece se voc invocar este uma varivel e algumas vezes criamos variveis mtodo e passar uma lista com somente um adicionais para remover a ambigidade. elemento (um singleton )? O que acontece se voc Poderamos ter escrito passar a lista vazia como um argumento? Existe imprimeDeTrasParaFrente sem cabeca e rabo, que a uma pr-condio para este mtodo? Se houver, tornaria mais concisa mas possivelmente menos corrija o mtodo para tratar uma violao da prcondio de modo razovel. clara:
def imprimeDeTrasParaFrente(lista): if lista == None : return imprimeDeTrasParaFrente(lista.proximo) print lista,

17.8 Envoltrios e Ajudadores

Freqentemente til dividir uma operao de lista em dois mtodos. Por exemplo, para imprimir uma lista de trs para frente no formato convencional de lista [3, 2, 1], podemos usar o mtodo imprimeDeTrasParaFrente para imprimir 3, 2, mas queremos um metodo separado para imprimir os O teorema da ambigidade braquetes e o primeiro n. Vamos cham-lo de fundamental descreve a ambigidade que imprimeDeTrasParaFrenteLegal: inerente referncia a um n: Olhando para as duas chamadas de funo, temos que lembrar que imprimeDeTrasParaFrente trata seu argumento como uma coleo e print trata seu argumento como um objeto nico. Uma varivel que refere a um n pode tratar o n como um objeto nico ou como o primeiro em uma lista de ns.
def imprimeDeTrasParaFrenteLegal(lista): print "[", if lista != None : cabeca = lista rabo = lista.proximo imprimeDeTrasParaFrente(rabo) print cabeca, print "]",

17.7 Modificando Listas

Existem duas maneiras de se modificar uma lista Novamente, uma boa idia verificar ligada. Obviamente, podemos modificar a carga dos mtodos como este para ver se eles funcionam com ns, mas as operaes mais interessantes so casos especiais como uma lista vazia ou um aquelas que adicionam, removem ou reordenam os singleton. ns. Quando usamos este mtodo em algum Como um exemplo, vamos escrever um lugar no programa, invocamos mtodo que remove o segundo n na lista e retorna imprimeDeTrasParaFrenteLegal diretamente, e ele uma referncia ao n removido: invoca imprimeDeTrasParaFrente por ns. Neste sentido, imprimeDeTrasParaFrenteLegal atua como def removeSegundo(lista): um envoltrio, e usa imprimeDeTrasParaFrente if lista == None : return como um ajudador.
primeiro = lista segundo = lista.proximo # faz o primeiro no referir ao terceiro primeiro.proximo = segundo.proximo # separa o segundo no do resto da lista segundo.proximo = None return segundo

17.9 A Classe ListaLigada

Existem alguns problemas sutis com o modo que implementamos listas. Em um inverso de causa e efeito, proporemos uma implementao alternativa Novamente, estamos usando variveis primeiro e ento explicaremos qual problema ela temporrias para tornar o cdigo mais fcil de ser resolve. lido. Aqui est como usar este mtodo: Captulo 17: Listas encadeadas #97

Como pensar como um cientista da Computao usando Python Primeiro, criaremos uma nova classe chamada ListaLigada. Seus atributos so um inteiro que contm o comprimento da lista e uma referncia para o primeiro n. Objetos do tipo ListaLigada servem como cabos (handles) para se manipular listas de objetos No:
class ListaLigada: def __init__(self): self.comprimento = 0 self.cabeca = None

que podemos querer requerer que listas no contenham laos. Outro requerimento que o valor de comprimento no objeto ListaLigada seja igual ao nmero real de ns da lista. Requerimentos como estes so chamados de invariantes porque, idealmente, eles deveriam ser verdade para cada objeto o tempo todo. Especificar invariantes para objetos um prtica de programao til porque torna mais fcil provar a correo do cdigo, verificar a integridade das estruturas de dados e detectar erros.

Uma coisa legal acerca da classe Uma coisa que algumas vezes confusa ListaLigada que ela prov um lugar natural para se colocar funes envoltrias como acerca de invariantes que existem momentos em imprimeDeTrasParaFrenteLegal, que podemos que eles so violados. Por exemplo, no meio de adicionaPrimeiro, aps termos adicionado o n mas transformar em um mtodo da classe ListaLigada: antes de termos incrementado comprimento, o class ListaLigada: invariante violado. Este tipo de violao ... aceitvel; de fato, freqentemente impossvel def imprimeDeTrasParaFrente(self): modificar um objeto sem violar um invariante por, no mnimo, um pequeno instante. Normalmente, print "[", requeremos que cada mtodo que viola um if self.cabeca != None : invariante deve restaurar este invariante. self.cabeca.imprimeDeTrasParaFrente()
print "]",

class No: ... def imprimeDeTrasParaFrente(self): if self.proximo != None: rabo = self.proximo rabo.imprimeDeTrasParaFrente() print self.carga,

Se h qualquer aumento significativo de cdigo no qual o invariante violado, importante tornar isto claro nos comentrios, de modo que nenhuma operao seja feita que dependa daquele invariante.

17.11 Glossrio
referncia Uma referncia embutida armazenada/associada em/a (embedded um atributo de um objeto. reference) lista ligada Uma estrutura de dados que uma coleo (linked list) implementa usando uma sequncia de ns ligados. n ou nodo Um elemento de uma lista, implementado (node) usualmente como um objeto que contm uma referncia para outro objeto do mesmo tipo. carga (cargo) Um item de dado contido em um n. referncia embutida ligao (link) Uma usada para ligar/conectar um objeto a outro. pr-condio Uma assero que (precondition) precisa/deve ser verdadeira para que um mtodo trabalhe corretamante. teorema da ambigidade fundamental (fundamental ambiguity theorem) Uma referncia para um n de uma lista pode ser tratada como um objeto nico ou como o primeiro em uma lista de ns.

Apenas para tornar as coisas confusas, mudamos o nome de imprimeDeTrasParaFrenteLegal. Agora existem dois mtodos chamados imprimeDeTrasParaFrente: um na classe No (o ajudador); e um na classe ListaLigada``(o envoltrio). Quano o envoltrio invoca ``self.cabeca.imprimeDeTrasParaFrente, ele est invocando o ajudador, porque self.cabeca um objeto No. Outro benefcio da classe ListaLigada que ela torna mais fcil adicionar e remover o primeiro elemento de uma lista. Por exemplo, adicionaPrimeiro um mtodo para ListaLigada; ele toma um item de carga como argumento e o coloca no incio da lista:
class ListaLigada: ... def adicionaPrimeiro(self, carga): no = No(carga) no.proximo = self.cabeca self.cabeca = no self.comprimento = self.comprimento + 1

Como de costume, voc deve conferir cdigos como este para ver se eles tratam os casos especiais. Por exemplo, o que acontece se a lista est inicialmente vazia?

17.10 Invariantes
Algumas listas so "bem formadas"; outras no o so. Por exemplo, se uma lista contm um lao, ela far muitos de nossos mtodos falharem, de modo

singleton Uma lista ligada com somente (singleton) um n. envoltrio Um mtodo que atua como um (middleman) (wrapper) intermedirio

Captulo 17: Listas encadeadas #98

Como pensar como um cientista da Computao usando Python entre um chamador e um mtodo ajudador (helper), freqentemente tornando a invocao do mtodo mais fcil ou menos propensa a erros. ajudador (helper) Um mtodo que no invocado diretamente pelo chamador (caller) mas usado por outro mtodo realizar parte de operao. para uma

invariante Uma assero que deveria ser (invariant) verdadeira sempre para um objeto (exceto talvez enquanto o objeto estiver sendo modificado).

Captulo 17: Listas encadeadas #99

Como pensar como um cientista da Computao usando Python

Captulo 18: Pilhas

18.1 Tipos abstratos de dados

pop : Remove um tem da pilha e o retorna, O tem que retornadao sempre o ltimo adicionado.

Os tipos de dados que voc viu at agora so todos isEmpty : Verifica se a pilha est vazia. concretos, no sentido que ns especificamos completamente como eles so implementados. Por Uma s vezes chamada uma estrutura exemplo, a classe Card(XXX ver como foi traduzido) de dados "last in, first out" ou LIFO, porque o ltimo representa uma carta utilizando dois inteiros. Como tem adicionad o primeiro a ser removido. discutimos no momento, esta no a nica maneira de representar uma carta; existem muitas implementaes alternativas. Um tipo abstrato de dado, ou TAD, especifica um conjunto de operaes (ou mtodos) e Python a semntica das operaes (o que elas fazem), mas no especifica a implementao das operaes. Isto As operaes de lista que Python oferecem so o que o faz abstrato. similares s operaes que definem uma pilha. A Por que isto til? interface no exatamente o que se supe ser, mas podemos escrever um cdigo para traduzir do TAD Simplifica a tarefa dde especificar um Pilha para as operaes nativas. algoritmo se voc pode XXXdenotar(denote) as operaes que voc precisa sem ter que Este cdigo chamado uma pensar, ao mesmo tempo, como as operaes implementao do TAD Pilha. Geralmente, uma so executadas. implementaa um conjunto de mtodos que satisfazem os requisitos sintticos e semnticos de Uma vez que existem geralmente muitas uma interface. maneiras de implementar um TAD, pode ser til escrever um algritmo que pode ser Aqui est uma implementao do TAD usado com qualquer das possveis Pilha que usa uma lista do Python: implementaes.

18.3 Implementando pilhas com listas de

TADs bastante conhecidos, como o TAD Pilha deste captulo, j esto implementados em bibliotecas padro, ento eles podem ser escritos uma vez e usado por muitos programadores. As operaes em TADs provm linguagem de alto nvel comum especificar e falar sobre algoritmos. uma para

class Stack : def __init__(self) : self.items = []

def push(self, item) : self.items.apend(item) def pop(self) : return self.items.pop() def isEmpty(self) : return (self.items == [])

Quando falamos sobre TADs, geralmente distinguimos o cdigo que usa o TAD, chamado cliente, do cdigo que implementa o TAD, chamado cdigo fornecedor .

18.2 O TAD Pilha

Um objeto Stack contm um atributo chamado items que uma lista de tens na pilha. O mtodo de inicializao define items como uma lista vazia.

Para adicionar um novo tem na pilha, Neste captulo, iremos olhar um TAD comum, a push o coloca em items. Para remover um tem da pilha. Uma pilha uma coleo, ou seja, uma pilha, pop usa o mtodo de lista homnimo para estrutura de dados que contei mltiplos elementos. remover e retornar um ltimo tem da lista. Outras colees que vimos incluem dicionrios e Finalmente, para verificar se a pilha listas. est vazia, isEmpty comprara items a uma lista Um TAd definido pelo conjunto de vazia. operaes que podem ser executadas nele, que Uma implementao como esta, na qual chamado interface. A interface para uma pilha os mtodos consistem de simples invocaes de consiste nestas operaes: mtodos existentes, chamado revestimento . Na __init__ : Inicializa uma nova pilha vida real, revestimento uma fina camada de vazia. madeira de boa qualidade usado em XXX*furnituremaking* para esconder madeira de menor push : Adiciona um novo item na pilha qualidade embaixo. Cientistas da Computao usam Captulo 18: Pilhas #100

Como pensar como um cientista da Computao usando Python esta metfora para descrever um pequeno trecho de cdigo que esconde os detalhes de uma implementao e fornece uma interface mais simples, ou mais padronizada.

Como um exerccio, aplique este algoritmo expresso 1 2 + 3 * .

18.4 Empilhando e desempilhando


Uma pilha uma estrutura de dados genrica , o que significa que podemos adicionar qualquer tipo de tem a ela. O exemplo a seguir empilha dois inteiros e uma XXXstring na pilha:
>>> >>> >>> >>> s = Stack() s.push(54) s.push(45) s.push("+")

Este exemplo demonstra uma das vantagens da notao ps-fixa - no necessrio usar parnteses para controlar a ordem das operaes. Para ter o mesmo resultado em notao infixa, deveramos escrever (1 + 2) * 3. Como um exerccio, escreva a expresso ps-fixa que equivalente a 1 + 2 * 3.

18.6 Anlise sinttica

Para implementar o algoritmo anterior, necessitamos estar prontos para percorrer uma string e quebr-la em operandos e operadores. Este Podemos usar isEmpty e pop para process um exemplo de parsing, e o resultado os pedaos da string - so chamados tokens. Voc remover e imprimir todos os tens da pilha: deve lembrar estas palavras do captulo 1. Python fornece um mtodo split nos mdulos string e re (expresses regulares). A funo A sada + 45 54. Em outras palavras, usamos a pilha para imprimir os tens ao contrrio! string.split separa uma string numa lista usando um Sabidamente, este no o formato padro de nico caracter como delimitador . Por exemplo: imprimir uma lista, mas, usando uma pilha, foi >>> import string notavelmente fcil de fazer. >>> string.split ("Now is the time", " ") Voc deve comparar este trecho de cdigo com a implementao de printBackward na seo 17.4. Existe um paralelo natura entre a verso recursiva de printBackward e o algoritmo de pilha aqui. A diferen que printBackward usa a pilha de execuo para XXXmanter a trilha(keep track) dos ns enquanto percorre a lista, e ento imprime-a no retorno da recurso. o algoritmo de pilha faz a mesma coisa, exceto que usa o objeto Stack ao invs da pilha de execuo.
['Now', 'is', 'the', 'time'] while not s.isEmpty() : priint s.pop()

Neste caso, o delimitador o caracter de espao, ento a string dividida a cada espao. A funo re.split mais poderosa, permitindo-nos fornecer uma expreso regular ao invs de um delimitador. Uma expresso regular uma maneira de especificar um conjunto de strings. Por exemplo, [A-z] o conjunto de todas as letras e [0-9] o conjunto de todos os dgitos. O operador ^nega um conunto, ento [^0-9] o conjunto de tudo o que no nmero, que exatamente o que queremos para dividir expresses ps-fixas.
>>> import re >>> re.split ("[^0-9]", "123+456*/") ['123', '+', '456', '*', '', '/', ' ']

18.5 Usando uma pilha para avaliar expresses ps-fixas


Em muitas linguagens de programao, expresses matemticas so executadas com o poerador entre os roid operandos, como em 1 + 2. Este formato chamado notao infixa. Uma alternativa usada por algumas calculadoras chamada notao psfixa. Em notao ps-fixa, o operador segue os operandos, como em 1 2 +. A razo pela qual a notao ps-fixa til algumas vezes que existe uma maneira natural de avaliar uma expresso ps-fixa usando uma pilha:

Note que a ordem dos argumentos diferente de string.split, o delimitador vem antes da string. A lista resultante inclui os operandos 123 e 456, e os operadores * e /. Tambm inclui duas strings vazias que so inseridas depois dos operadores.

18.7 Avaliando em ps-fixo.

comeando no incio da expresso, peque Para avaliar uma expresso ps-fixa, usaremos o um termo (operador ou operando) de cada parser da seo anterior e o algoritmo da seo vez. anterior a ela. Para manter as coisas simples, comearemos com um avaliador que implementa Se o termo um operando, empilhe-o somente os operadores + e . Se o termo um operador, desempilhe dois def evalPostfix (expr) : operandos, execute a operao neles, e import re empilhe o resultado. Quando chegar ao fim da expresso, deve existir exatamente um operando sobrando na pilha. Este operando o resultado.
tokenList = re.split ("([^0-9])", expr) stack = Stack() for token in tokenList if token == '' or token = ' ' :

Captulo 18: Pilhas #101

Como pensar como um cientista da Computao usando Python


continue if token == '+' : sum = stack.pop() + stack.pop() stack.push(sum) if token == '*' : product = stack.pop() * stack.pop() stack.push(product) else: stack.push(int(token)) return stack.pop()

(provider): escreveu) que implementa um TDA. revestimen Definio de classe que implementa to (veneer): um TDA com definies de mtodos que so chamadas a outros mtodos, s vezes com pequenas modificaes. A lmina faz um trabalho insignificante, mas melhora ou padroniza a interface dada ao cliente. estrutura Tipo de estrutura de dados que de dados contem data de um tipo genrica qualquer(tipo genrico). (generic data structure): infixa Notao matemtica em que (infix): operadores se situam entre operandos. ps-fixa Notao matemtica em que (postfix): operadores se situam aps operandos. os os os os

A primeira condio cuida de espaos e strings vazias. As duas prximas condies manipulam os operadores. Ns assumimos, agora que qualquer coisa um operador. claro, seria melhor chegar por entrada errnea e enviar uma mensagem de erro, mas faremos isto depois. Vamos test-lo avaliando a forma psfixa de (56 + 47) * 2
>>> print evalPostfix("56 47 + 2 *") 206

18.8 Clientes de fornecedores.


Um dos objetivos de um TAD separar os interesses do fornecedor, quem escreve o cdigo que implementa o TAD, e o cliente, que usa o TAD. O fornecedor tem que se preocupar apenas se a implementao est correta - de acordo com a especificao do TAD - e no como ele ser usado.

parse Ler um conjunto de caracteres(string (parse): de caracteres) ou tokens(smbolos atmicos) e analisar sua estrutura gramatical. token Conjunto de caracteres que so (token): tratados como uma unidade atmica para fins de anlise gramatical, como as palavras na linguagem natural.

Inversamente, o cliente assume que a delimitador Um caracter que utilizado para os smbolos implementao do TAD est correta e no se (delimiter): separar atmicos(tokens), como a pontuao preocupa com os detalhes. Quando voc est na linguagem natural. usando um tipo nativo do Python, tem o luxo de pensar exclusivamente como um cliente. claro, quanto voc implementa um TAD, voc tambm tem que escrever cdigo cliente para test-lo. Neste caso, voc faz os dois papis, o que pode ser confuso. Voc deve fazer algum esfor para manter a trilha do papel que est fazendo a cada momento.

18.9 Glossrio
tipo abstrato de dados (TAD) (abstract data type(ADT)): Um tipo de dado(geralmente uma coleo de objetos) que definidopor um conjunto de operaes, que podem ser implementadas de vrias maneiras.

interface o conjunto de operaes que (interface): definem um TDA. implement Cdigo que satisfaz(preenche?) os ao requisitos sintticos e semnticos de (implement uma interface. ation): cliente Um programa (ou o programador (client): que o escreveu) que faz utilizao de um TDA. fornecedor Cdigo (ou o programador que o Captulo 18: Pilhas #102

Como pensar como um cientista da Computao usando Python

Captulo 18: Pilhas #103

Como pensar como um cientista da Computao usando Python

Captulo 19: Filas

Este captulo apresenta dois TDAs: Fila e Fila por Prioridade. Na nossa vida diria, fila um alinhamento de consumidores aguardando algum tipo de servio. Na maioria dos casos, o primeiro da fila o primeiro a ser atendido. Mas h excees. No aeroporto, passageiros cujo vo vai decolar logo, s vezes so chamados primeiro ao balco do check-in, mesmo que estejam no meio da fila. No supermercado, comum na fila do caixa algum deixar passar na frente uma pessoa que chega fila s com um ou dois produtos na mo. A regra que determina quem o prximo da fila chama-se poltica de enfileiramento. A poltica de enfileiramento mais simples chama-se FIFO, sigla de first-in-first-out: primeiro a entrar, primeiro a sair. A poltica de enfileiramento mais geral o enfileiramento por prioridade, em que se atribui uma prioridade a cada pessoa da fila e a que tiver maior prioridade vai primeiro, independente da sua ordem de chegada. Dizemos que essa a poltica mais geral de todas, porque a prioridade pode ser baseada em qualquer coisa: hora de partida do vo; quantos produtos a pessoa vai passar pelo caixa; o grau de prestgio da pessoa. claro que nem todas as polticas de enfileiramento so "justas", mas o que justo depende do ponto de vista.

def isEmpty(self): return (self.length == 0) def insert(self, cargo): node = Node(cargo) node.next = None if self.head == None: # if list is empty the new node goes first self.head = node else: # find the last node in the list last = self.head while last.next: last = last.next # append the new node last.next = node self.length = self.length + 1 def remove(self): cargo = self.head.cargo self.head = self.head.next self.length = self.length - 1 return cargo

Os mtodos isEmpty e remove so idnticos aos mtodos isEmpty e removeFirst de O TDA Fila e o TDA Fila por Prioridade LinkedList. O mtodo insert novo e um pouco mais tm o mesmo conjunto de operaes. A diferena complicado. est na semntica das operaes: a fila usa a poltica Queremos inserir novos itens no fim da FIFO; e a fila por prioridade (como o prprio nome sugere) usa a poltica de enfileiramento por lista. Se a fila estiver vazia, basta fazer head apontar ao novo n. Se no, percorremos a lista at prioridade. o ltimo n e l penduramos o novo n. possvel identificar o ltimo n porque o seu atributo next None.

19.1 Um TDA Fila

O TDA Fila definido pelas seguintes operaes: __init__ Inicializar uma nova fila vazia. insert Adicionar um novo item fila. remov Remover e retornar um item da fila. O e item retornado o que foi adicionado primeiro. isEmpt Checar se a fila est vazia. y

Existem duas invariantes para um objeto Fila bem formado: o atributo length deve ser o nmero de ns na 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.3 Caractersticas de performance


Quando invocamos um mtodo, normalmente no estamos preocupados com os detalhes da sua implementao. Porm, h um certo "detalhe" que pode ser bom conhecer: as caractersticas de performance do mtodo. Quanto tempo leva, e como o tempo de execuo muda medida em que aumenta o nmero de itens da coleo?

19.2 Fila encadeada

A primeira implementao que vamos ver de um Primeiro, olhe para remove. No h TDA Fila chama-se fila encadeada porque feita de laos ou chamadas de funo aqui, o que sugere que objetos Ns encadeados. A definio da classe a o tempo de execuo desse mtodo sempre o seguinte: mesmo, toda vez. Um mtodo assim chamado de operao de tempo constante. Na verdade, o class Queue: mtodo pode ser ligeiramente mais rpido quando a def __init__(self): lista est vazia, uma vez que ele pula o corpo da self.length = 0 condicional, mas essa diferena no significativa.
self.head = None

Captulo 19: Filas #104

Como pensar como um cientista da Computao usando Python XXX: o condicional s aparece na re-implementao configurar last para None quando o ultimo n do mtodo na classe ImprovedQueue, p.200; essa removido: inconsistncia pode ser conferida tambm nas class ImprovedQueue: pginas 198-199 do livro original (PDF e impresso). A performance de insert muito diferente. No caso geral, temos de percorrer a lista para achar o ltimo elemento. Este percurso leva um tempo proporcional extenso da lista. Uma vez que o tempo de execuo uma funo linear da extenso, dizemos que este mtodo opera em tempo linear. Isso bem ruim, se comparado com o tempo constante.
#... def remove(self): cargo = self.head.cargo self.head = self.head.next self.length = self.length - 1 if self.length == 0: self.last = None return cargo

19.4 Fila encadeada aprimorada


Queremos uma implementao do TDA Fila que possa realizar todas as operaes em tempo constante. Uma maneira de fazer isso modificar a classe Fila, de modo que ela mantenha a referncia tanto ao primeiro quanto ao ltimo n, como mostra a figura:

Essa implementao mais complicada que a primeira, e mais difcil de se demonstrar que est correta. A vantagem que o objetivo foi atingido -- tanto insert quanto remove` so operaes de tempo constante. Como exerccio, escreva uma implementao do TDA Fila usando uma lista nativa do Python. Compare a performance dessa implementao com a de ImprovedQueue, para filas de diversos comprimentos.

19.5 Fila por prioridade


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. A implementao de ImprovedQueue tem essa cara:
class ImprovedQueue: def __init__(self): self.length = 0 self.head = None self.last = None

insert Adicionar um novo item fila. remove Remover e retornar um item da fila. O item retornado aquele que tiver maior prioridade.

isEmpt Checar se a fila est vazia. y A diferena semntica que o item removido da fila no necessariamente o que foi def isEmpty(self): includo primeiro e, sim, o que tem maior return (self.length == 0) prioridade. Que prioridades so essas e como elas se At agora, a nica mudana o atributo comparam umas com as outras no especificado last. Ele usado nos mtodos insert e remove: pela implementao Fila por Prioridade. Isso depende de quais itens esto na fila. class ImprovedQueue:
# ... def insert(self, cargo): node = Node(cargo) node.next = None if self.length == 0: #if list is empty, the new node is head & last self.head = self.last = node else: # find the last node last = self.last # append the new node last.next = node self.last = node self.length = self.length + 1

Por exemplo, se os itens da fila tiverem nome, podemos escolh-los por ordem alfabtica. Se for a pontuao de um jogo de boliche, podemos ir da maior para a menor, mas se for pontuao de golfe, teramos que ir da menor para a maior. Se possvel comparar os itens da fila, possvel achar e remover o que tem maior prioridade. Essa implementao da Fila por Prioridade tem como atributo uma lista Python chamada items, que contm os itens da fila.
class PriorityQueue: def __init__(self): self.items = [] def isEmpty(self): return self.items == [] def insert(self, item): self.items.append(item)

Uma vez que last no perde de vista o ultimo n, no necessrio busc-lo. Como resultado, esse mtodo tem tempo constante. adicionar Mas essa rapidez tem preo. preciso um caso especial a remove, para

O mtodo de inicializao, isEmpty, e

Captulo 19: Filas #105

Como pensar como um cientista da Computao usando Python


return "%-16s: %d" % (self.name, self.score) insert so apenas uma fachada para operaes bsicas de lista. O nico mtodo interessante O mtodo __str__ usa o operador de remove: formato para colocar nomes e pontuaes em colunas arrumadas. class PriorityQueue: # ... def remove(self): maxi = 0 for i in range(1,len(self.items)): if self.items[i] > self.items[maxi]: maxi = i item = self.items[maxi] self.items[maxi:maxi+1] = [] return item

Em seguida, definimos uma verso de __cmp__, ma qual a pontuao mais baixa fica com prioridade mxima. Como sempre, __cmp__ retorna 1 se self "maior que" other, -1 se self "menor que" other, e 0 se eles so iguais.
class Golfer: #... def __cmp__(self, other): if self.score < other.score: return 1 is more if self.score > other.score: return -1 return 0

# less

No incio de cada iterao, maxi armazena o ndice do maior item (a prioridade mais alta de todas) que vimos at agora. A cada volta do lao, o programa compara o i-simo item ao Agora estamos prontos para testar a fila campeo. Se o novo item for maior, maxi recebe o por prioridade com a classe Golfer: valor de i. Quando o comando for se completa, maxi o ndice do maior item. Esse item removido da lista e retornado. Vamos testar a implementao:
>>> >>> >>> >>> >>> >>> 14 13 12 11 q = PriorityQueue() q.insert(11) q.insert(12) q.insert(14) q.insert(13) while not q.isEmpty(): print q.remove() >>> tiger = Golfer("Tiger Woods", 61) >>> phil = Golfer("Phil Mickelson", 72) >>> hal = Golfer("Hal Sutton", 69) >>> >>> pq = PriorityQueue() >>> pq.insert(tiger) >>> pq.insert(phil) >>> pq.insert(hal) >>> while not pq.isEmpty(): print pq.remove() Tiger Woods : 61 Hal Sutton : 69 Phil Mickelson : 72

Se a fila contm nmeros ou strings simples, eles so removidas em ordem numrica decrescente ou alfabtica invertida (de Z at A). Pyhton consegue achar o maior inteiro ou string porque consegue compar-los usando os operadores de comparao nativos. Se a fila contm objetos de outro tipo, os objetos tm que prover um mtodo __cmp__. Quando remove usa o operador > para comparar dois itens, o mtodo __cmp__ de um dos itens invocado, recebendo o segundo item como argumento. Desde que o mtodo __cmp__ funcione de forma consistente, a Fila por Prioridade vai funcionar.

Como exerccio, escreva uma implementao do TDA Fila por Prioridade usando uma lista encadeada. Mantenha a lista em ordem para que a remoo seja uma operao de tempo constante. Compare a performance dessa implementao com a implementao usando uma lista nativa do Python.

19.7 Glossrio
fila (queue) Conjunto de objetos ordenados esperando algum tipo de servio. Fila (Queue) TAD (Tipo Abstrato de Dado) que realiza operaes comuns de acontecerem em uma fila. poltica de As regras que determinam qual enfileiramen membro de uma fila o prximo a to (queueing ser removido. policy) FIFO "First In, First Out," (primeiro a entrar, primeiro a sair) poltica de enfileiramento em que o primeiro membro a chegar o primeiro a ser removido. fila por prioridade (priority queue) Poltica de enfileiramento em que cada membro tem uma prioridade, determinada por fatores externos. O membro com a maior prioridade o primeiro a ser removido.

19.6 A classe Golfer


Como exemplo de um objeto com uma definio no-usual de prioridade, vamos implementar uma classe chamada Golfer (golfista), que mantm registro dos nomes e da pontuao de golfistas. Como sempre, comeamos definindo __init__ e __str__:
class Golfer: def __init__(self, name, score): self.name = name self.score= score def __str__(self):

Fila por TAD que define as operaes Prioridade comuns de acontecerem em uma Captulo 19: Filas #106

Como pensar como um cientista da Computao usando Python (Priority fila por prioridade. Queue) fila Implementao de uma fila usando encadeada uma lista encadeada. (linked queue) tempo Operao cujo tempo de execuo constante no depende do (constant estrutura de dados. time) tamanho da

tempo linear Operao cujo tempo de execuo (linear time) uma funo linear do tamanho da estrutura de dados.

Captulo 19: Filas #107

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 clula contm referncias a duas outras clulas (possivelmente nulas). Tais referncias so chamadas de subrvore esquerda e direita. Como as clulas de listas ligadas, as clulas de rvores tambm contm uma carga. Um diagrama de estados para uma rvore pode aparecer assim:

Uma rvore
a rvore vazia, representada por None, ou uma clula que contm uma referncia a um

objeto (a carga da clula) e duas referncias a rvores.

20.1 Construindo rvores


O processo de montar uma rvore similar ao processo de montar uma lista ligada. cada invocao do construtor cria uma clula.
class Tree : def __init__(self, cargo, left=None, right=None) : self.cargo = cargo self.left = left self.right = right def __str__(self) : return str(self.cargo)

A carga pode ser de qualquer tipo, mas os parmetros left e right devem ser clulas. left e right so opcionais; o valor default None. Para evitar a sobrecarga da figura, ns frequentemente omitimos os Nones. Para imprimir uma clula, imprimimos apenas a sua carga. Uma forma de construir uma rvore de baixo para cima. Aloque os filhos primeiro:

O topo da rvore (a clula qual o apontador tree se refere) chamada de raiz. left = Tree(2) Seguindo a metfora das rvores, as outras clulas right = Tree(3) so chamadas de galhos e as clulas nas pontas Em seguida crie a clula pai e ligue ela a contendo as referncias vazia so chamadas de seus filhos: folhas. Pode parecer estranho que desenhamos a figura com a raiz em cima e as folhas em baixo, mas tree = Tree(1, left, right); isto nem ser a coisa mais estranha. Podemos escrever este cdigo mais concisamente encaixando as invocaes do Para piorar as coisas, cientistas da computao misturam outra metfora alm da construtor: metfora biolgica - a rvore genealgica. Uma >>> tree = Tree(1, Tree(2), Tree(3)) clula superior pode ser chamada de pai e as De qualquer forma, o resultado a clulas a que ela se refere so chamadas de seus rvore que apareceu no incio do captulo. filhos. Clulas com o mesmo pai so chamadas de irmos. Finalmente, existe tambm o vocabulrio geomtrico para falar de rvores. J mencionamos esquerda e direita, mas existem tambm as direes "para cima" (na direo da raiz) e "para baixo" (na direo dos filhos/folhas). Ainda nesta terminologia, todas as clulas situadas mesma distncia da raiz constituem um nvel da rvore.

20.2 Percorrendo rvores

Cada vez que Voc v uma nova estrutura de dados, sua primeira pergunta deveria ser "Como eu percorro esta estrutura?" A forma mais natural de percorrer uma rvore fazer o percurso recursivamente. Por exemplo, se a rvore contm inteiros na carga, a funo abaixo retorna a soma Provavelmente no precisamos de trs das cargas: metforas para falar de rvores, mas a elas esto. Como listas ligadas, rvores so estruturas de dados recursivas j que elas so definidas recursivamente:
def total(tree) : if tree == None : return 0 return total(tree.left) + total(tree.right) +

Captulo 20: rvores #108

Como pensar como um cientista da Computao usando Python


tree.cargo

O caso base a rvore vazia, que no contm nenhuma carga, logo a soma das cargas 0. O passo recursivo faz duas chamadas recursivas Podemos percorrer uma rvore de expresso e para achar a soma das cargas das subrvores dos imprimir o seu contedo como segue: filhos. Ao finalizar a chamada recursiva, adicionamos a carga do pai e devolvemos o valor def printTree(tree) : if tree == None : return total.

20.4 Percurso de 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 saibamos que a multiplicao feita antes da adio. A rvore de expresso representa a mesma computao: seguinte

print tree.cargo, printTree(tree.left) printTree(tree.right)

Em outras palavras, para imprimir uma rvore, imprima primeiro o contedo da raiz, em seguida imprima toda a subrvore esquerda e finalmente imprima toda a subrvore direita. Esta forma de percorrer uma rvore chamada de prordem, porque o contedo da raiz aparece antes dos contedos dos filhos. Para o exemplo anterior, a sada :
>>> tree = Tree('+', Tree(1), Tree('*', Tree(2), Tree(3))) >>> printTree(tree) + 1 * 2 3

Esta notao diferente tanto da notao psfixa quanto da infixa; uma notao chamada de prefixa, em que os operadores aparecem antes dos seus operandos. Voc pode suspeitar que se Voc percorre a rvore numa ordem diferente, Voc produzir expresses numa notao diferente. Por exemplo, se Voc imprime subrvores primeiro e depois a raiz, Voc ter:
def printTreePostorder(tree) : if tree == None : return printTreePostorder(tree.left) printTreePostorder(tree.right) print tree.cargo,

As clulas de uma rvore de expresso Finalmente, para percorrer uma rvore podem ser operandos como 1 e 2 ou operaes como + e *. As clulas contendo operandos so folhas; em inordem, Voc imprime a subrvore esquerda, aquelas contendo operaes devem ter referncias depois a raiz e depois a subrvore direita: aos seus operandos. (Todos os nossos operandos so def printTreeInorder(tree) : binrios, significando que eles tem exatamente dois if tree == None : return operandos.) Podemos construir rvores assim:
>>> tree = Tree('+', Tree(1), Tree('*', Tree(2), Tree(3))) printTreeInorder(tree.left) print tree.cargo, printTreeInorder(tree.right)

O resultado, 1 2 3 * +, est na notao psfixa! Esta ordem de percurso chamada de psordem.

O resultado 1 + 2 * 3, que a expresso Examinando a figura, no h dvida na notao infixa. quanto ordem das operaes; a multiplicao Para sermos justos, devemos lembrar feita primeiro para calcular o segundo operando da que acabamos de omitir uma complicao adio. importante. algumas vezes quando escrevemos rvores de expresso tem muitos usos. expresses na notao infixa devemos usar O exemplo neste captulo usa rvores para traduzir parntesis para prescrever a ordem das operaes. expresses para as notaes psfixa, prefixa e Ou seja, um percurso em inordem no suficiente infixa. rvores similares so usadas em para gerar a expresso infixa. compiladores para analisar sintaticamente, Ainda assim, com alguns otimizar e traduzir programas. aperfeioamentos, a rvore de expresso e os trs modos recursivos de percurso resultam em algoritmos para transformar expresses de uma notao para outra. Como um exerccio, modifique `printTreeInorder` de modo que ele coloque Captulo 20: rvores #109

Como pensar como um cientista da Computao usando Python parntesis em volta de cada operador e par de operandos. A sada correta e no ambgua? Os parntesis so sempre necessrios? Se percorrermos uma rvore em inordem e acompanharmos em qual nvel na rvore estamos, podemos gerar uma representao grfica da rvore:
def printTreeIndented(tree, level=0) : if tree == None : return printTreeIndented(tree.right, level+1) print ' '*level + str(tree.cargo) printTreeIndented(tree.left, level+1)

funo que recebe uma expresso na forma de uma cadeia e devolve a lista de tokens. A primeira funo que escreveremos getToken que recebe como parmetros uma lista de tokens e um token esperado. Ela compara o token esperado com o o primeiro token da lista: se eles batem a funo remove o token da lista e devolve um valor verdadeiro, caso contrrio a funo devolve um valor falso:
def getToken(tokenList, expected) : if tokenList[0] == expected : tokenList[0:1] = [] # remove the token return 1 else : return 0

O parmetro level registra aonde estamos na rvore. Por 'default', o nvel inicialmente zero. A cada chamada recursiva repassamos level+1 porque o nvel do filho sempre um a mais J que tokenList refere a um objeto do que o nvel do pai. Cada item indentado dois mutvel, as alteraes feitas aqui so visveis para espaos por nvel. Para o nosso exemplo obtemos: qualquer outra varivel que se refira ao mesmo objeto. >>> printTreeIndented(tree)
3 * 2 + 1

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)

Se Voc deitar a sada acima Voc enxerga uma verso simplificada da figura original.

20.5 Construindo uma rvore de expresso

Antes de continuar, convm testar getNumber Atribumos uma lista de Nesta seo analisamos expresses infixas e nmeros aisoladamente. tokenList, extramos o primeiro, construmos as rvores de express o resultado e imprimimos o que resta correspondentes. Por exemplo, para a expresso imprimimos na lista de tokens: (3+7)*9 resultar a seguinte rvore:
>>> tokenList = [9, 11, 'end'] >>> x = getNumber(tokenList) >>> printTreePostorder(x) 9 >>> print tokenList [11, 'end']

Em seguida precisaremos da funo getProduct, que constri uma rvore de expresso para produtos. Os dois operandos de um produto simples so nmeros, como em 3 * 7. Segue uma verso de getProduct que trata de produtos simples.
def getProduct(tokenList) : a = getNumber(tokenList) if getToken(tokenList, '*') : b = getNumber(tokenList) return Tree('*', a, b) else : return a

Note que simplificamos o diagrama omitindo os nomes dos campos.

O analisador que escreveremos aceitar expresses que incluam nmeros, parntesis e as Supondo que a chamada de getNumber operaes + e *. Vamos supor que a cadeia de seja bem sucedida e devolva uma rvore de uma s entrada j foi tokenizada numa lista do Python. A clula atribumos o primeiro operando a `. Se o lista de tokens para a expresso (3+7)*9 : prximo caractere for *, vamos buscar o segundo nmero e construir a rvore com a, b e o operador. Se o caractere seguinte for qualquer O token final end prtico para prevenir que o analisador tente buscar mais dados outra coisa, ento simplesmente devolvemos uma clula folha com a. Seguem dois exemplos: aps o trmino da lista. A ttulo de um exerccio, escreva uma
>>> tokenList = [9, '*', 11, 'end'] ['(', 3, '+', 7, ')', '*', 9, 'end']

Captulo 20: rvores #110

Como pensar como um cientista da Computao usando Python


>>> tree = getProduct(tokenList) >>> printTreePostorder(tree) 9 11 *

definio, ela tem uma propriedade interessante: podemos representar qualquer expresso (sem parntesis) como uma soma de produtos. Esta propriedade a base do nosso algoritmo de anlise sinttica. getSum tenta construir a rvore com um produto esquerda e uma soma direita. Mas, se ele no encontra uma +, ele simplesmente constri um produto.
def getSum(tokenList) : a = getProduct(tokenList) if getToken(tokenList, '+') : b = getSum(tokenList) return Tree('+', a, b) else : return a

>>> tokenList = [9, '+', 11, 'end'] >>> tree = getProduct(tokenList) >>> printTreePostorder(tree) 9

O segundo exemplo sugere que ns consideramos um operando unitrio como uma espcie de produto. Esta definio de "produto" talvez no seja intuitiva, mas ela ser til. Agora tratamos produtos compostos, como 3 * 5 * 13. Encaramos esta expresso como um produto de produtos, mais precisamente como 3 * (5 * 13). A rvore resultante :

* 7:

Vamos testar o algoritmo com 9 * 11 + 5

>>> tokenList = [9, '*', 11, '+', 5, '*', 7, 'end'] >>> tree = getSum(tokenList) >>> printTreePostorder(tree) 9 11 * 5 7 * +

Quase terminamos, mas ainda temos que tratar dos parntesis. Em qualquer lugar numa expresso onde podemos ter um nmero, podemos tambm ter uma soma inteira envolvida entre parntesis. Precisamos, apenas, modificar getNumber para que ela possa tratar de subexpresses:
def getNumber(tokenList) : if getToken(tokenList, '(') : x = getSum(tokenList) # get subexpression getToken(tokenList, ')') #eat closing parenthesis return x else : x = tokenList[0] if type(x) != type(0) : return None tokenList[0:1] = [] # remove the token return Tree(x, None, None) # return a leaf with the number

Com uma pequena alterao em getProduct, podemos acomodar produtos arbitrariamente longos:
def getProduct(tokenList) : a = getNumber(tokenList) if getToken(tokenList, '*') : b = getProduct(tokenList) changed return Tree('*', a, b) else : return a

# this line

Testemos este cdigo com 9 * (11 + 5) * 7:


>>> tokenList = [9, '*', '(', 11, '+', 5, ')', '*', 7, 'end'] >>> tree = getSum(tokenList) >>> printTreePostorder(tree) 9 11 5 + 7 * *

Em outras palavras, um produto pode ser um singleton ou uma rvore com * na raiz, que tem um nmero como filho esquerdo e um produto como filho direito. Este tipo de definio recursiva devia comear a ficar familiar. Testemos produto composto:
>>> >>> >>> 2 3

nova

verso

com

O analisador tratou os corretamente; a adio feita um multiplicao.

parntesis antes da

tokenList = [2, '*', 3, '*', 5 , '*', 7, 'end'] tree = getProduct(tokenList) printTreePostorder(tree) 5 7 * * *

Na verso final do programa, seria uma boa idia dar a getNumber um nome mais descritivo do seu novo papel.

A seguir adicionamos o tratamento de somas. De novo, usamos uma definio de "soma" que ligeiramente no intuitiva. Para ns, uma soma pode ser uma rvore com + na raiz, que tem um produto como filho esquerdo e uma soma como filho direito. Ou, uma soma pode ser simplesmente um produto.

20.6 Manipulando erros

Ao longo do analisador sinttico tnhamos suposto que as expresses (de entrada) so bem formadas. Por exemplo, quando atingimos o fim de uma subexpresso, supomos que o prximo caractere um facha parntesis. Caso haja um erro e o prximo Se Voc est disposto a brincar com esta caractere seja algo diferente, devemos tratar disto. Captulo 20: rvores #111

Como pensar como um cientista da Computao usando Python


def getNumber(tokenList) : if getToken(tokenList, '(') : x = getSum(tokenList) if not getToken(tokenList, ')'): raise 'BadExpressionError', 'missing parenthesis' return x else : # the rest of the function omitted

O comando raise cria uma exceo; neste caso criamos um novo tipo de exceo, chamada de BadExpressionError. Se a funo que chamou getNumber, ou uma das outras funes no No comeo de cada rodada, o programa traceback, manipular a exceo, ento o programa pode continuar. caso contrrio Python vai imprimir parte do topo da rvore e faz a primeira pergunta. uma mensagem de erro e terminar o Dependendo da resposta, ele segue pelo filho esquerdo ou direito e continua at chegar numa processamento em seguida. folha. Neste ponto ele arrisca um palpite. Se o A ttulo de exerccio, encontre outros palpite no for correto, ele pergunta ao usurio o locais nas funes criadas onde erros possam nome de um novo animal e uma pergunta que ocorrer e adiciona comandos ``raise`` distingue o palpite errado do novo animal. A seguir, apropriados. Teste seu cdigo com expresses mal adiciona uma clula rvore contendo a nova formadas. pergunta e o novo animal. Aqui est o cdigo:

20.7 A rvore dos animais


Nesta seo, desenvolvemos um pequeno programa que usa uma rvore para representar uma base de conhecimento. O programa interage com o usurio para criar uma rvore de perguntas e de nomes de animais. Segue uma amostra da funcionalidade:
Are you thinking of an animal? y Is it a bird? n What is the animals name? dog What question would distinguish a dog from a bird? Can it fly If the animal were dog the answer would be? n Are you thinking of an animal? y Can it fly? n Is it a dog? n What is the animals name? cat What question would distinguish a cat from a dog? Does it bark If the animal were cat the answer would be? n Are you thinking of an animal? y Can it fly? n Does it bark? y Is it a dog? y I rule! Are you thinking of an animal? n

def animal() : # start with a singleton root = Tree("bird") # loop until the user quits while 1 : print if not yes("Are you thinking of an animal? ") : break # walk the tree tree = root while tree.getLeft() != None : prompt = tree.getCargo() + "? " if yes(prompt): tree = tree.getRight() else: tree = tree.getLeft() # make a guess guess = tree.getCargo() prompt = "Is it a " + guess + "? " if yes(prompt) : print "I rule!" continue # get new information prompt = "What is the animal\'s name? " animal = raw_input(prompt) prompt = "What question would distinguish a %s from a %s? " question = raw_input(prompt % (animal,guess)) # add new information to the tree tree.setCargo(question) prompt = "If the animal were %s the answer would be? " if yes(prompt % animal) : tree.setLeft(Tree(guess))

constri:

Aqui est a rvore que este dilogo

Captulo 20: rvores #112

Como pensar como um cientista da Computao usando Python


tree.setRight(Tree(animal)) else : tree.setLeft(Tree(animal)) tree.setRight(Tree(guess))

(nica) clula de uma rvore que no tem pai. folha (leaf) Uma clula mais baixa numa rvore; uma clula que no tem descendentes. pai (parent) A clula que aponta para uma clula dada. filho (child) Uma clula apontada por uma clula dada. irmos Clulas que tem o mesmo pai. (siebling) conjunto de nvel (level) Um equidistantes da raiz. clulas

A funo yes um auxiliar; ele imprime um prompt e em seguida solicita do usurio uma entrada. Se a resposta comear com y ou Y, a funo devolve um valor verdadeiro:
def yes(ques) : from string import lower ans = lower(raw_input(ques)) return (ans[0:1] == 'y')

A condio do lao externo 1`, que significa que ele continuar at a execuo de um comando break, caso o usurio no pense num animal. O lao while interno caminha na rvore de cima para baixo, guiado pelas respostas do usurio. Quando uma nova clula adicionada rvore, a nova pergunta substitui a carga e os dois filhos so o novo animal e a carga original. Uma falha do programa que ao sair ele esquece tudo que lhe foi cuidadosamente ensinado! A ttulo de exerccio, pense de vrias jeitos para salvar a rvore do conhecimento acumulado num arquivo. Implemente aquele que Voc pensa ser o mais fcil.

operador Um operador sobre dois operandos. binrio (binary operator) subexpress Uma expresso entre parntesis que o se comporta como um operando (subexpress simples numa expresso maior. ion) pr-ordem Uma forma de percorrer uma rvore (preorder) visitando cada clula antes dos seus filhos. notao prefixa (prefix notation) Uma forma de escrever uma expresso matemtica em que cada operador aparece antes dos seus operandos.

20.8 Glossrio
rvore Uma rvore em que cada clula tem binria zero, um ou dois descendentes. (binary tree) raiz (root) A clula mais alta de uma rvore, a

ps-ordem Uma forma de percorrer uma rvore (postorder) visitando os filhos de cada clula antes da prpria clula. in-ordem Uma forma de percorrer uma rvore (inorder) visitando a subrvore esquerda, seguida da raiz e finalmente da subrvore direita.

Captulo 20: rvores #113

Como pensar como um cientista da Computao usando Python

GNU Free Documentation License

Version 1.2, November 2002


Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 021101301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.

appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them. The "Invariant Sections" are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none.

0. PREAMBLE

The purpose of this License is to make a manual, textbook, or other functional and useful document "free" in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get The "Cover Texts" are certain short credit for their work, while not being considered passages of text that are listed, as Front-Cover Texts responsible for modifications made by others. or Back-Cover Texts, in the notice that says that the This License is a kind of "copyleft", Document is released under this License. A Frontwhich means that derivative works of the document Cover Text may be at most 5 words, and a Backmust themselves be free in the same sense. It Cover Text may be at most 25 words. complements the GNU General Public License, A "Transparent" copy of the Document which is a copyleft license designed for free means a machine-readable copy, represented in a software. format whose specification is available to the We have designed this License in order general public, that is suitable for revising the to use it for manuals for free software, because free document straightforwardly with generic text software needs free documentation: a free program editors or (for images composed of pixels) generic should come with manuals providing the same paint programs or (for drawings) some widely freedoms that the software does. But this License is available drawing editor, and that is suitable for not limited to software manuals; it can be used for input to text formatters or for automatic translation any textual work, regardless of subject matter or to a variety of formats suitable for input to text whether it is published as a printed book. We formatters. A copy made in an otherwise recommend this License principally for works Transparent file format whose markup, or absence whose purpose is instruction or reference. of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount of 1. APPLICABILITY AND DEFINITIONS text. A copy that is not "Transparent" is called "Opaque". This License applies to any manual or other work, Examples of suitable formats for in any medium, that contains a notice placed by the copyright holder saying it can be distributed under Transparent copies include plain ASCII without the terms of this License. Such a notice grants a markup, Texinfo input format, LaTeX input format, world-wide, royalty-free license, unlimited in SGML or XML using a publicly available DTD, and duration, to use that work under the conditions standard-conforming simple HTML, PostScript or stated herein. The "Document", below, refers to any PDF designed for human modification. Examples of such manual or work. Any member of the public is transparent image formats include PNG, XCF and a licensee, and is addressed as "you". You accept the JPG. Opaque formats include proprietary formats license if you copy, modify or distribute the work in that can be read and edited only by proprietary word processors, SGML or XML for which the DTD a way requiring permission under copyright law. and/or processing tools are not generally available, A "Modified Version" of the Document and the machine-generated HTML, PostScript or means any work containing the Document or a PDF produced by some word processors for output portion of it, either copied verbatim, or with purposes only. modifications and/or translated into another The "Title Page" means, for a printed language. book, the title page itself, plus such following pages A "Secondary Section" is a named as are needed to hold, legibly, the material this GNU Free Documentation License #114

Como pensar como um cientista da Computao usando Python License requires to appear in the title page. For pages. works in formats which do not have any title page If you publish or distribute Opaque as such, "Title Page" means the text near the most prominent appearance of the work's title, preceding copies of the Document numbering more than 100, you must either include a machine-readable the beginning of the body of the text. Transparent copy along with each Opaque copy, or A section "Entitled XYZ" means a named state in or with each Opaque copy a computersubunit of the Document whose title either is network location from which the general networkprecisely XYZ or contains XYZ in parentheses using public has access to download using publicfollowing text that translates XYZ in another standard network protocols a complete Transparent language. (Here XYZ stands for a specific section copy of the Document, free of added material. If you name mentioned below, such as use the latter option, you must take reasonably "Acknowledgements", "Dedications", prudent steps, when you begin distribution of "Endorsements", or "History".) To "Preserve the Opaque copies in quantity, to ensure that this Title" of such a section when you modify the Transparent copy will remain thus accessible at the Document means that it remains a section "Entitled stated location until at least one year after the last XYZ" according to this definition. time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to The Document may include Warranty the public. Disclaimers next to the notice which states that this License applies to the Document. These Warranty It is requested, but not required, that Disclaimers are considered to be included by you contact the authors of the Document well reference in this License, but only as regards before redistributing any large number of copies, to disclaiming warranties: any other implication that give them a chance to provide you with an updated these Warranty Disclaimers may have is void and version of the Document. has no effect on the meaning of this License.

2. VERBATIM COPYING
You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3. You may also lend copies, under the same conditions stated above, and you may publicly display copies.

4. MODIFICATIONS
You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version:

3. COPYING IN QUANTITY
If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects. If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent

A. Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission. B. List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has fewer than five), unless they release you from this requirement. C. State on the Title page the name of the publisher of the Modified Version, as the publisher. D. Preserve all the copyright notices of the Document. E. Add an appropriate copyright notice for your modifications adjacent to the other copyright notices. F. Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below. G. Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document's license notice.

GNU Free Documentation License #115

Como pensar como um cientista da Computao usando Python


H. Include an unaltered copy of this License. I. Preserve the section Entitled "History", Preserve its Title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section Entitled "History" in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence. J. Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the "History" section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission. K. For any section Entitled "Acknowledgements" or "Dedications", Preserve the Title of the section, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein. L. Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles. M. Delete any section Entitled "Endorsements". Such a section may not be included in the Modified Version. N. Do not retitle any existing section to be Entitled "Endorsements" or to conflict in title with any Invariant Section. O. Preserve any Warranty Disclaimers.

The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version.

5. COMBINING DOCUMENTS
You may combine the Document with other documents released under this License, under the terms defined in section 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 you preserve all their Warranty Disclaimers. The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work. In the combination, you must combine any sections Entitled "History" in the various original documents, forming one section Entitled "History"; likewise combine any sections Entitled "Acknowledgements", and any sections Entitled "Dedications". You must delete all sections Entitled "Endorsements."

6. COLLECTIONS OF DOCUMENTS
You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects.

If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version's license notice. These titles must be distinct from any other section titles.

You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of You may add a section Entitled this License into the extracted document, and follow "Endorsements", provided it contains nothing but this License in all other respects regarding verbatim endorsements of your Modified Version by various copying of that document. parties--for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard. 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-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one.

7. AGGREGATION WITH INDEPENDENT WORKS

A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, is called an "aggregate" if the copyright resulting from the compilation is not used to limit the legal rights of the compilation's users beyond what the individual works permit. When the Document is included in an aggregate, this License does not apply to the other works in the aggregate

GNU Free Documentation License #116

Como pensar como um cientista da Computao usando Python which are not themselves derivative works of the not specify a version number of this License, you Document. may choose any version ever published (not as a draft) by the Free Software Foundation. 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 How to use this License for your documents aggregate, the Document's Cover Texts may be To use this License in a document you placed on covers that bracket the Document within have written, include a copy of the License in the the aggregate, or the electronic equivalent of covers if the Document is in electronic form. Otherwise document and put the following copyright and they must appear on printed covers that bracket the license notices just after the title page: whole aggregate. Copyright (c) YEAR YOUR NAME.

8. TRANSLATION

Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License, and all the license notices in the If you have Invariant Sections, FrontDocument, and any Warranty Disclaimers, provided that you also include the original English version of Cover Texts and Back-Cover Texts, replace the this License and the original versions of those "with...Texts." line with this: notices and disclaimers. In case of a disagreement with the Invariant Sections being LIST THEIR between the translation and the original version of TITLES, with the this License or a notice or disclaimer, the original Front-Cover Texts being LIST, and with the Backversion will prevail. If a section in the Document is Entitled "Acknowledgements", "Dedications", or "History", If you have Invariant Sections without the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual Cover Texts, or some other combination of the three, merge those two alternatives to suit the title. 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 You may not copy, modify, sublicense, or distribute General Public License, to permit their use in free the Document except as expressly provided for software. under this License. Any other attempt to copy, modify, sublicense or distribute the Document is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
Cover Texts being LIST.

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".

9. TERMINATION

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 GNU Free Documentation License #117

Como pensar como um cientista da Computao usando Python

GNU Free Documentation License #118

You might also like