├── .gitignore
├── CONTRIBUIR.md
├── ERRATA.md
├── LICENSE.md
├── README.md
├── docs
├── 00-prefacio.md
├── 01-jornada.md
├── 02-vars-expr-instr.md
├── 03-funcoes.md
├── 04-caso-interface.md
├── 05-cond-recur.md
├── 06-funcoes-result.md
├── 07-iteracao.md
├── 08-strings.md
├── 09-caso-palavras.md
├── 10-listas.md
├── 11-dicionarios.md
├── 12-tuplas.md
├── 13-caso-estruturas.md
├── 14-arquivos.md
├── 15-classes-objetos.md
├── 16-classes-funcoes.md
├── 17-classes-metodos.md
├── 18-heranca.md
├── 19-extra.md
├── A-depuracao.md
├── B-analise-algorit.md
├── C-colofao-autor.md
├── _config.yml
└── index.md
├── ebooks
├── PenseEmPython2e.epub
└── metadata.xml
├── fig
├── p19f1.png
├── p242f1.png
├── p63f1.png
├── p72f1.png
├── p79f1.png
├── p79f2.png
├── p80f1.png
├── p83f1.png
├── tnkp_0201.png
├── tnkp_0301.png
├── tnkp_0401.png
├── tnkp_0402.png
├── tnkp_0501.png
├── tnkp_0502.png
├── tnkp_0601.png
├── tnkp_0701.png
├── tnkp_0801.png
├── tnkp_0802.png
├── tnkp_1001.png
├── tnkp_1002.png
├── tnkp_1003.png
├── tnkp_1004.png
├── tnkp_1005.png
├── tnkp_1101.png
├── tnkp_1102.png
├── tnkp_1201.png
├── tnkp_1202.png
├── tnkp_1501.png
├── tnkp_1502.png
├── tnkp_1503.png
├── tnkp_1601.png
├── tnkp_1801.png
├── tnkp_1802.png
└── tnkp_2101.png
├── img
├── Capa_PenseEmPython167x232.png
├── Capa_PenseEmPython332x461-borda.png
└── Capa_PenseEmPython667x927.png
├── recebido
├── PenseEmPython.md
├── PenseEmPython.xml
├── capitulos.ods
├── capitulos.txt
├── capitulos
│ ├── 00-prefacio.md
│ ├── 01-jornada.md
│ ├── 02-vars-expr-instr.md
│ ├── 03-funcoes.md
│ ├── 04-caso-interface.md
│ ├── 05-cond-recur.md
│ ├── 06-funcoes-result.md
│ ├── 07-iteracao.md
│ ├── 08-strings.md
│ ├── 09-caso-palavras.md
│ ├── 10-listas.md
│ ├── 11-dicionarios.md
│ ├── 12-tuplas.md
│ ├── 13-caso-estruturas.md
│ ├── 14-arquivos.md
│ ├── 15-classes-objetos.md
│ ├── 16-classes-funcoes.md
│ ├── 17-classes-metodos.md
│ ├── 18-heranca.md
│ ├── 19-extra.md
│ ├── A-depuracao.md
│ └── B-analise-algorit.md
├── figuras
│ ├── p19f1.pdf
│ ├── p242f1.pdf
│ ├── p63f1.pdf
│ ├── p72f1.pdf
│ ├── p79f1.pdf
│ ├── p79f2.pdf
│ ├── p80f1.pdf
│ ├── p83f1.pdf
│ ├── tnkp_0201.ai
│ ├── tnkp_0301.ai
│ ├── tnkp_0401.ai
│ ├── tnkp_0402.ai
│ ├── tnkp_0501.ai
│ ├── tnkp_0502.ai
│ ├── tnkp_0601.ai
│ ├── tnkp_0701.ai
│ ├── tnkp_0801.ai
│ ├── tnkp_0802.ai
│ ├── tnkp_1001.ai
│ ├── tnkp_1002.ai
│ ├── tnkp_1003.ai
│ ├── tnkp_1004.ai
│ ├── tnkp_1005.ai
│ ├── tnkp_1101.ai
│ ├── tnkp_1102.ai
│ ├── tnkp_1201.ai
│ ├── tnkp_1202.ai
│ ├── tnkp_1501.ai
│ ├── tnkp_1502.ai
│ ├── tnkp_1503.ai
│ ├── tnkp_1601.ai
│ ├── tnkp_1801.ai
│ ├── tnkp_1802.ai
│ └── tnkp_2101.ai
├── sumario.md
└── thinkpython2.pdf
└── util
├── epub.py
├── gloss_e_exerc.py
├── glossario_dl.py
├── marcar_listagens.py
├── marcar_secoes.py
└── separar_capitulos.py
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | env/
12 | build/
13 | develop-eggs/
14 | dist/
15 | downloads/
16 | eggs/
17 | .eggs/
18 | lib/
19 | lib64/
20 | parts/
21 | sdist/
22 | var/
23 | *.egg-info/
24 | .installed.cfg
25 | *.egg
26 |
27 | # PyInstaller
28 | # Usually these files are written by a python script from a template
29 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
30 | *.manifest
31 | *.spec
32 |
33 | # Installer logs
34 | pip-log.txt
35 | pip-delete-this-directory.txt
36 |
37 | # Unit test / coverage reports
38 | htmlcov/
39 | .tox/
40 | .coverage
41 | .coverage.*
42 | .cache
43 | nosetests.xml
44 | coverage.xml
45 | *,cover
46 | .hypothesis/
47 |
48 | # Translations
49 | *.mo
50 | *.pot
51 |
52 | # Django stuff:
53 | *.log
54 | local_settings.py
55 |
56 | # Flask stuff:
57 | instance/
58 | .webassets-cache
59 |
60 | # Scrapy stuff:
61 | .scrapy
62 |
63 | # Sphinx documentation
64 | docs/_build/
65 |
66 | # PyBuilder
67 | target/
68 |
69 | # IPython Notebook
70 | .ipynb_checkpoints
71 |
72 | # pyenv
73 | .python-version
74 |
75 | # celery beat schedule file
76 | celerybeat-schedule
77 |
78 | # dotenv
79 | .env
80 |
81 | # virtualenv
82 | venv/
83 | ENV/
84 |
85 | # Spyder project settings
86 | .spyderproject
87 |
88 | # Rope project settings
89 | .ropeproject
90 |
91 | tmp/
92 |
--------------------------------------------------------------------------------
/CONTRIBUIR.md:
--------------------------------------------------------------------------------
1 | # Como contribuir
2 |
3 | ## Procedimento
4 |
5 | Para contribuir:
6 |
7 | 1. Use o GitHub para fazer um fork do [repositório principal](https://github.com/PenseAllen/PensePython2e.git).
8 |
9 | 2. Clone o seu fork em sua máquina local.
10 |
11 | 3. Faça `commit` explicando claramente o motivo de cada alteração.
12 |
13 | 4. Faça `push` de suas alterações para o seu fork.
14 |
15 | 5. Use o GitHub para submeter um _pull request_ do seu fork para o repositório principal, incluindo uma descrição clara das alterações propostas.
16 |
17 |
18 | ## Critérios editoriais
19 |
20 | ### Marcação de palavras no texto corrido
21 |
22 | Nomes de variáveis, funções e módulos que aparecem nos exemplos antes e depois de um parágrafo devem ser marcadas como código, usando crases, assim: `x`, `factorial`, `os.path`.
23 |
24 | Os nomes dos tipos mais comuns, como string, float e bytes, exigem uma decisão. Por exemplo, quando o assunto é cadeia de caracteres qualquer, use string sem adorno, mas quando se está falando especificamente do tipo `string`, em uma discussão sobre tipos, use marcação de código: `string`. O motivo desse critério é evitar poluir demais o texto com marcações de código quando se trata genericamente desses conceitos.
25 |
--------------------------------------------------------------------------------
/ERRATA.md:
--------------------------------------------------------------------------------
1 | # Erros encontrados na tradução
2 |
3 | ## Prefácio
4 |
5 | Ante-penúltimo ponto: em vez de "Muito, muito obrigada" deveria ser "Muito, muito obrigado"
6 |
7 | ### Exemplos de uso de código (de acordo com a política da O'Reilly)
8 |
9 | O título desta sessão em inglês é "Using Code Examples". Em português, "Uso do código dos exemplos" seria uma tradução mais fiel. O texto entre parênteses não aparece no PDF da O'Reilly (p. xiii do PDF original).
10 |
11 | ## Capítulo 3
12 |
13 | ### 3.9 - Diagrama da pilha
14 |
15 | Parágrafo 3, "`__main__`, que é um nome especial para o frame na posição mais proeminente"; no original, trata-se do "topmost frame". Seria melhor traduzir como "o frame no topo da pilha" (veja figura 3.1)
16 |
17 |
18 | ## Capítulo 5
19 |
20 | ### Exercício 5.2
21 |
22 | "há nenhum número inteiro positivo a, b e c tal que" deveria ser "não existem números inteiros a, b e c tais que"
23 |
24 | ## Capítulo 6
25 |
26 | ### 6.5 - Mais recursividade
27 |
28 | Parágrafo 2: "é conhecido como o Teste de Turing. Para uma exposição mais completa (e exata) do Teste de Turing": o autor está explicando a Tese de Turing, portanto o correto é: "é conhecida como a Tese de Turing. Para uma exposição mais completa (e exata) da Tese de Turing"
29 |
30 | ## Capítulo 7
31 |
32 | ### 7.5 - Raízes quadradas
33 |
34 | Antepenúltimo parágrafo: "números mais racionais, como 1/3" está errado, o correto é "a maioria dos números racionais, como 1/3"
35 |
36 | ## Capítulo 12
37 |
38 | ### 12.5 - Listas e tuplas
39 |
40 | Parágrafo 5: "Se quiser usar operadores de lista e métodos", deveria ser "Se quiser usar operadores e métodos de lista"
41 |
42 |
43 | ## Capítulo 14
44 |
45 |
46 | ## 14.5 - Captura de exceções
47 |
48 | Parágrafo 3: "E se tentar abrir um diretório de leitura", deveria ser "E se tentar abrir um diretório para leitura"
49 |
50 |
51 | ## 14.7 - Usando o Pickle
52 |
53 | Parágrafos 3 e 4: as seguintes explicações entre parêntesis estão equivocadas e devem ser removidas:
54 |
55 | (dumps é a abreviação de “string de depósito” em inglês)
56 | (“string de carregamento” em inglês)
57 |
58 | ## 14.9 - Módulos de escrita
59 |
60 | O título desta seção no original é "Writing modules"; no contexto, a tradução correta é "Escrevendo módulos".
61 |
62 |
63 | ## Capítulo 15
64 |
65 | ### 15.1 - Tipos definidos pelos programadores
66 |
67 | Parágrafo 2, "(x, y) representa o ponto que está x unidades à direita e y unidades a partir da origem." deveria ser "(x, y) representa o ponto que está x unidades à direita e y unidades acima da origem."
68 |
69 | ## Capítulo 18
70 |
71 | ### 18.11 - Glossário
72 |
73 | A definição do termo __multiplicidade__ está confusa. Em vez de "quantas referências dela são instâncias de outra classe." é melhor "quantas referências a instâncias da outra classe podem existir."
74 |
75 | ## Capítulo 19
76 |
77 | ### 19.3 - Expressões geradoras
78 |
79 | Parágrafo 4, a exceção mencionada está como "StopException", mas o correto é "StopIteration".
80 |
81 | Nota: este erro existe também no original e eu (@ramalho) já o reportei no site da O'Reilly.
82 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # Licença
2 |
3 | Copyright © 2015 Allen Downey.
4 |
5 | ## CC BY-NC 3.0
6 |
7 | Este trabalho é oferecido sob a licença __Creative Commons Atribuição-NãoComercial 3.0 Não Adaptada__.
8 |
9 | O texto a seguir é um resumo e não substitui a licença completa em [legalês inglês](https://creativecommons.org/licenses/by-nc/3.0/legalcode).
10 |
11 |
12 | ## Você tem o direito de:
13 |
14 | __Compartilhar__ — copiar e redistribuir o material em qualquer suporte ou formato
15 |
16 | __Adaptar__ — remixar, transformar, e criar a partir do material
17 |
18 | O licenciante não pode revogar estes direitos desde que você respeite os termos da licença.
19 |
20 |
21 | ## De acordo com os termos seguintes:
22 |
23 | __Atribuição__ — Você deve dar o __crédito apropriado__, prover um link para a licença e __indicar se mudanças foram feitas__. Você deve fazê-lo em qualquer circunstância razoável, mas de maneira alguma que sugira ao licenciante a apoiar você ou o seu uso.
24 |
25 | __NãoComercial__ — Você não pode usar o material para __fins comerciais__.
26 |
27 | __Sem restrições adicionais__ — Você não pode aplicar termos jurídicos ou __medidas de caráter tecnológico__ que restrinjam legalmente outros de fazerem algo que a licença permita.
28 |
29 | ## Avisos:
30 |
31 | Você não tem de cumprir com os termos da licença relativamente a elementos do material que estejam no domínio público ou cuja utilização seja permitida por uma __exceção ou limitação__ que seja aplicável.
32 |
33 | Não são dadas quaisquer garantias. A licença pode não lhe dar todas as autorizações necessárias para o uso pretendido. Por exemplo, outros direitos, tais como __direitos de imagem, de privacidade ou direitos morais__, podem limitar o uso do material.
34 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Pense em Python
2 |
3 |
4 |
5 | Tradução do livro [Think Python](http://greenteapress.com/wp/think-python-2e/) (2ª edição), de Allen B. Downey, publicado sob licença [CC BY-NC 3.0](LICENSE.md).
6 |
7 | Este livro ensina programação para quem nunca programou, usando Python 3 nos exemplos. É aplicado no Olin College, IBMEC e outras faculdades de engenharia excelentes.
8 |
9 | > __DICA__: Você pode comprar um exemplar impresso de [__Pense em Python__](https://novatec.com.br/livros/pense-em-python/) no site da [Editora Novatec](https://novatec.com.br/livros/pense-em-python/) ou em livrarias. [ISBN: 978-85-7522-508-0](https://novatec.com.br/livros/pense-em-python/).
10 |
11 | [Versão navegável em HTML](https://PenseAllen.github.io/PensePython2e/)
12 |
13 |
14 | ## Créditos da edição brasileira
15 |
16 | Editor: Rubens Prates
17 | Tradução: Sheila Gomes
18 | Revisão Gramatical: Smirna Cavalheiro
19 | Editoração Eletrônica: Carolina Kuwabata
20 | Assistente Editorial: Priscila A. Yoshimatsu
21 |
22 |
23 | ## Proveniência
24 |
25 | Agradecemos a Rubens Prates da Editora Novatec por ter cedido gentilmente os arquivos com o texto integral e as figuras de [Pense em Python](https://novatec.com.br/livros/pense-em-python/), publicado sob licença da O'Reilly Media.
26 |
27 | O arquivo [`recebido/PenseEmPython.xml`](recebido/PenseEmPython.xml) em formato DocBook foi gerado a partir do arquivo InDesign criado pela Editora Novatec. Na conversão para DocBook foram usados os programas InDesign, Word e LibreOffice.
28 |
29 | O DocBook `PenseEmPython.xml` foi convertido para _markdown_ com a ferramenta Pandoc versão 1.19.2.1 usando a seguinte linha de comando:
30 |
31 | ```bash
32 | $ pandoc PenseEmPython.xml -f docbook -t markdown_github -o PenseEmPython.md
33 | ```
34 |
35 | Os arquivos _markdown_ separados por capítulo em [`recebido/docs/`](recebido/docs/) foram gerados a partir de `PenseEmPython.md` pelo script [`util/separar_capitulos.py`](util/separar_capitulos.py).
36 |
37 | A partir desse ponto, os ajustes nos capítulos foram feitos manualmente, com ajuda ocasional de scripts encontrados no diretório [`util/`](util/).
38 |
--------------------------------------------------------------------------------
/docs/02-vars-expr-instr.md:
--------------------------------------------------------------------------------
1 | # Capítulo 2: Variáveis, expressões e instruções
2 |
3 | Um dos recursos mais eficientes de uma linguagem de programação é a capacidade de manipular variáveis. Uma variável é um nome que se refere a um valor.
4 |
5 | ## 2.1 - Instruções de atribuição
6 |
7 | Uma instrução de atribuição cria uma nova variável e dá um valor a ela:
8 |
9 | ```python
10 | >>> message = 'And now for something completely different'
11 | >>> n = 17
12 | >>> pi = 3.141592653589793
13 | ```
14 |
15 | Esse exemplo faz três atribuições. A primeira atribui uma string a uma nova variável chamada message; a segunda dá o número inteiro 17 a n; a terceira atribui o valor (aproximado) de π a pi.
16 |
17 | Uma forma comum de representar variáveis por escrito é colocar o nome com uma flecha apontando para o seu valor. Este tipo de número é chamado de diagrama de estado porque mostra o estado no qual cada uma das variáveis está (pense nele como o estado de espírito da variável). A Figura 2.1 mostra o resultado do exemplo anterior.
18 |
19 | 
20 |
_Figura 2.1 – Diagrama de estado._
21 |
22 |
23 | ## 2.2 - Nomes de variáveis
24 |
25 | Os programadores geralmente escolhem nomes significativos para as suas variáveis – eles documentam o uso da variável.
26 |
27 | Nomes de variáveis podem ser tão longos quanto você queira. Podem conter tanto letras como números, mas não podem começar com um número. É legal usar letras maiúsculas, mas a convenção é usar apenas letras minúsculas para nomes de variáveis.
28 |
29 | O caractere de sublinhar (\_) pode aparecer em um nome. Muitas vezes é usado em nomes com várias palavras, como your\_name ou airspeed\_of\_unladen\_swallow.
30 |
31 | Se você der um nome ilegal a uma variável, recebe um erro de sintaxe:
32 |
33 | ```python
34 | >>> 76trombones = 'big parade'
35 | SyntaxError: invalid syntax
36 | >>> more@ = 1000000
37 | SyntaxError: invalid syntax
38 | >>> class = 'Advanced Theoretical Zymurgy'
39 | SyntaxError: invalid syntax
40 | ```
41 | `76trombones` é ilegal porque começa com um número. `more@` é ilegal porque contém um caractere ilegal, o `@`. Mas o que há de errado com `class`?
42 |
43 | A questão é que class é uma das palavras-chave do Python. O interpretador usa palavras-chave para reconhecer a estrutura do programa e elas não podem ser usadas como nomes de variável.
44 |
45 |
46 | O Python 3 tem estas palavras-chave:
47 |
48 | ```
49 | and del from None True
50 | as elif global nonlocal try
51 | assert else if not while
52 | break except import or with
53 | class False in pass yield
54 | continue finally is raise
55 | def for lambda return
56 | ```
57 |
58 | Você não precisa memorizar essa lista. Na maior parte dos ambientes de desenvolvimento, as palavras-chave são exibidas em uma cor diferente; se você tentar usar uma como nome de variável, vai perceber.
59 |
60 | ## 2.3 - Expressões e instruções
61 |
62 | Uma expressão é uma combinação de valores, variáveis e operadores. Um valor por si mesmo é considerado uma expressão, assim como uma variável, portanto as expressões seguintes são todas legais:
63 |
64 | ```python
65 | >>> 42
66 | 42
67 | >>> n
68 | 17
69 | >>> n + 25
70 | 42
71 | ```
72 |
73 | Quando você digita uma expressão no prompt, o interpretador a avalia, ou seja, ele encontra o valor da expressão. Neste exemplo, o n tem o valor 17 e n + 25 tem o valor 42.
74 |
75 | Uma instrução é uma unidade de código que tem um efeito, como criar uma variável ou exibir um valor.
76 |
77 | ```python
78 | >>> n = 17
79 | >>> print(n)
80 | ```
81 |
82 | A primeira linha é uma instrução de atribuição que dá um valor a n. A segunda linha é uma instrução de exibição que exibe o valor de n.
83 |
84 | Quando você digita uma instrução, o interpretador a executa, o que significa que ele faz o que a instrução diz. Em geral, instruções não têm valores.
85 |
86 | ## 2.4 - Modo script
87 |
88 | Até agora executamos o Python no modo interativo, no qual você interage diretamente com o interpretador. O modo interativo é uma boa forma de começar, mas se estiver trabalhando com mais do que algumas linhas do código, o processo pode ficar desorganizado.
89 |
90 | A alternativa é salvar o código em um arquivo chamado script e então executar o interpretador no modo script para executá-lo. Por convenção, os scripts no Python têm nomes que terminam com .py.
91 |
92 | Se souber como criar e executar um script no seu computador, você está pronto. Senão, recomendo usar o PythonAnywhere novamente. Inseri instruções sobre como executar programas no modo script em http://tinyurl.com/thinkpython2e.
93 |
94 | Como o Python oferece os dois modos, você pode testar pedaços do código no modo interativo antes de colocá-los em um script. Mas há diferenças entre o modo interativo e o modo script que podem confundir as pessoas.
95 |
96 | Por exemplo, se estiver usando o Python como uma calculadora, você poderia digitar:
97 |
98 | ```python
99 | >>> miles = 26.2
100 | >>> miles * 1.61
101 | 42.182
102 | ```
103 |
104 | A primeira linha atribui um valor a miles, mas não tem efeito visível. A segunda linha é uma expressão, então o interpretador a avalia e exibe o resultado. No fim, chega-se ao resultado de que uma maratona tem aproximadamente 42 quilômetros.
105 |
106 | Mas se você digitar o mesmo código em um script e executá-lo, não recebe nenhuma saída. Uma expressão, por conta própria, não tem efeito visível no modo script. O Python, na verdade, avalia a expressão, mas não exibe o valor a menos que você especifique:
107 |
108 | ```python
109 | miles = 26.2
110 | print(miles * 1.61)
111 | ```
112 |
113 | Este comportamento pode confundir um pouco no início.
114 |
115 | Um script normalmente contém uma sequência de instruções. Se houver mais de uma instrução, os resultados aparecem um após o outro, conforme as instruções sejam executadas.
116 |
117 | Por exemplo, o script
118 |
119 | ```python
120 | print(1)
121 | x = 2
122 | print(x)
123 | ```
124 | produz a saída
125 |
126 | ```python
127 | 1
128 | 2
129 | ```
130 |
131 | A instrução de atribuição não produz nenhuma saída.
132 |
133 | Para verificar sua compreensão, digite as seguintes instruções no interpretador do Python e veja o que fazem:
134 |
135 | ```python
136 | 5
137 | x = 5
138 | x + 1
139 | ```
140 |
141 | Agora ponha as mesmas instruções em um script e o execute. Qual é a saída? Altere o script transformando cada expressão em uma instrução de exibição e então o execute novamente.
142 |
143 | ## 2.5 - Ordem das operações
144 |
145 | Quando uma expressão contém mais de um operador, a ordem da avaliação depende da ordem das operações. Para operadores matemáticos, o Python segue a convenção matemática. O acrônimo PEMDAS pode ser útil para lembrar das regras:
146 |
147 | * Os Parênteses têm a precedência mais alta e podem ser usados para forçar a avaliação de uma expressão na ordem que você quiser. Como as expressões em parênteses são avaliadas primeiro, `2 * (3-1)` é 4, e `(1+1)**(5-2)` é 8. Também é possível usar parênteses para facilitar a leitura de uma expressão, como no caso de `(minute * 100) / 60`, mesmo se o resultado não for alterado.
148 |
149 | * A Exponenciação tem a próxima precedência mais alta, então `1 + 2**3` é 9, não 27, e `2 * 3**2` é 18, não 36.
150 |
151 | * A Multiplicação e a Divisão têm precedência mais alta que a Adição e a Subtração. Assim, `2 * 3 - 1` é 5, não 4, e `6 + 4 / 2` é 8, não 5.
152 |
153 | * Os operadores com a mesma precedência são avaliados da esquerda para a direita (exceto na exponenciação). Assim, na expressão `degrees / 2 * pi`, a divisão acontece primeiro e o resultado é multiplicado por `pi`. Para dividir por 2π, você pode usar parênteses ou escrever `degrees / 2 / pi`.
154 |
155 | Eu não fico sempre tentando lembrar da precedência de operadores. Se a expressão não estiver clara à primeira vista, uso parênteses para fazer isso.
156 |
157 | ## 2.6 - Operações com strings
158 |
159 | Em geral, não é possível executar operações matemáticas com strings, mesmo se elas parecerem números, então coisas assim são ilegais:
160 |
161 | ```
162 | '2'-'1' 'eggs'/'easy' 'third'*'a charm'
163 | ```
164 |
165 | Mas há duas exceções, `+` e `*`.
166 |
167 | O operador `+` executa uma concatenação de strings, ou seja, une as strings pelas extremidades. Por exemplo:
168 |
169 | ```python
170 | >>> first = 'throat'
171 | >>> second = 'warbler'
172 | >>> first + second
173 | throatwarbler
174 | ```
175 |
176 | O operador `*` também funciona em strings; ele executa a repetição. Por exemplo, 'Spam'`*`3 é 'SpamSpamSpam'. Se um dos valores for uma string, o outro tem de ser um número inteiro.
177 |
178 | Este uso de + e `*` faz sentido por analogia com a adição e a multiplicação. Tal como `4 * 3` é equivalente a `4 + 4 + 4`, esperamos que `'Spam' * 3` seja o mesmo que 'Spam'+'Spam'+'Spam', e assim é. Por outro lado, há uma diferença significativa entre a concatenação de strings e a repetição em relação à adição e à multiplicação de números inteiros. Você consegue pensar em uma propriedade que a adição tem, mas a concatenação de strings não tem?
179 |
180 | ## 2.7 - Comentários
181 |
182 | Conforme os programas ficam maiores e mais complicados, eles são mais difíceis de ler. As linguagens formais são densas e muitas vezes é difícil ver um pedaço de código e compreender o que ele faz ou por que faz isso.
183 |
184 | Por essa razão, é uma boa ideia acrescentar notas aos seus programas para explicar em linguagem natural o que o programa está fazendo. Essas notas são chamadas de comentários, e começam com o símbolo `#`:
185 |
186 |
187 | ```python
188 | # computa a percentagem da hora que passou
189 | percentage = (minute * 100) / 60
190 | ```
191 | Nesse caso, o comentário aparece sozinho em uma linha. Você também pode pôr comentários no fim das linhas:
192 |
193 | ```python
194 | percentage = (minute * 100) / 60 # percentagem de uma hora
195 | ```
196 |
197 | Tudo do `#` ao fim da linha é ignorado – não tem efeito na execução do programa.
198 |
199 | Os comentários tornam-se mais úteis quando documentam algo no código que não está óbvio. Podemos supor que o leitor compreenda o que o código faz; assim, é mais útil explicar porque faz o que faz.
200 |
201 | Este comentário é redundante em relação ao código, além de inútil:
202 |
203 | ```python
204 | v = 5 # atribui 5 a v
205 | ```
206 |
207 | Este comentário contém informações úteis que não estão no código:
208 |
209 | ```python
210 | v = 5 # velocidade em metros/segundo.
211 | ```
212 |
213 | Bons nomes de variáveis podem reduzir a necessidade de comentários, mas nomes longos podem tornar expressões complexas difíceis de ler, então é preciso analisar o que vale mais a pena.
214 |
215 | ## 2.8 - Depuração
216 |
217 | Há três tipos de erros que podem ocorrer em um programa: erros de sintaxe, erros de tempo de execução e erros semânticos. É útil distinguir entre eles para rastreá-los mais rapidamente.
218 |
219 |
220 | - Erro de sintaxe
221 | - A “sintaxe” refere-se à estrutura de um programa e suas respectivas regras. Por exemplo, os parênteses devem vir em pares correspondentes, então (1 + 2) é legal, mas 8) é um erro de sintaxe.
222 | - Se houver um erro de sintaxe em algum lugar no seu programa, o Python exibe uma mensagem de erro e para, e não será possível executar o programa. Nas primeiras poucas semanas da sua carreira em programação, você pode passar muito tempo rastreando erros de sintaxe. Ao adquirir experiência, você fará menos erros e os encontrará mais rápido.
223 |
224 | - Erro de tempo de execução
225 | - O segundo tipo de erro é o erro de tempo de execução, assim chamado porque o erro não aparece até que o programa seja executado. Esses erros também se chamam de exceções porque normalmente indicam que algo excepcional (e ruim) aconteceu.
226 | - Os erros de tempo de execução são raros nos programas simples que veremos nos primeiros capítulos, então pode demorar um pouco até você encontrar algum.
227 |
228 | - Erro semântico
229 | - O terceiro tipo do erro é “semântico”, ou seja, relacionado ao significado. Se houver um erro semântico no seu programa, ele será executado sem gerar mensagens de erro, mas não vai fazer a coisa certa. Vai fazer algo diferente. Especificamente, vai fazer o que você disser para fazer.
230 | - Identificar erros semânticos pode ser complicado, porque é preciso trabalhar de trás para a frente, vendo a saída do programa e tentando compreender o que ele está fazendo.
231 |
232 |
233 | ## 2.9 - Glossário
234 |
235 |
236 | - variável
237 | - Um nome que se refere a um valor.
238 |
239 | - atribuição
240 | - Uma instrução que atribui um valor a uma variável.
241 |
242 | - diagrama de estado
243 | - Uma representação gráfica de um grupo de variáveis e os valores a que se referem.
244 |
245 | - palavra-chave
246 | - Uma palavra reservada, usada para analisar um programa; não é possível usar palavras-chave como if, def e while como nomes de variáveis.
247 |
248 | - operando
249 | - Um dos valores que um operador produz.
250 |
251 | - expressão
252 | - Uma combinação de variáveis, operadores e valores que representa um resultado único.
253 |
254 | - avaliar
255 | - Simplificar uma expressão executando as operações para produzir um valor único.
256 |
257 | - instrução
258 | - Uma seção do código que representa um comando ou ação. Por enquanto, as instruções que vimos são instruções de atribuições e de exibição.
259 |
260 | - executar
261 | - Executar uma instrução para fazer o que ela diz.
262 |
263 | - modo interativo
264 | - Um modo de usar o interpretador do Python, digitando o código no prompt.
265 |
266 | - modo script
267 | - Um modo de usar o interpretador do Python para ler código em um script e executá-lo.
268 |
269 | - script
270 | - Um programa armazenado em um arquivo.
271 |
272 | - ordem das operações
273 | - As regras que governam a ordem na qual as expressões que envolvem vários operadores e operandos são avaliadas.
274 |
275 | - concatenar
276 | - Juntar dois operandos pelas extremidades.
277 |
278 | - comentários
279 | - Informações em um programa destinadas a outros programadores (ou qualquer pessoa que leia o texto fonte) que não têm efeito sobre a execução do programa.
280 |
281 | - erro de sintaxe
282 | - Um erro em um programa que torna sua análise impossível (e por isso impossível de interpretar).
283 |
284 | - exceção
285 | - Um erro que se descobre quando o programa é executado.
286 |
287 | - semântica
288 | - O significado de um programa.
289 |
290 | - erro semântico
291 | - Um erro que faz com que um programa faça algo diferente do que o programador pretendia.
292 |
293 |
294 |
295 | ## 2.10 - Exercícios
296 |
297 | ### Exercício 2.1
298 |
299 | Repetindo o meu conselho do capítulo anterior, sempre que você aprender um recurso novo, você deve testá-lo no modo interativo e fazer erros de propósito para ver o que acontece.
300 |
301 | * Vimos que n = 42 é legal. E 42 = n?
302 |
303 | * Ou x = y = 1?
304 |
305 | * Em algumas linguagens, cada instrução termina em um ponto e vírgula ;. O que acontece se você puser um ponto e vírgula no fim de uma instrução no Python?
306 |
307 | * E se puser um ponto no fim de uma instrução?
308 |
309 | * Em notação matemática é possível multiplicar x e y desta forma: xy. O que acontece se você tentar fazer o mesmo no Python?
310 |
311 | ### Exercício 2.2
312 |
313 | Pratique o uso do interpretador do Python como uma calculadora:
314 |
315 | 1. O volume de uma esfera com raio r é . Qual é o volume de uma esfera com raio 5?
316 |
317 | 2. Suponha que o preço de capa de um livro seja R$ 24,95, mas as livrarias recebem um desconto de 40%. O transporte custa R$ 3,00 para o primeiro exemplar e 75 centavos para cada exemplar adicional. Qual é o custo total de atacado para 60 cópias?
318 |
319 | 3. Se eu sair da minha casa às 6:52 e correr 1 quilômetro a um certo passo (8min15s por quilômetro), então 3 quilômetros a um passo mais rápido (7min12s por quilômetro) e 1 quilômetro no mesmo passo usado em primeiro lugar, que horas chego em casa para o café da manhã?
320 |
--------------------------------------------------------------------------------
/docs/07-iteracao.md:
--------------------------------------------------------------------------------
1 | # Capítulo 7: Iteração
2 |
3 | Este capítulo é sobre a iteração, a capacidade de executar um bloco de instruções repetidamente. Vimos um tipo de iteração, usando a recursividade, em “Recursividade”, na página 81. Vimos outro tipo, usando um loop for, em “Repetição simples”, na página 65. Neste capítulo veremos ainda outro tipo, usando a instrução while. Porém, primeiro quero falar um pouco mais sobre a atribuição de variáveis.
4 |
5 | ## 7.1 - Reatribuição
6 |
7 | Pode ser que você já tenha descoberto que é permitido fazer mais de uma atribuição para a mesma variável. Uma nova atribuição faz uma variável existente referir-se a um novo valor (e deixar de referir-se ao valor anterior).
8 |
9 | ```python
10 | >>> x = 5
11 | >>> x
12 | 5
13 | >>> x = 7
14 | >>> x
15 | 7
16 | ```
17 |
18 | A primeira vez que exibimos x, seu valor é 5; na segunda vez, seu valor é 7.
19 |
20 | A Figura 7.1 mostra que a reatribuição parece um diagrama de estado.
21 |
22 | Neste ponto quero tratar de uma fonte comum de confusão. Como o Python usa o sinal de igual (=) para atribuição, é tentador interpretar uma afirmação como a = b como uma proposição matemática de igualdade; isto é, a declaração de que a e b são iguais. Mas esta é uma interpretação equivocada.
23 |
24 | Em primeiro lugar, a igualdade é uma relação simétrica e a atribuição não é. Por exemplo, na matemática, se a=7 então 7=a. Mas no Python, a instrução a = 7 é legal e 7 = a não é.
25 |
26 | Além disso, na matemática, uma proposição de igualdade é verdadeira ou falsa para sempre. Se a=b agora, então a sempre será igual a b. No Python, uma instrução de atribuição pode tornar duas variáveis iguais, mas elas não precisam se manter assim:
27 |
28 | ```python
29 | >>> a = 5
30 | >>> b = a # a e b agora são iguais
31 | >>> a = 3 # a e b não são mais iguais
32 | >>> b
33 | 5
34 | ```
35 |
36 | A terceira linha modifica o valor de a, mas não muda o valor de b, então elas já não são iguais.
37 |
38 | A reatribuição de variáveis muitas vezes é útil, mas você deve usá-la com prudência. Se os valores das variáveis mudarem frequentemente, isso pode dificultar a leitura e depuração do código.
39 |
40 | ```python
41 | Figura 7.1 – Diagrama de estado.
42 | ```
43 |
44 | 
45 |
_Figura 7.1 – Diagrama de estado da variável x._
46 |
47 | ## 7.2 - Atualização de variáveis
48 |
49 | Um tipo comum de reatribuição é uma atualização, onde o novo valor da variável depende do velho.
50 |
51 | ```python
52 | >>> x = x + 1
53 | ```
54 |
55 | Isso significa “pegue o valor atual de x, acrescente um, e então atualize x para o novo valor”.
56 |
57 | Se você tentar atualizar uma variável que não existe, recebe um erro porque o Python avalia o lado direito antes de atribuir um valor a x:
58 |
59 | ```python
60 | >>> x = x + 1
61 | NameError: name 'x' is not defined
62 | ```
63 |
64 | Antes de poder atualizar uma variável é preciso inicializá-la, normalmente com uma atribuição simples:
65 |
66 | ```python
67 | >>> x = 0
68 | >>> x = x + 1
69 | ```
70 |
71 | Atualizar uma variável acrescentando 1 chama-se incremento; subtrair 1 chama-se decremento.
72 |
73 | ## 7.3 - Instrução while
74 |
75 | Os computadores muitas vezes são usados para automatizar tarefas repetitivas. A repetição de tarefas idênticas ou semelhantes sem fazer erros é algo que os computadores fazem bem e as pessoas não. Em um programa de computador, a repetição também é chamada de iteração.
76 |
77 | Já vimos duas funções, `countdown` e `print_n`, que se repetem usando recursividade. Como a iteração é bem comum, o Python fornece recursos de linguagem para facilitá-la. Um deles é a instrução `for` que vimos em “Repetição simples”, na página 65. Voltaremos a isso mais adiante.
78 |
79 | Outra é a instrução `while`. Aqui está uma versão de countdown que usa a instrução `while`:
80 |
81 | ```python
82 | def countdown(n):
83 | while n > 0:
84 | print(n)
85 | n = n - 1
86 | print('Blastoff!')
87 | ```
88 |
89 | Você até pode ler a instrução `while` como se fosse uma tradução do inglês. Significa “Enquanto `n` for maior que 0, mostre o valor de `n` e então decremente `n`. Quando chegar a 0, mostre a palavra Blastoff!”
90 |
91 | Mais formalmente, aqui está o fluxo de execução para uma instrução while:
92 |
93 | 1. Determine se a condição é verdadeira ou falsa.
94 |
95 | 2. Se for falsa, saia da instrução while e continue a execução da próxima instrução.
96 |
97 | 3. Se a condição for verdadeira, execute o corpo e então volte ao passo 1.
98 |
99 | Este tipo de fluxo chama-se loop (laço), porque o terceiro passo faz um loop de volta ao topo.
100 |
101 | O corpo do loop deve mudar o valor de uma ou mais variáveis para que, a certa altura, a condição fique falsa e o loop termine. Senão o loop vai se repetir para sempre, o que é chamado de loop infinito. Uma fonte infindável de divertimento para cientistas da computação é a observação das instruções no xampu, “Faça espuma, enxágue, repita”, que são parte de um loop infinito.
102 |
103 | No caso de countdown, podemos provar que o loop termina: se `n` for zero ou negativo, o loop nunca é executado. Senão, `n` fica cada vez menor ao passar pelo loop, até eventualmente chegar a 0.
104 |
105 | Para alguns outros loops, não é tão fácil perceber isso. Por exemplo:
106 |
107 | ```python
108 | def sequence(n):
109 | while n != 1:
110 | print(n)
111 | if n % 2 == 0: # n é par
112 | n = n / 2
113 | else: # n é ímpar
114 | n = n * 3 + 1
115 | ```
116 |
117 | A condição deste loop é `n != 1`, então o loop continuará até que `n` seja 1, o que torna a condição falsa.
118 |
119 | Cada vez que passa pelo loop, o programa produz o valor de `n` e então verifica se é par ou ímpar. Se for par, `n` é dividido por 2. Se for ímpar, o valor de `n` é substituído por `n * 3 + 1`. Por exemplo, se o argumento passado a sequence for 3, os valores resultantes de `n` são 3, 10, 5, 16, 8, 4, 2, 1.
120 |
121 | Como `n` às vezes aumenta e às vezes diminui, não há nenhuma prova óbvia de que `n` chegará eventualmente a 1, ou que o programa terminará. Para alguns valores de `n`, podemos provar o término. Por exemplo, se o valor inicial for uma potência de dois, `n` será par cada vez que passar pelo loop até que chegue a 1. O exemplo anterior termina com uma sequência assim, que inicia com 16.
122 |
123 | A questão difícil é se podemos provar que este programa termina para todos os valores positivos de `n`. Por enquanto, ninguém foi capaz de comprovar ou refutar isso! (Veja http://en.wikipedia.org/wiki/Collatz\_conjecture.)
124 |
125 | Como um exercício, reescreva a função print\_n de “Recursividade”, na página 81, usando a iteração em vez da recursividade.
126 |
127 | ## 7.4 - break
128 |
129 | Às vezes você não sabe que está na hora de terminar um loop até que já esteja na metade do corpo. Neste caso pode usar a instrução break para sair do loop.
130 |
131 | Por exemplo, suponha que você quer receber uma entrada do usuário até que este digite done. Você pode escrever:
132 |
133 | ```python
134 | while True:
135 | line = input('> ')
136 | if line == 'done':
137 | break
138 | print(line)
139 | print('Done!')
140 | ```
141 |
142 | A condição do loop é True, que sempre é verdade, então o loop roda até que chegue à instrução de interrupção.
143 |
144 | Cada vez que passa pelo loop, o programa apresenta ao usuário um colchete angular. Se o usuário digitar done, a instrução break sai do loop. Senão, o programa ecoa o que quer que o usuário digite e volta ao topo do loop. Aqui está uma amostra de execução:
145 |
146 | ```python
147 | > not done
148 | not done
149 | > done
150 | Done!
151 | ```
152 |
153 | Esta forma de escrever loops while é comum porque podemos verificar a condição em qualquer lugar do loop (não somente no topo) e podemos exprimir a condição de parada afirmativamente (“pare quando isto acontecer”) em vez de negativamente (“continue a seguir até que isto aconteça”).
154 |
155 | ## 7.5 - Raízes quadradas
156 |
157 | Loops muitas vezes são usados em programas que calculam resultados numéricos, começando com uma resposta aproximada e melhorando-a iterativamente.
158 |
159 | Por exemplo, uma forma de calcular raízes quadradas é o método de Newton. Suponha que você queira saber a raiz quadrada de a. Se começar com quase qualquer estimativa, x, é possível calcular uma estimativa melhor com a seguinte fórmula:
160 |
161 | 
162 |
163 | ```python
164 | Por exemplo, se a for 4 e x for 3:
165 | >>> a = 4
166 | >>> x = 3
167 | >>> y = (x + a/x) / 2
168 | >>> y
169 | 2.16666666667
170 | ```
171 | O resultado é mais próximo à resposta correta ( = 2). Se repetirmos o processo com a nova estimativa, chegamos ainda mais perto:
172 |
173 | ```python
174 | >>> x = y
175 | >>> y = (x + a/x) / 2
176 | >>> y
177 | 2.00641025641
178 | ```
179 | Depois de algumas atualizações, a estimativa é quase exata:
180 |
181 | ```python
182 | >>> x = y
183 | >>> y = (x + a/x) / 2
184 | >>> y
185 | 2.00001024003
186 | >>> x = y
187 | >>> y = (x + a/x) / 2
188 | >>> y
189 | 2.00000000003
190 | ```
191 |
192 | Em geral, não sabemos com antecedência quantos passos são necessários para chegar à resposta correta, mas sabemos quando chegamos lá porque a estimativa para de mudar:
193 |
194 | ```python
195 | >>> x = y
196 | >>> y = (x + a/x) / 2
197 | >>> y
198 | 2.0
199 | >>> x = y
200 | >>> y = (x + a/x) / 2
201 | >>> y
202 | 2.0
203 | ```
204 | Quando y == x, podemos parar. Aqui está um loop que começa com uma estimativa inicial, x, e a melhora até que deixe de mudar:
205 |
206 | ```python
207 | while True:
208 | print(x)
209 | y = (x + a/x) / 2
210 | if y == x:
211 | break
212 | x = y
213 | ```
214 |
215 | Para a maior parte de valores de `a` funciona bem, mas pode ser perigoso testar a igualdade de um float. Os valores de ponto flutuante são aproximadamente corretos: a maioria dos números racionais, como 1/3, e números irracionais, como , não podem ser representados exatamente com um float.
216 |
217 | Em vez de verificar se `x` e `y` são exatamente iguais, é mais seguro usar a função integrada `abs` para calcular o valor absoluto ou magnitude da diferença entre eles:
218 |
219 | ```python
220 | if abs(y-x) < epsilon:
221 | break
222 | ```
223 |
224 | Onde `epsilon` tem um valor como 0.0000001, que determina a proximidade desejada entre `x` e `y`.
225 |
226 | ## 7.6 - Algoritmos
227 |
228 | O método de Newton é um exemplo de um algoritmo: um processo mecânico para resolver uma categoria de problemas (neste caso, calcular raízes quadradas).
229 |
230 | Para entender o que é um algoritmo, pode ser útil começar com algo que não é um algoritmo. Quando aprendeu a multiplicar números de um dígito, você provavelmente memorizou a tabuada. Ou seja, você memorizou 100 soluções específicas. Este tipo de conhecimento não é algorítmico.
231 |
232 | No entanto, se você foi “preguiçoso”, poderia ter aprendido alguns truques. Por exemplo, para encontrar o produto de `n` e 9, pode escrever `n-1` como o primeiro dígito e `10-n` como o segundo dígito. Este truque é uma solução geral para multiplicar qualquer número de dígito único por 9. Isto é um algoritmo!
233 |
234 | De forma semelhante, as técnicas que aprendeu, como o transporte na adição, o empréstimo na subtração e a divisão longa são todos algoritmos. Uma das características de algoritmos é que eles não exigem inteligência para serem executados. São processos mecânicos, nos quais cada passo segue a partir do último, de acordo com um conjunto de regras simples.
235 |
236 | A execução de algoritmos é maçante, mas projetá-los é interessante, intelectualmente desafiador e uma parte central da Ciência da Computação.
237 |
238 | Algumas coisas que as pessoas fazem naturalmente, sem dificuldade ou pensamento consciente, são as mais difíceis para exprimir algoritmicamente. A compreensão de linguagem natural é um bom exemplo. Todos nós o fazemos, mas por enquanto ninguém foi capaz de explicar como o fazemos, pelo menos não na forma de um algoritmo.
239 |
240 | ## 7.7 - Depuração
241 |
242 | Ao começar a escrever programas maiores, pode ser que você passe mais tempo depurando. Mais código significa mais possibilidades fazer erros e mais lugares para esconder defeitos.
243 |
244 | Uma forma de cortar o tempo de depuração é “depurar por bisseção”. Por exemplo, se há 100 linhas no seu programa e você as verifica uma a uma, seriam 100 passos a tomar.
245 |
246 | Em vez disso, tente quebrar o problema pela metade. Olhe para o meio do programa, ou perto disso, para um valor intermediário que possa verificar. Acrescente uma instrução print (ou outra coisa que tenha um efeito verificável) e execute o programa.
247 |
248 | Se a verificação do ponto central for incorreta, deve haver um problema na primeira metade do programa. Se for correta, o problema está na segunda metade.
249 |
250 | Cada vez que executar uma verificação assim, divida ao meio o número de linhas a serem verificadas. Depois de seis passos (que é menos de 100), você teria menos de uma ou duas linhas do código para verificar, pelo menos em teoria.
251 |
252 | Na prática, nem sempre é claro o que representa o “meio do programa” e nem sempre é possível verificá-lo. Não faz sentido contar linhas e encontrar o ponto central exato. Em vez disso, pense em lugares no programa onde poderia haver erros e lugares onde é fácil inserir um ponto de verificação. Então escolha um lugar onde as possibilidades são basicamente as mesmas de que o defeito esteja antes ou depois da verificação.
253 |
254 | ## 7.8 - Glossário
255 |
256 |
257 | - reatribuição
258 | - Atribuir um novo valor a uma variável que já existe.
259 |
260 | - atualização
261 | - Uma atribuição onde o novo valor da variável dependa do velho.
262 |
263 | - inicialização
264 | - Uma atribuição que dá um valor inicial a uma variável que será atualizada.
265 |
266 | - incremento
267 | - Uma atualização que aumenta o valor de uma variável (normalmente por uma unidade).
268 |
269 | - decremento
270 | - Uma atualização que reduz o valor de uma variável.
271 |
272 | - iteração
273 | - Execução repetida de um grupo de instruções, usando uma chamada da função recursiva ou um loop.
274 |
275 | - loop infinito
276 | - Um loop no qual a condição de término nunca é satisfeita.
277 |
278 | - algoritmo
279 | - Um processo geral para resolver uma categoria de problemas.
280 |
281 |
282 |
283 | ## 7.9 - Exercícios
284 |
285 | ### Exercício 7.1
286 |
287 | Copie o loop de “Raízes quadradas”, na página 111, e encapsule-o em uma função chamada `mysqrt` que receba a como parâmetro, escolha um valor razoável de x e devolva uma estimativa da raiz quadrada de a.
288 |
289 | Para testar, escreva uma função denominada `test_square_root`, que exibe uma tabela como esta:
290 |
291 | ```python
292 | a mysqrt(a) math.sqrt(a) diff
293 | - --------- ------------ ----
294 | 1.0 1.0 1.0 0.0
295 | 2.0 1.41421356237 1.41421356237 2.22044604925e-16
296 | 3.0 1.73205080757 1.73205080757 0.0
297 | 4.0 2.0 2.0 0.0
298 | 5.0 2.2360679775 2.2360679775 0.0
299 | 6.0 2.44948974278 2.44948974278 0.0
300 | 7.0 2.64575131106 2.64575131106 0.0
301 | 8.0 2.82842712475 2.82842712475 4.4408920985e-16
302 | 9.0 3.0 3.0 0.0
303 | ```
304 |
305 | A primeira coluna é um número, `a`; a segunda coluna é a raiz quadrada de a calculada com `mysqrt`; a terceira coluna é a raiz quadrada calculada por `math.sqrt`; a quarta coluna é o valor absoluto da diferença entre as duas estimativas.
306 |
307 | ### Exercício 7.2
308 |
309 | A função integrada `eval` toma uma string e a avalia, usando o interpretador do Python. Por exemplo:
310 |
311 | ```python
312 | >>> eval('1 + 2 * 3')
313 | 7
314 | >>> import math
315 | >>> eval('math.sqrt(5)')
316 | 2.2360679774997898
317 | >>> eval('type(math.pi)')
318 |
319 | ```
320 |
321 | Escreva uma função chamada `eval_loop` que iterativamente peça uma entrada ao usuário, a avalie usando `eval` e exiba o resultado.
322 |
323 | Ela deve continuar até que o usuário digite `done`; então deverá exibir o valor da última expressão avaliada.
324 |
325 | ### Exercício 7.3
326 |
327 | O matemático Srinivasa Ramanujan encontrou uma série infinita que pode ser usada para gerar uma aproximação numérica de 1/π:
328 |
329 | 
330 |
331 | Escreva uma função chamada `estimate_pi` que use esta fórmula para computar e devolver uma estimativa de π. Você deve usar o loop `while` para calcular os termos da adição até que o último termo seja menor que 1e-15 (que é a notação do Python para `10 ** 15`). Você pode verificar o resultado comparando-o com `math.pi`.
332 |
--------------------------------------------------------------------------------
/docs/09-caso-palavras.md:
--------------------------------------------------------------------------------
1 | # Capítulo 9: Estudo de caso: jogos de palavras
2 |
3 | Este capítulo apresenta o segundo estudo de caso que envolve solucionar quebra-cabeças usando palavras com certas propriedades. Por exemplo, encontraremos os palíndromos mais longos em inglês e procuraremos palavras cujas letras apareçam em ordem alfabética. E apresentarei outro plano de desenvolvimento de programa: a redução a um problema resolvido anteriormente.
4 |
5 | ## 9.1 - Leitura de listas de palavras
6 |
7 | Para os exercícios deste capítulo vamos usar uma lista de palavras em inglês. Há muitas listas de palavras disponíveis na internet, mas a mais conveniente ao nosso propósito é uma das listas de palavras disponibilizadas em domínio público por Grady Ward como parte do projeto lexical Moby (ver http://wikipedia.org/wiki/Moby\_Project). É uma lista de 113.809 palavras cruzadas oficiais; isto é, as palavras que se consideram válidas em quebra-cabeças de palavras cruzadas e outros jogos de palavras. Na coleção Moby, o nome do arquivo é 113809of.fic; você pode baixar uma cópia, com um nome mais simples como words.txt, de http://thinkpython2.com/code/words.txt.
8 |
9 | Este arquivo está em texto simples, então você pode abri-lo com um editor de texto, mas também pode lê-lo no Python. A função integrada open recebe o nome do arquivo como um parâmetro e retorna um objeto de arquivo que você pode usar para ler o arquivo.
10 |
11 | ```python
12 | >>> fin = open('words.txt')
13 | ```
14 |
15 | `fin` é um nome comum de objeto de arquivo usado para entrada de dados. O objeto de arquivo oferece vários métodos de leitura, inclusive readline, que lê caracteres no arquivo até chegar a um comando de nova linha, devolvendo o resultado como uma string:
16 |
17 | ```python
18 | >>> fin.readline()
19 | 'aa\r\n'
20 | ```
21 |
22 | A primeira palavra nesta lista específica é “aa”, uma espécie de lava. A sequência `'\r\n'` representa dois caracteres que representam espaços em branco (whitespace), um retorno de carro e uma nova linha, que separa esta palavra da seguinte.
23 |
24 | O objeto de arquivo grava a posição em que está no arquivo, então se você chamar readline mais uma vez, receberá a seguinte palavra:
25 |
26 | ```python
27 | >>> fin.readline()
28 | 'aah\r\n'
29 | ```
30 |
31 | A palavra seguinte é “aah”, uma palavra perfeitamente legítima, então pare de olhar para mim desse jeito. Ou, se é o whitespace que está incomodando você, podemos nos livrar dele com o método de string `strip`:
32 |
33 | ```python
34 | >>> line = fin.readline()
35 | >>> word = line.strip()
36 | >>> word
37 | 'aahed'
38 | ```
39 |
40 | Você também pode usar um objeto de arquivo como parte de um loop `for`. Este programa lê words.txt e imprime cada palavra, uma por linha:
41 |
42 | ```python
43 | fin = open('words.txt')
44 | for line in fin:
45 | word = line.strip()
46 | print(word)
47 | ```
48 |
49 | ## 9.2 - Exercícios
50 |
51 | Há soluções para estes exercícios na próxima seção. Mas é bom você tentar fazer cada um antes de ver as soluções.
52 |
53 | ### Exercício 9.1
54 |
55 | Escreva um programa que leia words.txt e imprima apenas as palavras com mais de 20 caracteres (sem contar whitespace).
56 |
57 | ### Exercício 9.2
58 |
59 | Em 1939, Ernest Vincent Wright publicou uma novela de 50.000 palavras, chamada Gadsby, que não contém a letra “e”. Como o “e” é a letra mais comum em inglês, isso não é algo fácil de fazer.
60 |
61 | Na verdade, é difícil até construir um único pensamento sem usar o símbolo mais comum do idioma. No início é lento, mas com prudência e horas de treino, vai ficando cada vez mais fácil.
62 |
63 | ```python
64 | Muito bem, agora eu vou parar.
65 | ```
66 |
67 | Escreva uma função chamada `has_no_e` que retorne `True` se a palavra dada não tiver a letra “e” nela.
68 |
69 | Altere seu programa na seção anterior para imprimir apenas as palavras que não têm “e” e calcule a porcentagem de palavras na lista que não têm “e”.
70 |
71 | ### Exercício 9.3
72 |
73 | Escreva uma função chamada avoids que receba uma palavra e uma série de letras proibidas, e retorne True se a palavra não usar nenhuma das letras proibidas.
74 |
75 | Altere o código para que o usuário digite uma série de letras proibidas e o programa imprima o número de palavras que não contêm nenhuma delas. Você pode encontrar uma combinação de cinco letras proibidas que exclua o menor número possível de palavras?
76 |
77 | ### Exercício 9.4
78 |
79 | Escreva uma função chamada `uses_only` que receba uma palavra e uma série de letras e retorne `True`, se a palavra só contiver letras da lista. Você pode fazer uma frase usando só as letras acefhlo? Que não seja “Hoe alfalfa?”
80 |
81 | ### Exercício 9.5
82 |
83 | Escreva uma função chamada `uses_all` que receba uma palavra e uma série de letras obrigatórias e retorne `True` se a palavra usar todas as letras obrigatórias pelo menos uma vez. Quantas palavras usam todas as vogais (aeiou)? E que tal aeiouy?
84 |
85 | ### Exercício 9.6
86 |
87 | Escreva uma função chamada `is_abecedarian` que retorne `True` se as letras numa palavra aparecerem em ordem alfabética (tudo bem se houver letras duplas). Quantas palavras em ordem alfabética existem?
88 |
89 | ## 9.3 - Busca
90 |
91 | Todos os exercícios na seção anterior têm algo em comum; eles podem ser resolvidos com o modelo de busca que vimos em [Buscando](./08-strings.md#86---buscando). O exemplo mais simples é:
92 |
93 | ```python
94 | def has_no_e(word):
95 | for letter in word:
96 | if letter == 'e':
97 | return False
98 | return True
99 | ```
100 |
101 | O loop for atravessa os caracteres em word. Se encontrarmos a letra “e”, podemos retornar False imediatamente; se não for o caso, temos que ir à letra seguinte. Se sairmos do loop normalmente, isso quer dizer que não encontramos um “e”, então retornamos True.
102 |
103 | Você pode escrever esta função de forma mais concisa usando o operador in, mas comecei com esta versão porque ela demonstra a lógica do modelo de busca.
104 |
105 | `avoids` é uma versão mais geral de `has_no_e`, mas tem a mesma estrutura:
106 |
107 |
108 | ```python
109 | def avoids(word, forbidden):
110 | for letter in word:
111 | if letter in forbidden:
112 | return False
113 | return True
114 | ```
115 |
116 | Podemos retornar `False` logo que encontrarmos uma letra proibida; se chegarmos ao fim do loop, retornamos `True`.
117 |
118 | `uses_only` é semelhante, exceto pelo sentido da condição, que se inverte:
119 |
120 | ```python
121 | def uses_only(word, available):
122 | for letter in word:
123 | if letter not in available:
124 | return False
125 | return True
126 | ```
127 |
128 | Em vez de uma lista de letras proibidas, temos uma lista de letras disponíveis. Se encontrarmos uma letra em word que não está em `available`, podemos retornar `False`.
129 |
130 | `uses_all` é semelhante, mas invertemos a função da palavra e a string de letras:
131 |
132 | ```python
133 | def uses_all(word, required):
134 | for letter in required:
135 | if letter not in word:
136 | return False
137 | return True
138 | ```
139 |
140 | Em vez de atravessar as letras em `word`, o loop atravessa as letras obrigatórias. Se alguma das letras obrigatórias não aparecer na palavra, podemos retornar `False`.
141 |
142 | Se você realmente estivesse pensando como um cientista da computação, teria reconhecido que `uses_all` foi um exemplo de um problema resolvido anteriormente e escreveria:
143 |
144 | ```python
145 | def uses_all(word, required):
146 | return uses_only(required, word)
147 | ```
148 |
149 | Esse é um exemplo de um plano de desenvolvimento de programa chamado __redução a um problema resolvido anteriormente__, ou seja, você reconhece o problema no qual está trabalhando como um exemplo de um problema já resolvido e aplica uma solução existente.
150 |
151 | ## 9.4 - Loop com índices
152 |
153 | Escrevi as funções na seção anterior com loops `for` porque eu só precisava dos caracteres nas strings; não precisava fazer nada com os índices.
154 |
155 | Para `is_abecedarian` temos que comparar letras adjacentes, o que é um pouco complicado para o loop for:
156 |
157 | ```python
158 | def is_abecedarian(word):
159 | previous = word[0]
160 | for c in word:
161 | if c < previous:
162 | return False
163 | previous = c
164 | return True
165 | ```
166 |
167 | Uma alternativa é usar a recursividade:
168 |
169 | ```python
170 | def is_abecedarian(word):
171 | if len(word) <= 1:
172 | return True
173 | if word[0] > word[1]:
174 | return False
175 | return is_abecedarian(word[1:])
176 | ```
177 |
178 | Outra opção é usar um loop `while`:
179 |
180 | ```python
181 | def is_abecedarian(word):
182 | i = 0
183 | while i < len(word)-1:
184 | if word[i+1] < word[i]:
185 | return False
186 | i = i+1
187 | return True
188 | ```
189 |
190 | O loop começa com `i == 0` e termina quando `i == len(word)-1`. Cada vez que passa pelo loop, o programa compara o “i-ésimo” caractere (que você pode considerar o caractere atual) com o caractere de posição `i+1` (que pode ser considerado o caractere seguinte).
191 |
192 | Se o próximo caractere for de uma posição anterior (alfabeticamente anterior) à atual, então descobrimos uma quebra na tendência alfabética, e retornamos `False`.
193 |
194 | Se chegarmos ao fim do loop sem encontrar uma quebra, então a palavra passa no teste. Para convencer-se de que o loop termina corretamente, considere um exemplo como `'flossy'`. O comprimento da palavra é 6, então o loop é executado pela última vez quando i for igual a 4, que é o índice do segundo caractere de trás para frente. Na última iteração, o programa compara o penúltimo caractere com o último, que é o que queremos.
195 |
196 | Aqui está uma versão de `is_palindrome` (veja o Exercício 6.3) que usa dois índices: um começa no início e aumenta; o outro começa no final e diminui.
197 |
198 | ```python
199 | def is_palindrome(word):
200 | i = 0
201 | j = len(word)-1
202 | while i
237 | objeto de arquivo
238 | Um valor que representa um arquivo aberto.
239 |
240 | redução a um problema resolvido anteriormente
241 | Um modo de resolver um problema expressando-o como uma instância de um problema resolvido anteriormente.
242 |
243 | caso especial
244 | Um caso de teste que é atípico ou não é óbvio (e com probabilidade menor de ser tratado corretamente).
245 |
246 |
247 |
248 | ## 9.7 - Exercícios
249 |
250 | ### Exercício 9.7
251 |
252 | Esta pergunta é baseada em um quebra-cabeça veiculado em um programa de rádio chamado Car Talk (http://www.cartalk.com/content/puzzlers):
253 |
254 | Dê uma palavra com três letras duplas consecutivas. Vou dar exemplos de palavras que quase cumprem a condição, mas não chegam lá. Por exemplo, a palavra committee, c-o-m-m-i-t-t-e-e. Seria perfeita se não fosse aquele ‘i’ que se meteu ali no meio. Ou Mississippi: M-i-s-s-i-s-s-i-p-p-i. Se pudesse tirar aqueles ‘is’, daria certo. Mas há uma palavra que tem três pares consecutivos de letras e, que eu saiba, pode ser a única palavra que existe. É claro que provavelmente haja mais umas 500, mas só consigo pensar nessa. Qual é a palavra?
255 |
256 | Escreva um programa que a encontre.
257 |
258 | Solução: http://thinkpython2.com/code/cartalk1.py.
259 |
260 | ### Exercício 9.8
261 |
262 | Aqui está outro quebra-cabeça do programa Car Talk (http://www.cartalk.com/content/puzzlers):
263 |
264 | “Estava dirigindo outro dia e percebi algo no hodômetro que chamou a minha atenção. Como a maior parte dos hodômetros, ele mostra seis dígitos, apenas em milhas inteiras. Por exemplo, se o meu carro tivesse 300.000 milhas, eu veria 3-0-0-0-0-0.
265 |
266 | “Agora, o que vi naquele dia foi muito interessante. Notei que os últimos 4 dígitos eram um palíndromo; isto é, podiam ser lidos da mesma forma no sentido correto e no sentido inverso. Por exemplo, 5-4-4-5 é um palíndromo, então no meu hodômetro poderia ser 3-1-5-4-4-5.
267 |
268 | “Uma milha depois, os últimos 5 números formaram um palíndromo. Por exemplo, poderia ser 3-6-5-4-5-6. Uma milha depois disso, os 4 números do meio, dentro dos 6, formavam um palíndromo. E adivinhe só? Um milha depois, todos os 6 formavam um palíndromo!
269 |
270 | “A pergunta é: o que estava no hodômetro quando olhei primeiro?”
271 |
272 | Escreva um programa Python que teste todos os números de seis dígitos e imprima qualquer número que satisfaça essas condições.
273 |
274 | Solução: http://thinkpython2.com/code/cartalk2.py.
275 |
276 | ### Exercício 9.9
277 |
278 | Aqui está outro problema do Car Talk que você pode resolver com uma busca (http://www.cartalk.com/content/puzzlers):
279 |
280 | “Há pouco tempo recebi uma visita da minha mãe e percebemos que os dois dígitos que compõem a minha idade, quando invertidos, representavam a idade dela. Por exemplo, se ela tem 73 anos, eu tenho 37 anos. Ficamos imaginando com que frequência isto aconteceu nos anos anteriores, mas acabamos mudando de assunto e não chegamos a uma resposta.
281 |
282 | “Quando cheguei em casa, cheguei à conclusão de que os dígitos das nossas idades tinham sido reversíveis seis vezes até então. Também percebi que, se tivéssemos sorte, isso aconteceria novamente dali a alguns anos, e se fôssemos muito sortudos, aconteceria mais uma vez depois disso. Em outras palavras, aconteceria 8 vezes no total. Então a pergunta é: quantos anos tenho agora?”
283 |
284 | Escreva um programa em Python que busque soluções para esse problema. Dica: pode ser uma boa ideia usar o método de string zfill.
285 |
--------------------------------------------------------------------------------
/docs/15-classes-objetos.md:
--------------------------------------------------------------------------------
1 | # Capítulo 15: Classes e objetos
2 |
3 | A esta altura você já sabe como usar funções para organizar código e tipos integrados para organizar dados. O próximo passo é aprender “programação orientada a objeto”, que usa tipos definidos pelos programadores para organizar tanto o código quanto os dados. A programação orientada a objeto é um tópico abrangente; será preciso passar por alguns capítulos para abordar o tema.
4 |
5 | Os exemplos de código deste capítulo estão disponíveis em http://thinkpython2.com/code/Point1.py; as soluções para os exercícios estão disponíveis em http://thinkpython2.com/code/Point1_soln.py.
6 |
7 | ## 15.1 - Tipos definidos pelos programadores
8 |
9 | Já usamos muitos tipos integrados do Python; agora vamos definir um tipo próprio. Como exemplo, criaremos um tipo chamado `Point`, que representa um ponto no espaço bidimensional.
10 |
11 | Na notação matemática, os pontos muitas vezes são escritos entre parênteses, com uma vírgula separando as coordenadas. Por exemplo, (0,0) representa a origem e (x, y) representa o ponto que está x unidades à direita e y unidades acima da origem.
12 |
13 | Há várias formas para representar pontos no Python:
14 |
15 | * Podemos armazenar as coordenadas separadamente em duas variáveis, x e y.
16 |
17 | * Podemos armazenar as coordenadas como elementos em uma lista ou tupla.
18 |
19 | * Podemos criar um tipo para representar pontos como objetos.
20 |
21 | Criar um tipo é mais complicado que outras opções, mas tem vantagens que logo ficarão evidentes.
22 |
23 | Um tipo definido pelo programador também é chamado de classe. Uma definição de classe pode ser assim:
24 |
25 | ```python
26 | class Point:
27 | """Represents a point in 2-D space."""
28 | ```
29 |
30 | O cabeçalho indica que a nova classe se chama `Point`. O corpo é uma docstring que explica para que a classe serve. Você pode definir variáveis e métodos dentro de uma definição de classe, mas voltaremos a isso depois.
31 |
32 | Definir uma classe denominada `Point` cria um objeto de classe:
33 |
34 | ```python
35 | >>> Point
36 |
37 | ```
38 |
39 | Como `Point` é definido no nível superior, seu “nome completo” é `__main__.Point`.
40 |
41 | O objeto de classe é como uma fábrica para criar objetos. Para criar um `Point`, você chama `Point` como se fosse uma função:
42 |
43 |
44 | ```python
45 | >>> blank = Point()
46 | >>> blank
47 | <__main__.Point object at 0xb7e9d3ac>
48 | ```
49 |
50 | O valor de retorno é uma referência a um objeto `Point`, ao qual atribuímos blank.
51 |
52 | Criar um objeto chama-se instanciação, e o objeto é uma instância da classe.
53 |
54 | Quando você exibe uma instância, o Python diz a que classe ela pertence e onde está armazenada na memória (o prefixo o 0x significa que o número seguinte está em formato hexadecimal).
55 |
56 | Cada objeto é uma instância de alguma classe, então “objeto” e “instância” são intercambiáveis. Porém, neste capítulo uso “instância” para indicar que estou falando sobre um tipo definido pelo programador.
57 |
58 | ## 15.2 - Atributos
59 |
60 | Você pode atribuir valores a uma instância usando a notação de ponto:
61 |
62 | ```python
63 | >>> blank.x = 3.0
64 | >>> blank.y = 4.0
65 | ```
66 |
67 | Essa sintaxe é semelhante à usada para selecionar uma variável de um módulo, como math.pi ou string.whitespace. Nesse caso, entretanto, estamos atribuindo valores a elementos nomeados de um objeto. Esses elementos chamam-se atributos.
68 |
69 | Em inglês, quando é um substantivo, a palavra “AT-trib-ute” é pronunciada com ênfase na primeira sílaba, ao contrário de “a-TRIB-ute”, que é um verbo.
70 |
71 | O diagrama seguinte mostra o resultado dessas atribuições. Um diagrama de estado que mostra um objeto e seus atributos chama-se diagrama de objeto; veja a Figura 15.1.
72 |
73 | 
74 |
_Figura 15.1 – Diagrama de um objeto_ `Point`.
75 |
76 | A variável blank refere-se a um objeto `Point`, que contém dois atributos. Cada atributo refere-se a um número de ponto flutuante.
77 |
78 | Você pode ler o valor de um atributo usando a mesma sintaxe:
79 |
80 | ```python
81 | >>> blank.y
82 | 4.0
83 | >>> x = blank.x
84 | >>> x
85 | 3.0
86 | ```
87 |
88 | A expressão `blank.x` significa “Vá ao objeto a que blank se refere e pegue o valor de x”. No exemplo, atribuímos este valor a uma variável `x`. Não há nenhum conflito entre a variável `x` e o atributo `x`.
89 |
90 | Você pode usar a notação de ponto como parte de qualquer expressão. Por exemplo:
91 |
92 | ```python
93 | >>> '(%g, %g)' % (blank.x, blank.y)
94 | '(3.0, 4.0)'
95 | >>> distance = math.sqrt(blank.x ** 2 + blank.y ** 2)
96 | >>> distance
97 | 5.0
98 | ```
99 |
100 | Você pode passar uma instância como argumento da forma habitual. Por exemplo:
101 |
102 | ```python
103 | def print_point(p):
104 | print('(%g, %g)' % (p.x, p.y))
105 | ```
106 |
107 | `print_point` toma um ponto como argumento e o exibe em notação matemática. Para invocá-lo, você pode passar `blank` como argumento:
108 |
109 | ```python
110 | >>> print_point(blank)
111 | (3.0, 4.0)
112 | ```
113 |
114 | Dentro da função, `p` é um alias para `blank`, então, se a função altera `p`, `blank` também muda.
115 |
116 | Como exercício, escreva uma função chamada `distance_between_points`, que toma dois pontos como argumentos e retorna a distância entre eles.
117 |
118 | ## 15.3 - Retângulos
119 |
120 | Às vezes, é óbvio quais deveriam ser os atributos de um objeto, mas outras é preciso decidir entre as possibilidades. Por exemplo, vamos supor que você esteja criando uma classe para representar retângulos. Que atributos usaria para especificar a posição e o tamanho de um retângulo? Você pode ignorar ângulo; para manter as coisas simples, suponha que o retângulo seja vertical ou horizontal.
121 |
122 | Há duas possibilidades, no mínimo:
123 |
124 | * Você pode especificar um canto do retângulo (ou o centro), a largura e a altura.
125 |
126 | * Você pode especificar dois cantos opostos.
127 |
128 | Nesse ponto é difícil dizer qual opção é melhor, então implementaremos a primeira, como exemplo.
129 |
130 | Aqui está a definição de classe:
131 |
132 | ```python
133 | class Rectangle:
134 | """Represents a rectangle.
135 | attributes: width, height, corner.
136 | """
137 | ```
138 |
139 | A docstring lista os atributos: width e height são números; corner é um objeto `Point` que especifica o canto inferior esquerdo.
140 |
141 | Para representar um retângulo, você tem que instanciar um objeto `Rectangle` e atribuir valores aos atributos:
142 |
143 | ```python
144 | box = Rectangle()
145 | box.width = 100.0
146 | box.height = 200.0
147 | box.corner = Point()
148 | box.corner.x = 0.0
149 | box.corner.y = 0.0
150 | ```
151 |
152 | A expressão `box.corner.x` significa “Vá ao objeto ao qual `box` se refere e pegue o atributo denominado `corner`; então vá a este objeto e pegue o atributo denominado `x`”.
153 |
154 | A Figura 15.2 mostra o estado deste objeto. Um objeto que é um atributo de outro objeto é integrado.
155 |
156 | A Figura 10.1 mostra o diagrama de estado para cheeses, numbers e empty.
157 |
158 | 
159 |
_Figura 15.2 – Diagrama de um objeto_ `Rectangle`.
160 |
161 |
162 | ## 15.4 - Instâncias como valores de retorno
163 |
164 | As funções podem retornar instâncias. Por exemplo, `find_center` recebe um `Rectangle` como argumento e devolve um `Point`, que contém as coordenadas do centro do retângulo:
165 |
166 | ```python
167 | def find_center(rect):
168 | p = Point()
169 | p.x = rect.corner.x + rect.width/2
170 | p.y = rect.corner.y + rect.height/2
171 | return p
172 | ```
173 |
174 | Aqui está um exemplo que passa `box` como um argumento para `find_center` e atribui o `ponto` resultante à variável `center`:
175 |
176 | ```python
177 | >>> center = find_center(box)
178 | >>> print_point(center)
179 | (50, 100)
180 | ```
181 |
182 | ## 15.5 - Objetos são mutáveis
183 |
184 | Você pode alterar o estado de um objeto fazendo uma atribuição a um dos seus atributos. Por exemplo, para mudar o tamanho de um retângulo sem mudar sua posição, você pode alterar os valores de width e height:
185 |
186 | ```python
187 | box.width = box.width + 50
188 | box.height = box.height + 100
189 | ```
190 |
191 | Você também pode escrever funções que alteram objetos. Por exemplo, `grow_rectangle` recebe um objeto `Rectangle` e dois números, `dwidth` e `dheight`, e adiciona os números à largura e altura do retângulo:
192 |
193 | ```python
194 | def grow_rectangle(rect, dwidth, dheight):
195 | rect.width += dwidth
196 | rect.height += dheight
197 | ```
198 |
199 | Eis um exemplo que demonstra o efeito:
200 |
201 | ```python
202 | >>> box.width, box.height
203 | (150.0, 300.0)
204 | >>> grow_rectangle(box, 50, 100)
205 | >>> box.width, box.height
206 | (200.0, 400.0)
207 | ```
208 |
209 | Dentro da função, `rect` é um alias de `box`, então quando a função altera `rect`, `box` aponta para o objeto alterado.
210 |
211 | Como exercício, escreva uma função chamada `move_rectangle` que toma um Rectangle e dois números chamados dx e dy. Ela deve alterar a posição do retângulo, adicionando dx à coordenada x de corner e adicionando dy à coordenada y de corner.
212 |
213 | ## 15.6 - Cópia
214 |
215 | Alias podem tornar um programa difícil de ler porque as alterações em um lugar podem ter efeitos inesperados em outro lugar. É difícil monitorar todas as variáveis que podem referir-se a um dado objeto.
216 |
217 | Em vez de usar alias, copiar o objeto pode ser uma alternativa. O módulo `copy` contém uma função chamada `copy` que pode duplicar qualquer objeto:
218 |
219 | ```python
220 | >>> p1 = Point()
221 | >>> p1.x = 3.0
222 | >>> p1.y = 4.0
223 | >>> import copy
224 | >>> p2 = copy.copy(p1)
225 | ```
226 |
227 | `p1` e `p2` contêm os mesmos dados, mas não são o mesmo `Point`:
228 |
229 | ```python
230 | >>> print_point(p1)
231 | (3, 4)
232 | >>> print_point(p2)
233 | (3, 4)
234 | >>> p1 is p2
235 | False
236 | >>> p1 == p2
237 | False
238 | ```
239 |
240 | O operador `is` indica que `p1` e `p2` não são o mesmo objeto, que é o que esperamos. Porém, você poderia ter esperado que `==` fosse apresentado como `True`, porque esses pontos contêm os mesmos dados. Nesse caso, pode ficar desapontado ao saber que, para instâncias, o comportamento padrão do operador `==` é o mesmo que o do operador `is`; ele verifica a identidade dos objetos, não a sua equivalência. Isso acontece porque, para tipos definidos pelo programador, o Python não sabe o que deve ser considerado equivalente. Pelo menos, ainda não.
241 |
242 | Se você usar `copy.copy` para duplicar um retângulo, descobrirá que ele copia o objeto `Rectangle`, mas não o `Point` embutido nele:
243 |
244 | ```python
245 | >>> box2 = copy.copy(box)
246 | >>> box2 is box
247 | False
248 | >>> box2.corner is box.corner
249 | True
250 | ```
251 |
252 | A Figura 15.3 mostra como fica o diagrama de objeto. Esta operação chama-se cópia superficial porque copia o objeto e qualquer referência que contenha, mas não os objetos integrados.
253 |
254 | 
255 |
_Figura 15.3 – Diagrama: dois objetos_ `Rectangle` _compartilhando o mesmo_ `Point`.
256 |
257 | Para a maior parte das aplicações, não é isso que você quer. Nesse exemplo, invocar `grow_rectangle` em um dos Rectangles não afetaria o outro, mas invocar `move_rectangle` em qualquer um deles afetaria a ambos! Esse comportamento é confuso e propenso a erros.
258 |
259 | Felizmente, o módulo `copy` oferece um método chamado `deepcopy` que copia não só o objeto, mas também os objetos aos quais ele se refere, e os objetos aos quais estes se referem, e assim por diante. Você não se surpreenderá ao descobrir que esta operação se chama cópia profunda.
260 |
261 | ```python
262 | >>> box3 = copy.deepcopy(box)
263 | >>> box3 is box
264 | False
265 | >>> box3.corner is box.corner
266 | False
267 | box3 e box são objetos completamente separados.
268 | ```
269 |
270 | Como exercício, escreva uma versão de `move_rectangle` que cria e retorne um novo retângulo em vez de alterar o antigo.
271 |
272 | ## 15.7 - Depuração
273 |
274 | Ao começar a trabalhar com objetos, provavelmente você encontrará algumas novas exceções. Se tentar acessar um atributo que não existe, recebe um `AttributeError`:
275 |
276 | ```python
277 | >>> p = Point()
278 | >>> p.x = 3
279 | >>> p.y = 4
280 | >>> p.z
281 | AttributeError: Point instance has no attribute 'z'
282 | ```
283 |
284 | Se não estiver certo sobre o tipo que um objeto é, pode perguntar:
285 |
286 | ```python
287 | >>> type(p)
288 |
289 | ```
290 |
291 | Você também pode usar `isinstance` para verificar se um objeto é uma instância de uma classe:
292 |
293 | ```python
294 | >>> isinstance(p, Point)
295 | True
296 | ```
297 |
298 | Caso não tenha certeza se um objeto tem determinado atributo, você pode usar a função integrada `hasattr`:
299 |
300 | ```python
301 | >>> hasattr(p, 'x')
302 | True
303 | >>> hasattr(p, 'z')
304 | False
305 | ```
306 |
307 | O primeiro argumento pode ser qualquer objeto; o segundo argumento é uma `string` com o nome do atributo.
308 |
309 | Você também pode usar uma instrução `try` para ver se o objeto tem os atributos de que precisa:
310 |
311 |
312 | ```python
313 | try:
314 | x = p.x
315 | except AttributeError:
316 | x = 0
317 | ```
318 |
319 | Essa abordagem pode facilitar a escrita de funções que atuam com tipos diferentes; você verá mais informações sobre isso em “Polimorfismo”, na página 248.
320 |
321 | ## 15.8 - Glossário
322 |
323 |
324 | - classe
325 | - Tipo definido pelo programador. Uma definição de classe cria um objeto de classe.
326 |
327 | - objeto de classe
328 | - Objeto que contém a informação sobre um tipo definido pelo programador. O objeto de classe pode ser usado para criar instâncias do tipo.
329 |
330 | - instância
331 | - Objeto que pertence a uma classe.
332 |
333 | - instanciar
334 | - Criar um objeto.
335 |
336 | - atributo
337 | - Um dos valores denominados associados a um objeto.
338 |
339 | - objeto integrado
340 | - Objeto que é armazenado como um atributo de outro objeto.
341 |
342 | - cópia superficial
343 | - Copiar o conteúdo de um objeto, inclusive qualquer referência a objetos integrados; implementada pela função copy no módulo copy.
344 |
345 | - cópia profunda
346 | - Copiar o conteúdo de um objeto, bem como qualquer objeto integrado, e qualquer objeto integrado a estes, e assim por diante; implementado pela função deepcopy no módulo copy.
347 |
348 | - diagrama de objeto
349 | - Diagrama que mostra objetos, seus atributos e os valores dos atributos.
350 |
351 |
352 |
353 | ## 15.9 - Exercícios
354 |
355 | ### Exercício 15.1
356 |
357 | 1. Escreva uma definição para uma classe denominada `Circle`, com os atributos center e radius, onde center é um objeto `Point` e radius é um número.
358 |
359 | 2. Instancie um objeto `Circle`, que represente um círculo com o centro em 150, 100 e raio 75.
360 |
361 | 3. Escreva uma função denominada `point_in_circle`, que tome um `Circle` e um `Point` e retorne `True`, se o ponto estiver dentro ou no limite do círculo.
362 |
363 | 4. Escreva uma função chamada `rect_in_circle`, que tome um `Circle` e um Rectangle e retorne `True`, se o retângulo estiver totalmente dentro ou no limite do círculo.
364 |
365 | 5. Escreva uma função denominada `rect_circle_overlap`, que tome um `Circle` e um Rectangle e retorne `True`, se algum dos cantos do retângulo cair dentro do círculo. Ou, em uma versão mais desafiadora, retorne `True` se alguma parte do retângulo cair dentro do círculo.
366 |
367 | Solução: http://thinkpython2.com/code/Circle.py.
368 |
369 | ### Exercício 15.2
370 |
371 | 1. Escreva uma função chamada `draw_rect` que receba um objeto `Turtle` e um `Rectangle` e use o `Turtle` para desenhar o retângulo. Veja no Capítulo 4 os exemplos de uso de objetos `Turtle`.
372 |
373 | 2. Escreva uma função chamada `draw_circle`, que tome um Turtle e um `Circle` e desenhe o círculo.
374 |
--------------------------------------------------------------------------------
/docs/16-classes-funcoes.md:
--------------------------------------------------------------------------------
1 | # Capítulo 16: Classes e funções
2 |
3 | Agora que sabemos como criar tipos, o próximo passo deve ser escrever funções que recebam objetos definidos pelo programador como parâmetros e os retornem como resultados. Neste capítulo também vou apresentar o “estilo funcional de programação” e dois novos planos de desenvolvimento de programas.
4 |
5 | Os exemplos de código deste capítulo estão disponíveis em http://thinkpython2.com/code/Time1.py. As soluções para os exercícios estão em http://thinkpython2.com/code/Time1\_soln.py.
6 |
7 | ## 16.1 - Time
8 |
9 | Para ter mais um exemplo de tipo definido pelo programador, criaremos uma classe chamada `Time` (hora), que registra um horário no dia. A definição da classe é assim:
10 |
11 |
12 | ```python
13 | class Time:
14 | """Represents the time of day.
15 | attributes: hour, minute, second
16 | """
17 | ```
18 |
19 | Podemos criar um objeto `Time` e ter atributos para horas, minutos e segundos:
20 |
21 | ```python
22 | time = Time()
23 | time.hour = 11
24 | time.minute = 59
25 | time.second = 30
26 | ```
27 |
28 | O diagrama de estado do objeto Time está na Figura 16.1.
29 |
30 | 
31 |
_Figura 16.1 – Diagrama de um objeto_ `Time`.
32 |
33 | Como exercício, escreva uma função chamada `print_time`, que receba um objeto Time e o exiba na forma hour:minute:second. Dica: a sequência de formatação `'%.2d'` exibe um número inteiro com, pelo menos, dois dígitos, incluindo um zero à esquerda, se for necessário.
34 |
35 | Escreva uma função booleana chamada `is_after`, que receba dois objetos Time, `t1` e `t2`, e devolva `True` se `t1` for cronologicamente depois de `t2` e `False` se não for. Desafio: não use uma instrução `if`.
36 |
37 | ## 16.2 - Funções puras
38 |
39 | Nas próximas seções, vamos escrever duas funções que adicionam valores de tempo. Elas demonstram dois tipos de funções: funções puras e modificadores. Também demonstram um plano de desenvolvimento que chamarei de protótipo e correção, que é uma forma de atacar um problema complexo começando com um protótipo simples e lidando com as complicações de forma incremental.
40 |
41 | Aqui está um protótipo simples de `add_time`:
42 |
43 | ```python
44 | def add_time(t1, t2):
45 | sum = Time()
46 | sum.hour = t1.hour + t2.hour
47 | sum.minute = t1.minute + t2.minute
48 | sum.second = t1.second + t2.second
49 | return sum
50 | ```
51 |
52 | A função cria um novo objeto `Time`, inicializa seus atributos e retorna uma referência ao novo objeto. A função pura é chamada assim porque não altera nenhum dos objetos passados a ela como argumentos; além disso, ela não tem efeitos, como exibir um valor ou receber entradas de usuário, apenas retorna um valor.
53 |
54 | Para testar esta função, criarei objetos `Time`: `start`, que contém o tempo de início de um filme, como _Monty Python e o cálice sagrado_, e `duration`, que contém o tempo de execução do filme, que é de 1 hora e 35 minutos.
55 |
56 | `add_time` calcula quando o filme acaba:
57 |
58 | ```python
59 | >>> start = Time()
60 | >>> start.hour = 9
61 | >>> start.minute = 45
62 | >>> start.second = 0
63 | >>> duration = Time()
64 | >>> duration.hour = 1
65 | >>> duration.minute = 35
66 | >>> duration.second = 0
67 | >>> done = add_time(start, duration)
68 | >>> print_time(done)
69 | 10:80:00
70 | ```
71 |
72 | O resultado, 10:80:00, pode não ser o que você esperava. O problema é que esta função não trata casos onde o número de segundos ou minutos é maior que 60. Quando isso acontece, precisamos transportar os segundos extras à coluna dos minutos ou os minutos extras à coluna das horas.
73 |
74 | Aqui está uma versão melhorada:
75 |
76 | ```python
77 | def add_time(t1, t2):
78 | sum = Time()
79 | sum.hour = t1.hour + t2.hour
80 | sum.minute = t1.minute + t2.minute
81 | sum.second = t1.second + t2.second
82 | if sum.second >= 60:
83 | sum.second -= 60
84 | sum.minute += 1
85 | if sum.minute >= 60:
86 | sum.minute -= 60
87 | sum.hour += 1
88 | return sum
89 | ```
90 |
91 | Embora esta função esteja correta, é um pouco extensa. Veremos uma alternativa menor mais adiante.
92 |
93 | ## 16.3 - Modificadores
94 |
95 | Às vezes é útil uma função alterar os objetos que recebe como parâmetros. Nesse caso, as mudanças são visíveis a quem chama a função. As funções que fazem isso chamam-se modificadores.
96 |
97 | `increment`, que acrescenta um dado número de segundos a um objeto `Time`, pode ser escrita naturalmente como um modificador. Aqui está um primeiro esboço:
98 |
99 | ```python
100 | def increment(time, seconds):
101 | time.second += seconds
102 | if time.second >= 60:
103 | time.second -= 60
104 | time.minute += 1
105 | if time.minute >= 60:
106 | time.minute -= 60
107 | time.hour += 1
108 | ```
109 |
110 | A primeira linha executa a operação básica; o resto lida com os casos especiais que vimos antes.
111 |
112 | Esta função está correta? O que acontece se `second` for muito mais que 60?
113 |
114 | Neste caso não basta transportar uma vez, temos que continuar fazendo isso até que time.second seja menos de 60. Uma solução é substituir a instrução `if` pela instrução `while`. Isso tornaria a função correta, mas não muito eficiente. Como exercício, escreva uma versão correta de `increment` que não contenha loops.
115 |
116 | O que se faz com modificadores também pode ser feito com funções puras. Na verdade, algumas linguagens de programação só permitem funções puras. Há evidências de que os programas que usam funções puras são mais rápidos para serem desenvolvidos e menos propensos a erros que programas que usam modificadores. No entanto, modificadores são convenientes de vez em quando, e os programas funcionais tendem a ser menos eficientes.
117 |
118 | De forma geral, recomendo que você escreva funções puras sempre que achar razoável e recorra a modificadores só se houver alguma vantagem clara. Esta abordagem pode ser chamada de __programação funcional__.
119 |
120 | Como exercício, escreva uma versão “pura” de increment que cria e retorna um objeto `Time` em vez de alterar o parâmetro.
121 |
122 | ## 16.4 - Prototipação versus planejamento
123 |
124 | O plano de desenvolvimento que estou demonstrando chama-se “protótipo e correção”. Para cada função, escrevi um protótipo que executa o cálculo básico e então testa a função, corrigindo erros no decorrer do caminho.
125 |
126 | Esta abordagem pode ser eficaz, especialmente se você ainda não tem uma compreensão profunda do problema. Porém, as correções incrementais podem gerar código que se complica desnecessariamente (pois trata de muitos casos especiais) e pouco confiáveis (já que é difícil saber se todos os erros foram encontrados).
127 |
128 | Uma alternativa é o desenvolvimento planejado, no qual a compreensão de alto nível do problema pode facilitar muito a programação. Neste caso, descobre-se que um objeto Time é, na verdade, um número de três dígitos na base 60 (veja http://en.wikipedia.org/wiki/Sexagesimal)! O atributo second é a “coluna de unidades”, o atributo minute é a “coluna dos 60”, e o atributo hour é a “coluna do 3.600”.
129 |
130 | Quando escrevemos `add_time` e `increment`, estávamos na verdade fazendo adições na base 60, e por isso transportávamos os resultados de uma coluna à seguinte.
131 |
132 | Essa observação sugere outra abordagem para o problema inteiro – podemos converter objetos `Time` em números inteiros e aproveitar o fato de que o computador sabe trabalhar com aritmética de números inteiros.
133 |
134 | Aqui está uma função que converte objetos `Time` em números inteiros:
135 |
136 |
137 | ```python
138 | def time_to_int(time):
139 | minutes = time.hour * 60 + time.minute
140 | seconds = minutes * 60 + time.second
141 | return seconds
142 | ```
143 |
144 | E aqui está uma função que converte um número inteiro em um `Time` (lembre-se de que `divmod` divide o primeiro argumento pelo segundo e devolve o quociente e o resto como uma tupla):
145 |
146 | ```python
147 | def int_to_time(seconds):
148 | time = Time()
149 | minutes, time.second = divmod(seconds, 60)
150 | time.hour, time.minute = divmod(minutes, 60)
151 | return time
152 | ```
153 |
154 | Você pode ter que pensar um pouco e fazer alguns testes, para se convencer de que essas funções estão corretas. Um modo de testá-las é ver se `time_to_int(int_to_time(x)) == x` para muitos valores de `x`. Este é um exemplo de uma verificação de consistência.
155 |
156 | Uma vez que esteja convencido de que estão corretas, você pode usá-las para reescrever `add_time`:
157 |
158 | ```python
159 | def add_time(t1, t2):
160 | seconds = time_to_int(t1) + time_to_int(t2)
161 | return int_to_time(seconds)
162 | ```
163 |
164 | Esta versão é mais curta que a original, e mais fácil de verificar. Como exercício, reescreva `increment` usando `time_to_int` e `int_to_time`.
165 |
166 | Em algumas situações, converter da base 60 para a base 10 e de volta é mais difícil que apenas lidar com as horas. A conversão de base é mais abstrata; nossa intuição para lidar com valores temporais é melhor.
167 |
168 | No entanto, se tivermos discernimento para lidar com horas como números de base 60 e investirmos esforço em escrever as funções de conversão (`time_to_int` e `int_to_time`), chegamos a um programa que é mais curto, mais fácil de ler e depurar, e mais confiável.
169 |
170 | Também é mais fácil acrescentar recursos depois. Por exemplo, imagine subtrair dois objetos `Time` para encontrar a duração entre eles. Uma abordagem ingênua seria implementar a subtração com transporte. Porém, usar funções de conversão seria mais fácil e, provavelmente, mais correto.
171 |
172 | Ironicamente, tornar um problema mais difícil (ou mais geral) facilita (porque há menos casos especiais e menos oportunidades de erro).
173 |
174 | ## 16.5 - Depuração
175 |
176 | Um objeto `Time` é bem formado se os valores de `minute` e `second` estiverem entre 0 e 60 (incluindo 0, mas não 60) e se `hour` for positivo. `hour` e `minute` devem ser valores inteiros, mas podemos permitir que `second` tenha uma parte fracionária.
177 |
178 | Requisitos como esses chamam-se invariáveis porque sempre devem ser verdadeiros. Para dizer de outra forma, se não forem verdadeiros, algo deu errado.
179 |
180 | Escrever código para verificar requisitos invariáveis pode ajudar a descobrir erros e encontrar suas causas. Por exemplo, você pode ter uma função como valid\_time, que receba um objeto Time e retorne False se ele violar um requisito invariável:
181 |
182 | ```python
183 | def valid_time(time):
184 | if time.hour < 0 or time.minute < 0 or time.second < 0:
185 | return False
186 | if time.minute >= 60 or time.second >= 60:
187 | return False
188 | return True
189 | ```
190 |
191 | No início de cada função você pode verificar os argumentos para ter certeza de que são válidos:
192 |
193 | ```python
194 | def add_time(t1, t2):
195 | if not valid_time(t1) or not valid_time(t2):
196 | raise ValueError('invalid Time object in add_time')
197 |
198 | seconds = time_to_int(t1) + time_to_int(t2)
199 | return int_to_time(seconds)
200 | ```
201 |
202 | Ou você pode usar uma instrução `assert`, que verifica determinado requisito invariável e cria uma exceção se ela falhar:
203 |
204 | ```python
205 | def add_time(t1, t2):
206 | assert valid_time(t1) and valid_time(t2)
207 | seconds = time_to_int(t1) + time_to_int(t2)
208 | return int_to_time(seconds)
209 | ```
210 |
211 | Instruções assert são úteis porque distinguem o código que lida com condições normais do código que verifica erros.
212 |
213 | ## 16.6 - Glossário
214 |
215 |
216 | - protótipo e correção
217 | - Plano de desenvolvimento no qual a escrita do programa parte de um esboço inicial, e depois segue ao teste e correção de erros, conforme sejam encontrados.
218 |
219 | - desenvolvimento planejado
220 | - Plano de desenvolvimento que implica uma compreensão de alto nível do problema e mais planejamento que desenvolvimento incremental ou desenvolvimento prototipado.
221 |
222 | - função pura
223 | - Função que não altera nenhum dos objetos que recebe como argumento. A maior parte das funções puras gera resultado.
224 |
225 | - modificador
226 | - Função que modifica um ou vários dos objetos que recebe como argumento. A maior parte dos modificadores são nulos; isto é, retornam None.
227 |
228 | - programação funcional
229 | - Estilo de projeto de programa no qual a maioria das funções são puras.
230 |
231 | - invariável
232 | - Condição que sempre deve ser verdadeira durante a execução de um programa.
233 |
234 | - instrução assert
235 | - Instrução que verifica uma condição e levanta uma exceção se esta falhar.
236 |
237 |
238 |
239 | ## 16.7 - Exercícios
240 |
241 | Os exemplos de código deste capítulo estão disponíveis em http://thinkpython2.com/code/Time1.py; as soluções para os exercícios estão disponíveis em http://thinkpython2.com/code/Time1_soln.py.
242 |
243 | ### Exercício 16.1
244 |
245 | Escreva uma função chamada `mul_time` que receba um objeto `Time` e um número e retorne um novo objeto `Time` que contenha o produto do `Time` original e do número.
246 |
247 | Então use `mul_time` para escrever uma função que receba um objeto `Time` representando o tempo até o fim de uma corrida e um número que represente a distância, e retorne um objeto `Time` com o passo médio (tempo por milha).
248 |
249 | ### Exercício 16.2
250 |
251 | O módulo `datetime` fornece objetos `time` que são semelhantes aos objetos `Time` deste capítulo, mas ele oferece um grande conjunto de métodos e operadores. Leia a documentação em http://docs.python.org/3/library/datetime.html.
252 |
253 | 1. Use o módulo `datetime` para escrever um programa que receba a data atual e exiba o dia da semana.
254 |
255 | 2. Escreva um programa que receba um aniversário como entrada e exiba a idade do usuário e o número de dias, horas, minutos e segundos até o seu próximo aniversário.
256 |
257 | 3. Para duas pessoas nascidas em dias diferentes, há um dia em que a idade de uma equivale a duas vezes a da outra. Este é o Dia Duplo delas. Escreva um programa que receba dois aniversários e calcule o Dia Duplo dos aniversariantes.
258 |
259 | 4. Para um desafio um pouco maior, escreva a versão mais geral que calcule o dia em que uma pessoa é N vezes mais velha que a outra.
260 |
--------------------------------------------------------------------------------
/docs/C-colofao-autor.md:
--------------------------------------------------------------------------------
1 | # Colofão
2 |
3 |
4 |
5 | O animal na capa de Pense em Python é um papagaio-da-carolina, também conhecido como periquito-da-carolina (Conuropsis carolinensis). Este papagaio habitava o sudeste dos Estados Unidos e foi o único papagaio continental a habitar regiões acima do norte do México. Um dia, vivia no norte, em locais tão distantes quanto Nova Iorque e os Grandes Lagos, embora fosse encontrado principalmente na região da Flórida às Carolinas.
6 |
7 | O papagaio-da-carolina era quase todo verde com a cabeça amarela e, na maturidade, tinha uma coloração laranja na testa e na face. Seu tamanho médio variava de 31 a 33 cm. Tinha uma voz alta, ruidosa e palrava constantemente enquanto se alimentava. Habitava troncos de árvores ocos perto de brejos e barrancos. O papagaio-da-carolina era um animal muito gregário, que vivia em pequenos grupos os quais podiam chegar a várias centenas quando se alimentavam.
8 |
9 | Infelizmente, essas áreas de alimentação muitas vezes eram as plantações de agricultores, que disparavam nos pássaros para mantê-los longe das plantas. A natureza social dos pássaros fazia com que eles voassem ao resgate de qualquer papagaio ferido, permitindo aos agricultores derrubar bandos inteiros de cada vez. Além disso, suas penas eram usadas para embelezar chapéus de senhoras, e alguns papagaios eram mantidos como mascotes. Uma combinação desses fatores levou o papagaio-da-carolina a tornar-se raro no fim dos anos 1800, e as doenças de aves domésticas podem ter contribuído para diminuir seu número. Pelos anos 1920, a espécie estava extinta.
10 |
11 | Hoje, há mais de 700 espécimes de papagaios-da-carolina conservados em museus no mundo inteiro.
12 |
13 | Muitos dos animais nas capas de livros da O’Reilly estão em perigo de extinção; todos eles são importantes para o mundo. Para saber mais sobre como você pode ajudar, acesse animals.oreilly.com. A imagem da capa é do livro Johnson’s Natural History.
14 |
15 | ## Sobre o autor
16 |
17 | Allen Downey é professor de Ciência da Computação no Olin College of Engineering. Ele já ensinou no Wellesley College, Colby College e na U.C. Berkeley. É doutor em Ciência da Computação pela U.C. Berkeley e mestre e graduado pelo MIT.
18 |
--------------------------------------------------------------------------------
/docs/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-cayman
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | # Pense em Python
2 |
3 | ### Pense como um cientista da computação
4 |
5 |
6 |
7 | Este livro ensina programação para quem nunca programou, usando [Python 3](https://www.python.org/) nos exemplos. É aplicado no Olin College, IBMEC e outras faculdades de engenharia de primeira linha.
8 |
9 | > __DICA__: Você pode comprar um exemplar impresso de [__Pense em Python__](https://novatec.com.br/livros/pense-em-python/) no site da [Editora Novatec](https://novatec.com.br/livros/pense-em-python/) ou em livrarias. [ISBN: 978-85-7522-508-0](https://novatec.com.br/livros/pense-em-python/).
10 |
11 | [__Pense em Python__](https://novatec.com.br/livros/pense-em-python/) é uma tradução do livro [Think Python](http://shop.oreilly.com/product/0636920045267.do) (2ª edição), de __Allen B. Downey__, traduzido e publicado no Brasil pela [Editora Novatec](https://novatec.com.br) sob licença da O'Reilly Media.
12 |
13 | ## Sumário
14 |
15 | * [Prefácio](00-prefacio.md)
16 |
17 |
18 | 1. [A jornada do programa](01-jornada.md)
19 | 2. [Variáveis, expressões e instruções](02-vars-expr-instr.md)
20 | 3. [Funções](03-funcoes.md)
21 | 4. [Estudo de caso: projeto de interface](04-caso-interface.md)
22 | 5. [Condicionais e recursividade](05-cond-recur.md)
23 | 6. [Funções com resultado](06-funcoes-result.md)
24 | 7. [Iteração](07-iteracao.md)
25 | 8. [Strings](08-strings.md)
26 | 9. [Estudo de caso: jogos de palavras](09-caso-palavras.md)
27 | 10. [Listas](10-listas.md)
28 | 11. [Dicionários](11-dicionarios.md)
29 | 12. [Tuplas](12-tuplas.md)
30 | 13. [Estudo de caso: seleção de estrutura de dados](13-caso-estruturas.md)
31 | 14. [Arquivos](14-arquivos.md)
32 | 15. [Classes e objetos](15-classes-objetos.md)
33 | 16. [Classes e funções](16-classes-funcoes.md)
34 | 17. [Classes e métodos](17-classes-metodos.md)
35 | 18. [Herança](18-heranca.md)
36 | 19. [Extra](19-extra.md)
37 |
38 |
39 | * [Apêndice A: Depuração](A-depuracao.md)
40 | * [Apêndice B: Análise de algoritmos](B-analise-algorit.md)
41 | * [Colofão / Sobre o Autor](C-colofao-autor.md)
42 |
43 | ## Créditos da edição brasileira
44 |
45 | Editor: Rubens Prates
46 | Tradução: Sheila Gomes
47 | Revisão Gramatical: Smirna Cavalheiro
48 | Editoração Eletrônica: Carolina Kuwabata
49 | Assistente Editorial: Priscila A. Yoshimatsu
50 |
51 |
52 | ## Histórico
53 |
54 | Allen Downey publicou o [original em inglês](http://greenteapress.com/wp/think-python-2e/) sob uma licença Creative Commons Atribuição-NãoComercial [CC BY-NC 3.0](https://github.com/PenseAllen/PensePython2/blob/master/LICENSE.md). A Novatec oferece à comunidade esta tradução nos termos da mesma licença do original, [CC BY-NC 3.0](https://github.com/PenseAllen/PensePython2/blob/master/LICENSE.md), atendendo ao desejo do autor oferecer seu trabalho através de uma licença livre.
55 |
56 | Esta versão digital de __Pense em Python__ em português foi gerada por [Luciano Ramalho](https://twitter.com/ramalhoorg) da [ThoughtWorks](https://www.thoughtworks.com/) a partir de arquivos cedidos por [Rubens Prates](https://novatec.com.br/autores/rprates.php) da [Editora Novatec](https://novatec.com.br).
57 |
--------------------------------------------------------------------------------
/ebooks/PenseEmPython2e.epub:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/ebooks/PenseEmPython2e.epub
--------------------------------------------------------------------------------
/ebooks/metadata.xml:
--------------------------------------------------------------------------------
1 | Pense em Python
2 | Allen Downey
3 | Creative Commons
4 | pt-BR
--------------------------------------------------------------------------------
/fig/p19f1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/p19f1.png
--------------------------------------------------------------------------------
/fig/p242f1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/p242f1.png
--------------------------------------------------------------------------------
/fig/p63f1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/p63f1.png
--------------------------------------------------------------------------------
/fig/p72f1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/p72f1.png
--------------------------------------------------------------------------------
/fig/p79f1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/p79f1.png
--------------------------------------------------------------------------------
/fig/p79f2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/p79f2.png
--------------------------------------------------------------------------------
/fig/p80f1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/p80f1.png
--------------------------------------------------------------------------------
/fig/p83f1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/p83f1.png
--------------------------------------------------------------------------------
/fig/tnkp_0201.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/tnkp_0201.png
--------------------------------------------------------------------------------
/fig/tnkp_0301.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/tnkp_0301.png
--------------------------------------------------------------------------------
/fig/tnkp_0401.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/tnkp_0401.png
--------------------------------------------------------------------------------
/fig/tnkp_0402.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/tnkp_0402.png
--------------------------------------------------------------------------------
/fig/tnkp_0501.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/tnkp_0501.png
--------------------------------------------------------------------------------
/fig/tnkp_0502.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/tnkp_0502.png
--------------------------------------------------------------------------------
/fig/tnkp_0601.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/tnkp_0601.png
--------------------------------------------------------------------------------
/fig/tnkp_0701.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/tnkp_0701.png
--------------------------------------------------------------------------------
/fig/tnkp_0801.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/tnkp_0801.png
--------------------------------------------------------------------------------
/fig/tnkp_0802.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/tnkp_0802.png
--------------------------------------------------------------------------------
/fig/tnkp_1001.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/tnkp_1001.png
--------------------------------------------------------------------------------
/fig/tnkp_1002.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/tnkp_1002.png
--------------------------------------------------------------------------------
/fig/tnkp_1003.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/tnkp_1003.png
--------------------------------------------------------------------------------
/fig/tnkp_1004.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/tnkp_1004.png
--------------------------------------------------------------------------------
/fig/tnkp_1005.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/tnkp_1005.png
--------------------------------------------------------------------------------
/fig/tnkp_1101.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/tnkp_1101.png
--------------------------------------------------------------------------------
/fig/tnkp_1102.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/tnkp_1102.png
--------------------------------------------------------------------------------
/fig/tnkp_1201.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/tnkp_1201.png
--------------------------------------------------------------------------------
/fig/tnkp_1202.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/tnkp_1202.png
--------------------------------------------------------------------------------
/fig/tnkp_1501.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/tnkp_1501.png
--------------------------------------------------------------------------------
/fig/tnkp_1502.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/tnkp_1502.png
--------------------------------------------------------------------------------
/fig/tnkp_1503.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/tnkp_1503.png
--------------------------------------------------------------------------------
/fig/tnkp_1601.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/tnkp_1601.png
--------------------------------------------------------------------------------
/fig/tnkp_1801.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/tnkp_1801.png
--------------------------------------------------------------------------------
/fig/tnkp_1802.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/tnkp_1802.png
--------------------------------------------------------------------------------
/fig/tnkp_2101.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/fig/tnkp_2101.png
--------------------------------------------------------------------------------
/img/Capa_PenseEmPython167x232.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/img/Capa_PenseEmPython167x232.png
--------------------------------------------------------------------------------
/img/Capa_PenseEmPython332x461-borda.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/img/Capa_PenseEmPython332x461-borda.png
--------------------------------------------------------------------------------
/img/Capa_PenseEmPython667x927.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/img/Capa_PenseEmPython667x927.png
--------------------------------------------------------------------------------
/recebido/capitulos.ods:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/capitulos.ods
--------------------------------------------------------------------------------
/recebido/capitulos.txt:
--------------------------------------------------------------------------------
1 | 0 Prefácio
2 | 1 A jornada do programa
3 | 2 Variáveis, expressões e instruções
4 | 3 Funções
5 | 4 Estudo de caso: projeto de interface
6 | 5 Condicionais e recursividade
7 | 6 Funções com resultado
8 | 7 Iteração
9 | 8 Strings
10 | 9 Estudo de caso: jogos de palavras
11 | 10 Listas
12 | 11 Dicionários
13 | 12 Tuplas
14 | 13 Estudo de caso: seleção de estrutura de dados
15 | 14 Arquivos
16 | 15 Classes e objetos
17 | 16 Classes e funções
18 | 17 Classes e métodos
19 | 18 Herança
20 | 19 Extra
21 | A Depuração
22 | B Análise de algoritmos
23 |
--------------------------------------------------------------------------------
/recebido/capitulos/02-vars-expr-instr.md:
--------------------------------------------------------------------------------
1 | # Capítulo 2: Variáveis, expressões e instruções
2 |
3 | Um dos recursos mais eficientes de uma linguagem de programação é a capacidade de manipular variáveis. Uma variável é um nome que se refere a um valor.
4 |
5 | Instruções de atribuição
6 |
7 | Uma instrução de atribuição cria uma nova variável e dá um valor a ela:
8 |
9 | >>> message = 'And now for something completely different'
10 |
11 | >>> n = 17
12 |
13 | >>> pi = 3.141592653589793
14 |
15 | Esse exemplo faz três atribuições. A primeira atribui uma string a uma nova variável chamada message; a segunda dá o número inteiro 17 a n; a terceira atribui o valor (aproximado) de π a pi.
16 |
17 | Uma forma comum de representar variáveis por escrito é colocar o nome com uma flecha apontando para o seu valor. Este tipo de número é chamado de diagrama de estado porque mostra o estado no qual cada uma das variáveis está (pense nele como o estado de espírito da variável). A Figura 2.1 mostra o resultado do exemplo anterior.
18 |
19 | Figura 2.1 – Diagrama de estado.
20 |
21 | Nomes de variáveis
22 |
23 | Os programadores geralmente escolhem nomes significativos para as suas variáveis – eles documentam o uso da variável.
24 |
25 | Nomes de variáveis podem ser tão longos quanto você queira. Podem conter tanto letras como números, mas não podem começar com um número. É legal usar letras maiúsculas, mas a convenção é usar apenas letras minúsculas para nomes de variáveis.
26 |
27 | O caractere de sublinhar (\_) pode aparecer em um nome. Muitas vezes é usado em nomes com várias palavras, como your\_name ou airspeed\_of\_unladen\_swallow.
28 |
29 | Se você der um nome ilegal a uma variável, recebe um erro de sintaxe:
30 |
31 | >>> 76trombones = 'big parade'
32 |
33 | SyntaxError: invalid syntax
34 |
35 | >>> more@ = 1000000
36 |
37 | SyntaxError: invalid syntax
38 |
39 | >>> class = 'Advanced Theoretical Zymurgy'
40 |
41 | SyntaxError: invalid syntax
42 |
43 | 76trombones é ilegal porque começa com um número. more@ é ilegal porque contém um caractere ilegal, o @. Mas o que há de errado com class?
44 |
45 | A questão é que class é uma das palavras-chave do Python. O interpretador usa palavras-chave para reconhecer a estrutura do programa e elas não podem ser usadas como nomes de variável.
46 |
47 | O Python 3 tem estas palavras-chave:
48 |
49 | False class finally is return
50 |
51 | None continue for lambda try
52 |
53 | True def from nonlocal while
54 |
55 | and del global not with
56 |
57 | as elif if or yield
58 |
59 | assert else import pass
60 |
61 | break except in raise
62 |
63 | Você não precisa memorizar essa lista. Na maior parte dos ambientes de desenvolvimento, as palavras-chave são exibidas em uma cor diferente; se você tentar usar uma como nome de variável, vai perceber.
64 |
65 | Expressões e instruções
66 |
67 | Uma expressão é uma combinação de valores, variáveis e operadores. Um valor por si mesmo é considerado uma expressão, assim como uma variável, portanto as expressões seguintes são todas legais:
68 |
69 | >>> 42
70 |
71 | 42
72 |
73 | >>> n
74 |
75 | 17
76 |
77 | >>> n + 25
78 |
79 | 42
80 |
81 | Quando você digita uma expressão no prompt, o interpretador a avalia, ou seja, ele encontra o valor da expressão. Neste exemplo, o n tem o valor 17 e n + 25 tem o valor 42.
82 |
83 | Uma instrução é uma unidade de código que tem um efeito, como criar uma variável ou exibir um valor.
84 |
85 | >>> n = 17
86 |
87 | >>> print(n)
88 |
89 | A primeira linha é uma instrução de atribuição que dá um valor a n. A segunda linha é uma instrução de exibição que exibe o valor de n.
90 |
91 | Quando você digita uma instrução, o interpretador a executa, o que significa que ele faz o que a instrução diz. Em geral, instruções não têm valores.
92 |
93 | Modo script
94 |
95 | Até agora executamos o Python no modo interativo, no qual você interage diretamente com o interpretador. O modo interativo é uma boa forma de começar, mas se estiver trabalhando com mais do que algumas linhas do código, o processo pode ficar desorganizado.
96 |
97 | A alternativa é salvar o código em um arquivo chamado script e então executar o interpretador no modo script para executá-lo. Por convenção, os scripts no Python têm nomes que terminam com .py.
98 |
99 | Se souber como criar e executar um script no seu computador, você está pronto. Senão, recomendo usar o PythonAnywhere novamente. Inseri instruções sobre como executar programas no modo script em http://tinyurl.com/thinkpython2e.
100 |
101 | Como o Python oferece os dois modos, você pode testar pedaços do código no modo interativo antes de colocá-los em um script. Mas há diferenças entre o modo interativo e o modo script que podem confundir as pessoas.
102 |
103 | Por exemplo, se estiver usando o Python como uma calculadora, você poderia digitar:
104 |
105 | >>> miles = 26.2
106 |
107 | >>> miles \* 1.61
108 |
109 | 42.182
110 |
111 | A primeira linha atribui um valor a miles, mas não tem efeito visível. A segunda linha é uma expressão, então o interpretador a avalia e exibe o resultado. No fim, chega-se ao resultado de que uma maratona tem aproximadamente 42 quilômetros.
112 |
113 | Mas se você digitar o mesmo código em um script e executá-lo, não recebe nenhuma saída. Uma expressão, por conta própria, não tem efeito visível no modo script. O Python, na verdade, avalia a expressão, mas não exibe o valor a menos que você especifique:
114 |
115 | miles = 26.2
116 |
117 | print(miles \* 1.61)
118 |
119 | Este comportamento pode confundir um pouco no início.
120 |
121 | Um script normalmente contém uma sequência de instruções. Se houver mais de uma instrução, os resultados aparecem um após o outro, conforme as instruções sejam executadas.
122 |
123 | Por exemplo, o script
124 |
125 | print(1)
126 |
127 | x = 2
128 |
129 | print(x)
130 |
131 | produz a saída
132 |
133 | 1
134 |
135 | 2
136 |
137 | A instrução de atribuição não produz nenhuma saída.
138 |
139 | Para verificar sua compreensão, digite as seguintes instruções no interpretador do Python e veja o que fazem:
140 |
141 | 5
142 |
143 | x = 5
144 |
145 | x + 1
146 |
147 | Agora ponha as mesmas instruções em um script e o execute. Qual é a saída? Altere o script transformando cada expressão em uma instrução de exibição e então o execute novamente.
148 |
149 | Ordem das operações
150 |
151 | Quando uma expressão contém mais de um operador, a ordem da avaliação depende da ordem das operações. Para operadores matemáticos, o Python segue a convenção matemática. O acrônimo PEMDAS pode ser útil para lembrar das regras:
152 |
153 | • Os Parênteses têm a precedência mais alta e podem ser usados para forçar a avaliação de uma expressão na ordem que você quiser. Como as expressões em parênteses são avaliadas primeiro, 2 \* (3-1) é 4, e (1+1)\*\*(5-2) é 8. Também é possível usar parênteses para facilitar a leitura de uma expressão, como no caso de (minute \* 100) / 60, mesmo se o resultado não for alterado.
154 |
155 | • A Exponenciação tem a próxima precedência mais alta, então 1 + 2\*\*3 é 9, não 27, e 2 \* 3\*\*2 é 18, não 36.
156 |
157 | • A Multiplicação e a Divisão têm precedência mais alta que a Adição e a Subtração. Assim, 2\*3-1 é 5, não 4, e 6+4/2 é 8, não 5.
158 |
159 | • Os operadores com a mesma precedência são avaliados da esquerda para a direita (exceto na exponenciação). Assim, na expressão degrees/ 2 \* pi, a divisão acontece primeiro e o resultado é multiplicado por pi. Para dividir por 2π, você pode usar parênteses ou escrever degrees / 2 / pi.
160 |
161 | Eu não fico sempre tentando lembrar da precedência de operadores. Se a expressão não estiver clara à primeira vista, uso parênteses para fazer isso.
162 |
163 | Operações com strings
164 |
165 | Em geral, não é possível executar operações matemáticas com strings, mesmo se elas parecerem números, então coisas assim são ilegais:
166 |
167 | '2'-'1' 'eggs'/'easy' 'third'\*'a charm'
168 |
169 | Mas há duas exceções, + e \*.
170 |
171 | O operador + executa uma concatenação de strings, ou seja, une as strings pelas extremidades. Por exemplo:
172 |
173 | >>> first = 'throat'
174 |
175 | >>> second = 'warbler'
176 |
177 | >>> first + second
178 |
179 | throatwarbler
180 |
181 | O operador \* também funciona em strings; ele executa a repetição. Por exemplo, 'Spam'\*3 é 'SpamSpamSpam'. Se um dos valores for uma string, o outro tem de ser um número inteiro.
182 |
183 | Este uso de + e \* faz sentido por analogia com a adição e a multiplicação. Tal como 4\*3 é equivalente a 4+4+4, esperamos que 'Spam'\*3 seja o mesmo que 'Spam'+'Spam'+'Spam', e assim é. Por outro lado, há uma diferença significativa entre a concatenação de strings e a repetição em relação à adição e à multiplicação de números inteiros. Você consegue pensar em uma propriedade que a adição tem, mas a concatenação de strings não tem?
184 |
185 | Comentários
186 |
187 | Conforme os programas ficam maiores e mais complicados, eles são mais difíceis de ler. As linguagens formais são densas e muitas vezes é difícil ver um pedaço de código e compreender o que ele faz ou por que faz isso.
188 |
189 | Por essa razão, é uma boa ideia acrescentar notas aos seus programas para explicar em linguagem natural o que o programa está fazendo. Essas notas são chamadas de comentários, e começam com o símbolo \#:
190 |
191 | \# computa a percentagem da hora que passou
192 |
193 | percentage = (minute \* 100) / 60
194 |
195 | Nesse caso, o comentário aparece sozinho em uma linha. Você também pode pôr comentários no fim das linhas:
196 |
197 | percentage = (minute \* 100) / 60 \# percentagem de uma hora
198 |
199 | Tudo do \# ao fim da linha é ignorado – não tem efeito na execução do programa.
200 |
201 | Os comentários tornam-se mais úteis quando documentam algo no código que não está óbvio. Podemos supor que o leitor compreenda o que o código faz; assim, é mais útil explicar porque faz o que faz.
202 |
203 | Este comentário é redundante em relação ao código, além de inútil:
204 |
205 | v = 5 \# atribui 5 a v
206 |
207 | Este comentário contém informações úteis que não estão no código:
208 |
209 | v = 5 \# velocidade em metros/segundo.
210 |
211 | Bons nomes de variáveis podem reduzir a necessidade de comentários, mas nomes longos podem tornar expressões complexas difíceis de ler, então é preciso analisar o que vale mais a pena.
212 |
213 | Depuração
214 |
215 | Há três tipos de erros que podem ocorrer em um programa: erros de sintaxe, erros de tempo de execução e erros semânticos. É útil distinguir entre eles para rastreá-los mais rapidamente.
216 |
217 | Erro de sintaxe:
218 |
219 | A “sintaxe” refere-se à estrutura de um programa e suas respectivas regras. Por exemplo, os parênteses devem vir em pares correspondentes, então (1 + 2) é legal, mas 8) é um erro de sintaxe.
220 |
221 | Se houver um erro de sintaxe em algum lugar no seu programa, o Python exibe uma mensagem de erro e para, e não será possível executar o programa. Nas primeiras poucas semanas da sua carreira em programação, você pode passar muito tempo rastreando erros de sintaxe. Ao adquirir experiência, você fará menos erros e os encontrará mais rápido.
222 |
223 | Erro de tempo de execução:
224 |
225 | O segundo tipo de erro é o erro de tempo de execução, assim chamado porque o erro não aparece até que o programa seja executado. Esses erros também se chamam de exceções porque normalmente indicam que algo excepcional (e ruim) aconteceu.
226 |
227 | Os erros de tempo de execução são raros nos programas simples que veremos nos primeiros capítulos, então pode demorar um pouco até você encontrar algum.
228 |
229 | Erro semântico:
230 |
231 | O terceiro tipo do erro é “semântico”, ou seja, relacionado ao significado. Se houver um erro semântico no seu programa, ele será executado sem gerar mensagens de erro, mas não vai fazer a coisa certa. Vai fazer algo diferente. Especificamente, vai fazer o que você disser para fazer.
232 |
233 | Identificar erros semânticos pode ser complicado, porque é preciso trabalhar de trás para a frente, vendo a saída do programa e tentando compreender o que ele está fazendo.
234 |
235 | Glossário
236 |
237 | variável:
238 |
239 | Um nome que se refere a um valor.
240 |
241 | atribuição:
242 |
243 | Uma instrução que atribui um valor a uma variável.
244 |
245 | diagrama de estado:
246 |
247 | Uma representação gráfica de um grupo de variáveis e os valores a que se referem.
248 |
249 | palavra-chave:
250 |
251 | Uma palavra reservada, usada para analisar um programa; não é possível usar palavras-chave como if, def e while como nomes de variáveis.
252 |
253 | operando:
254 |
255 | Um dos valores que um operador produz.
256 |
257 | expressão:
258 |
259 | Uma combinação de variáveis, operadores e valores que representa um resultado único.
260 |
261 | avaliar:
262 |
263 | Simplificar uma expressão executando as operações para produzir um valor único.
264 |
265 | instrução:
266 |
267 | Uma seção do código que representa um comando ou ação. Por enquanto, as instruções que vimos são instruções de atribuições e de exibição.
268 |
269 | executar:
270 |
271 | Executar uma instrução para fazer o que ela diz.
272 |
273 | modo interativo:
274 |
275 | Um modo de usar o interpretador do Python, digitando o código no prompt.
276 |
277 | modo script:
278 |
279 | Um modo de usar o interpretador do Python para ler código em um script e executá-lo.
280 |
281 | script:
282 |
283 | Um programa armazenado em um arquivo.
284 |
285 | ordem das operações:
286 |
287 | As regras que governam a ordem na qual as expressões que envolvem vários operadores e operandos são avaliadas.
288 |
289 | concatenar:
290 |
291 | Juntar dois operandos pelas extremidades.
292 |
293 | comentários:
294 |
295 | Informações em um programa destinadas a outros programadores (ou qualquer pessoa que leia o texto fonte) que não têm efeito sobre a execução do programa.
296 |
297 | erro de sintaxe:
298 |
299 | Um erro em um programa que torna sua análise impossível (e por isso impossível de interpretar).
300 |
301 | exceção:
302 |
303 | Um erro que se descobre quando o programa é executado.
304 |
305 | semântica:
306 |
307 | O significado de um programa.
308 |
309 | erro semântico:
310 |
311 | Um erro que faz com que um programa faça algo diferente do que o programador pretendia.
312 |
313 | Exercícios
314 |
315 | Exercício 2.1
316 |
317 | Repetindo o meu conselho do capítulo anterior, sempre que você aprender um recurso novo, você deve testá-lo no modo interativo e fazer erros de propósito para ver o que acontece.
318 |
319 | • Vimos que n = 42 é legal. E 42 = n?
320 |
321 | • Ou x = y = 1?
322 |
323 | • Em algumas linguagens, cada instrução termina em um ponto e vírgula ;. O que acontece se você puser um ponto e vírgula no fim de uma instrução no Python?
324 |
325 | • E se puser um ponto no fim de uma instrução?
326 |
327 | • Em notação matemática é possível multiplicar x e y desta forma: xy. O que acontece se você tentar fazer o mesmo no Python?
328 |
329 | Exercício 2.2
330 |
331 | Pratique o uso do interpretador do Python como uma calculadora:
332 |
333 | 1. O volume de uma esfera com raio r é . Qual é o volume de uma esfera com raio 5?
334 |
335 | 2. Suponha que o preço de capa de um livro seja R$ 24,95, mas as livrarias recebem um desconto de 40%. O transporte custa R$ 3,00 para o primeiro exemplar e 75 centavos para cada exemplar adicional. Qual é o custo total de atacado para 60 cópias?
336 |
337 | 3. Se eu sair da minha casa às 6:52 e correr 1 quilômetro a um certo passo (8min15s por quilômetro), então 3 quilômetros a um passo mais rápido (7min12s por quilômetro) e 1 quilômetro no mesmo passo usado em primeiro lugar, que horas chego em casa para o café da manhã?
338 |
339 |
--------------------------------------------------------------------------------
/recebido/capitulos/07-iteracao.md:
--------------------------------------------------------------------------------
1 | # Capítulo 7: Iteração
2 |
3 | Este capítulo é sobre a iteração, a capacidade de executar um bloco de instruções repetidamente. Vimos um tipo de iteração, usando a recursividade, em “Recursividade”, na página 81. Vimos outro tipo, usando um loop for, em “Repetição simples”, na página 65. Neste capítulo veremos ainda outro tipo, usando a instrução while. Porém, primeiro quero falar um pouco mais sobre a atribuição de variáveis.
4 |
5 | Reatribuição
6 |
7 | Pode ser que você já tenha descoberto que é legal fazer mais de uma atribuição para a mesma variável. Uma nova atribuição faz uma variável existente referir-se a um novo valor (e deixar de referir-se ao valor anterior).
8 |
9 | >>> x = 5
10 |
11 | >>> x
12 |
13 | 5
14 |
15 | >>> x = 7
16 |
17 | >>> x
18 |
19 | 7
20 |
21 | A primeira vez que exibimos x, seu valor é 5; na segunda vez, seu valor é 7.
22 |
23 | A Figura 7.1 mostra que a reatribuição parece um diagrama de estado.
24 |
25 | Neste ponto quero tratar de uma fonte comum de confusão. Como o Python usa o sinal de igual (=) para atribuição, é tentador interpretar uma afirmação como a = b como uma proposição matemática de igualdade; isto é, a declaração de que a e b são iguais. Mas esta é uma interpretação equivocada.
26 |
27 | Em primeiro lugar, a igualdade é uma relação simétrica e a atribuição não é. Por exemplo, na matemática, se a=7 então 7=a. Mas no Python, a instrução a = 7 é legal e 7 = a não é.
28 |
29 | Além disso, na matemática, uma proposição de igualdade é verdadeira ou falsa para sempre. Se a=b agora, então a sempre será igual a b. No Python, uma instrução de atribuição pode tornar duas variáveis iguais, mas elas não precisam se manter assim:
30 |
31 | >>> a = 5
32 |
33 | >>> b = a \# a e b agora são iguais
34 |
35 | >>> a = 3 \# a e b não são mais iguais
36 |
37 | >>> b
38 |
39 | 5
40 |
41 | A terceira linha modifica o valor de a, mas não muda o valor de b, então elas já não são iguais.
42 |
43 | A reatribuição de variáveis muitas vezes é útil, mas você deve usá-la com prudência. Se os valores das variáveis mudarem frequentemente, isso pode dificultar a leitura e depuração do código.
44 |
45 | Figura 7.1 – Diagrama de estado.
46 |
47 | Atualização de variáveis
48 |
49 | Um tipo comum de reatribuição é uma atualização, onde o novo valor da variável depende do velho.
50 |
51 | >>> x = x + 1
52 |
53 | Isso significa “pegue o valor atual de x, acrescente um, e então atualize x para o novo valor”.
54 |
55 | Se você tentar atualizar uma variável que não existe, recebe um erro porque o Python avalia o lado direito antes de atribuir um valor a x:
56 |
57 | >>> x = x + 1
58 |
59 | NameError: name 'x' is not defined
60 |
61 | Antes de poder atualizar uma variável é preciso inicializá-la, normalmente com uma atribuição simples:
62 |
63 | >>> x = 0
64 |
65 | >>> x = x + 1
66 |
67 | Atualizar uma variável acrescentando 1 chama-se incremento; subtrair 1 chama-se decremento.
68 |
69 | Instrução while
70 |
71 | Os computadores muitas vezes são usados para automatizar tarefas repetitivas. A repetição de tarefas idênticas ou semelhantes sem fazer erros é algo que os computadores fazem bem e as pessoas não. Em um programa de computador, a repetição também é chamada de iteração.
72 |
73 | Já vimos duas funções, countdown e print\_n, que se repetem usando recursividade. Como a iteração é bem comum, o Python fornece recursos de linguagem para facilitá-la. Um deles é a instrução for que vimos em “Repetição simples”, na página 65. Voltaremos a isso mais adiante.
74 |
75 | Outra é a instrução while. Aqui está uma versão de countdown que usa a instrução while:
76 |
77 | def countdown(n):
78 |
79 | while n > 0:
80 |
81 | print(n)
82 |
83 | n = n - 1
84 |
85 | print('Blastoff!')
86 |
87 | Você até pode ler a instrução while como se fosse uma tradução do inglês. Significa “Enquanto n for maior que 0, mostre o valor de n e então decremente n. Quando chegar a 0, mostre a palavra Blastoff!”
88 |
89 | Mais formalmente, aqui está o fluxo de execução para uma instrução while:
90 |
91 | 1. Determine se a condição é verdadeira ou falsa.
92 |
93 | 2. Se for falsa, saia da instrução while e continue a execução da próxima instrução.
94 |
95 | 3. Se a condição for verdadeira, execute o corpo e então volte ao passo 1.
96 |
97 | Este tipo de fluxo chama-se loop, porque o terceiro passo faz um loop de volta ao topo.
98 |
99 | O corpo do loop deve mudar o valor de uma ou mais variáveis para que, a certa altura, a condição fique falsa e o loop termine. Senão o loop vai se repetir para sempre, o que é chamado de loop infinito. Uma fonte infindável de divertimento para cientistas da computação é a observação das instruções no xampu, “Faça espuma, enxágue, repita”, que são parte de um loop infinito.
100 |
101 | No caso de countdown, podemos provar que o loop termina: se n for zero ou negativo, o loop nunca é executado. Senão, n fica cada vez menor ao passar pelo loop, até eventualmente chegar a 0.
102 |
103 | Para alguns outros loops, não é tão fácil perceber isso. Por exemplo:
104 |
105 | def sequence(n):
106 |
107 | while n != 1:
108 |
109 | print(n)
110 |
111 | if n % 2 == 0: \# n é par
112 |
113 | n = n / 2
114 |
115 | else: \# n é ímpar
116 |
117 | n = n\*3 + 1
118 |
119 | A condição deste loop é n != 1, então o loop continuará até que n seja 1, o que torna a condição falsa.
120 |
121 | Cada vez que passa pelo loop, o programa produz o valor de n e então verifica se é par ou ímpar. Se for par, n é dividido por 2. Se for ímpar, o valor de n é substituído por n\*3 + 1. Por exemplo, se o argumento passado a sequence for 3, os valores resultantes de n são 3, 10, 5, 16, 8, 4, 2, 1.
122 |
123 | Como n às vezes aumenta e às vezes diminui, não há nenhuma prova óbvia de que n chegará eventualmente a 1, ou que o programa terminará. Para alguns valores de n, podemos provar o término. Por exemplo, se o valor inicial for uma potência de dois, n será par cada vez que passar pelo loop até que chegue a 1. O exemplo anterior termina com uma sequência assim, que inicia com 16.
124 |
125 | A questão difícil é se podemos provar que este programa termina para todos os valores positivos de n. Por enquanto, ninguém foi capaz de comprovar ou refutar isso! (Veja http://en.wikipedia.org/wiki/Collatz\_conjecture.)
126 |
127 | Como um exercício, reescreva a função print\_n de “Recursividade”, na página 81, usando a iteração em vez da recursividade.
128 |
129 | break
130 |
131 | Às vezes você não sabe que está na hora de terminar um loop até que já esteja na metade do corpo. Neste caso pode usar a instrução break para sair do loop.
132 |
133 | Por exemplo, suponha que você quer receber uma entrada do usuário até que este digite done. Você pode escrever:
134 |
135 | while True:
136 |
137 | line = input('> ')
138 |
139 | if line == 'done':
140 |
141 | break
142 |
143 | print(line)
144 |
145 | print('Done!')
146 |
147 | A condição do loop é True, que sempre é verdade, então o loop roda até que chegue à instrução de interrupção.
148 |
149 | Cada vez que passa pelo loop, o programa apresenta ao usuário um colchete angular. Se o usuário digitar done, a instrução break sai do loop. Senão, o programa ecoa o que quer que o usuário digite e volta ao topo do loop. Aqui está uma amostra de execução:
150 |
151 | > not done
152 |
153 | not done
154 |
155 | > done
156 |
157 | Done!
158 |
159 | Esta forma de escrever loops while é comum porque podemos verificar a condição em qualquer lugar do loop (não somente no topo) e podemos exprimir a condição de parada afirmativamente (“pare quando isto acontecer”) em vez de negativamente (“continue a seguir até que isto aconteça”).
160 |
161 | Raízes quadradas
162 |
163 | Loops muitas vezes são usados em programas que calculam resultados numéricos, começando com uma resposta aproximada e melhorando-a iterativamente.
164 |
165 | Por exemplo, uma forma de calcular raízes quadradas é o método de Newton. Suponha que você queira saber a raiz quadrada de a. Se começar com quase qualquer estimativa, x, é possível calcular uma estimativa melhor com a seguinte fórmula:
166 |
167 | Por exemplo, se a for 4 e x for 3:
168 |
169 | >>> a = 4
170 |
171 | >>> x = 3
172 |
173 | >>> y = (x + a/x) / 2
174 |
175 | >>> y
176 |
177 | 2.16666666667
178 |
179 | O resultado é mais próximo à resposta correta ( = 2). Se repetirmos o processo com a nova estimativa, chegamos ainda mais perto:
180 |
181 | >>> x = y
182 |
183 | >>> y = (x + a/x) / 2
184 |
185 | >>> y
186 |
187 | 2.00641025641
188 |
189 | Depois de algumas atualizações, a estimativa é quase exata:
190 |
191 | >>> x = y
192 |
193 | >>> y = (x + a/x) / 2
194 |
195 | >>> y
196 |
197 | 2.00001024003
198 |
199 | >>> x = y
200 |
201 | >>> y = (x + a/x) / 2
202 |
203 | >>> y
204 |
205 | 2.00000000003
206 |
207 | Em geral, não sabemos com antecedência quantos passos são necessários para chegar à resposta correta, mas sabemos quando chegamos lá porque a estimativa para de mudar:
208 |
209 | >>> x = y
210 |
211 | >>> y = (x + a/x) / 2
212 |
213 | >>> y
214 |
215 | 2.0
216 |
217 | >>> x = y
218 |
219 | >>> y = (x + a/x) / 2
220 |
221 | >>> y
222 |
223 | 2.0
224 |
225 | Quando y == x, podemos parar. Aqui está um loop que começa com uma estimativa inicial, x, e a melhora até que deixe de mudar:
226 |
227 | while True:
228 |
229 | print(x)
230 |
231 | y = (x + a/x) / 2
232 |
233 | if y == x:
234 |
235 | break
236 |
237 | x = y
238 |
239 | Para a maior parte de valores de a funciona bem, mas pode ser perigoso testar a igualdade de um float. Os valores de ponto flutuante são aproximadamente corretos: números mais racionais, como 1/3, e números irracionais, como , não podem ser representados exatamente com um float.
240 |
241 | Em vez de verificar se x e y são exatamente iguais, é mais seguro usar a função integrada abs para calcular o valor absoluto ou magnitude da diferença entre eles:
242 |
243 | if abs(y-x) < epsilon:
244 |
245 | break
246 |
247 | Quando epsilon tem um valor como 0.0000001, isso determina se está próximo o suficiente.
248 |
249 | Algoritmos
250 |
251 | O método de Newton é um exemplo de um algoritmo: um processo mecânico para resolver uma categoria de problemas (neste caso, calcular raízes quadradas).
252 |
253 | Para entender o que é um algoritmo, pode ser útil começar com algo que não é um algoritmo. Quando aprendeu a multiplicar números de um dígito, você provavelmente memorizou a tabuada. Ou seja, você memorizou 100 soluções específicas. Este tipo de conhecimento não é algorítmico.
254 |
255 | No entanto, se você foi “preguiçoso”, poderia ter aprendido alguns truques. Por exemplo, para encontrar o produto de n e 9, pode escrever n-1 como o primeiro dígito e 10-n como o segundo dígito. Este truque é uma solução geral para multiplicar qualquer número de dígito único por 9. Isto é um algoritmo!
256 |
257 | De forma semelhante, as técnicas que aprendeu, como o transporte na adição, o empréstimo na subtração e a divisão longa são todos algoritmos. Uma das características de algoritmos é que eles não exigem inteligência para serem executados. São processos mecânicos, nos quais cada passo segue a partir do último, de acordo com um conjunto de regras simples.
258 |
259 | A execução de algoritmos é maçante, mas projetá-los é interessante, intelectualmente desafiador e uma parte central da Ciência da Computação.
260 |
261 | Algumas coisas que as pessoas fazem naturalmente, sem dificuldade ou pensamento consciente, são as mais difíceis para exprimir algoritmicamente. A compreensão de linguagem natural é um bom exemplo. Todos nós o fazemos, mas por enquanto ninguém foi capaz de explicar como o fazemos, pelo menos não na forma de um algoritmo.
262 |
263 | Depuração
264 |
265 | Ao começar a escrever programas maiores, pode ser que você passe mais tempo depurando. Mais código significa mais possibilidades fazer erros e mais lugares para esconder defeitos.
266 |
267 | Uma forma de cortar o tempo de depuração é “depurar por bisseção”. Por exemplo, se há 100 linhas no seu programa e você as verifica uma a uma, seriam 100 passos a tomar.
268 |
269 | Em vez disso, tente quebrar o problema pela metade. Olhe para o meio do programa, ou perto disso, para um valor intermediário que possa verificar. Acrescente uma instrução print (ou outra coisa que tenha um efeito verificável) e execute o programa.
270 |
271 | Se a verificação do ponto central for incorreta, deve haver um problema na primeira metade do programa. Se for correta, o problema está na segunda metade.
272 |
273 | Cada vez que executar uma verificação assim, divida ao meio o número de linhas a serem verificadas. Depois de seis passos (que é menos de 100), você teria menos de uma ou duas linhas do código para verificar, pelo menos em teoria.
274 |
275 | Na prática, nem sempre é claro o que representa o “meio do programa” e nem sempre é possível verificá-lo. Não faz sentido contar linhas e encontrar o ponto central exato. Em vez disso, pense em lugares no programa onde poderia haver erros e lugares onde é fácil inserir um ponto de verificação. Então escolha um lugar onde as possibilidades são basicamente as mesmas de que o defeito esteja antes ou depois da verificação.
276 |
277 | Glossário
278 |
279 | reatribuição:
280 |
281 | Atribuir um novo valor a uma variável que já existe.
282 |
283 | atualização:
284 |
285 | Uma atribuição onde o novo valor da variável dependa do velho.
286 |
287 | inicialização:
288 |
289 | Uma atribuição que dá um valor inicial a uma variável que será atualizada.
290 |
291 | incremento:
292 |
293 | Uma atualização que aumenta o valor de uma variável (normalmente por uma unidade).
294 |
295 | decremento:
296 |
297 | Uma atualização que reduz o valor de uma variável.
298 |
299 | iteração:
300 |
301 | Execução repetida de um grupo de instruções, usando uma chamada da função recursiva ou um loop.
302 |
303 | loop infinito:
304 |
305 | Um loop no qual a condição de término nunca é satisfeita.
306 |
307 | algoritmo:
308 |
309 | Um processo geral para resolver uma categoria de problemas.
310 |
311 | Exercícios
312 |
313 | Exercício 7.1
314 |
315 | Copie o loop de “Raízes quadradas”, na página 111, e encapsule-o em uma função chamada mysqrt que receba a como parâmetro, escolha um valor razoável de x e devolva uma estimativa da raiz quadrada de a.
316 |
317 | Para testar, escreva uma função denominada test\_square\_root, que imprime uma tabela como esta:
318 |
319 | a mysqrt(a) math.sqrt(a) diff
320 |
321 | - --------- ------------ ----
322 |
323 | 1.0 1.0 1.0 0.0
324 |
325 | 2.0 1.41421356237 1.41421356237 2.22044604925e-16
326 |
327 | 3.0 1.73205080757 1.73205080757 0.0
328 |
329 | 4.0 2.0 2.0 0.0
330 |
331 | 5.0 2.2360679775 2.2360679775 0.0
332 |
333 | 6.0 2.44948974278 2.44948974278 0.0
334 |
335 | 7.0 2.64575131106 2.64575131106 0.0
336 |
337 | 8.0 2.82842712475 2.82842712475 4.4408920985e-16
338 |
339 | 9.0 3.0 3.0 0.0
340 |
341 | A primeira coluna é um número, a; a segunda coluna é a raiz quadrada de a calculada com mysqrt; a terceira coluna é a raiz quadrada calculada por math.sqrt; a quarta coluna é o valor absoluto da diferença entre as duas estimativas.
342 |
343 | Exercício 7.2
344 |
345 | A função integrada eval toma uma string e a avalia, usando o interpretador do Python. Por exemplo:
346 |
347 | >>> eval('1 + 2 \* 3')
348 |
349 | 7
350 |
351 | >>> import math
352 |
353 | >>> eval('math.sqrt(5)')
354 |
355 | 2.2360679774997898
356 |
357 | >>> eval('type(math.pi)')
358 |
359 | <class 'float'>
360 |
361 | Escreva uma função chamada eval\_loop que iterativamente peça uma entrada ao usuário, a avalie usando eval e imprima o resultado.
362 |
363 | Ela deve continuar até que o usuário digite 'done'; então deverá exibir o valor da última expressão avaliada.
364 |
365 | Exercício 7.3
366 |
367 | O matemático Srinivasa Ramanujan encontrou uma série infinita que pode ser usada para gerar uma aproximação numérica de 1/π:
368 |
369 | Escreva uma função chamada estimate\_pi que use esta fórmula para computar e devolver uma estimativa de π. Você deve usar o loop while para calcular os termos da adição até que o último termo seja menor que 1e-15 (que é a notação do Python para 10−15). Você pode verificar o resultado comparando-o com math.pi.
370 |
371 | Solução: http://thinkpython2.com/code/pi.py.
372 |
373 |
--------------------------------------------------------------------------------
/recebido/capitulos/09-caso-palavras.md:
--------------------------------------------------------------------------------
1 | # Capítulo 9: Estudo de caso: jogos de palavras
2 |
3 | Este capítulo apresenta o segundo estudo de caso que envolve solucionar quebra-cabeças usando palavras com certas propriedades. Por exemplo, encontraremos os palíndromos mais longos em inglês e procuraremos palavras cujas letras apareçam em ordem alfabética. E apresentarei outro plano de desenvolvimento de programa: a redução a um problema resolvido anteriormente.
4 |
5 | Leitura de listas de palavras
6 |
7 | Para os exercícios deste capítulo vamos usar uma lista de palavras em inglês. Há muitas listas de palavras disponíveis na internet, mas a mais conveniente ao nosso propósito é uma das listas de palavras disponibilizadas em domínio público por Grady Ward como parte do projeto lexical Moby (ver http://wikipedia.org/wiki/Moby\_Project). É uma lista de 113.809 palavras cruzadas oficiais; isto é, as palavras que se consideram válidas em quebra-cabeças de palavras cruzadas e outros jogos de palavras. Na coleção Moby, o nome do arquivo é 113809of.fic; você pode baixar uma cópia, com um nome mais simples como words.txt, de http://thinkpython2.com/code/words.txt.
8 |
9 | Este arquivo está em texto simples, então você pode abri-lo com um editor de texto, mas também pode lê-lo no Python. A função integrada open recebe o nome do arquivo como um parâmetro e retorna um objeto de arquivo que você pode usar para ler o arquivo.
10 |
11 | >>> fin = open('words.txt')
12 |
13 | fin é um nome comum de objeto de arquivo usado para entrada de dados. O objeto de arquivo oferece vários métodos de leitura, inclusive readline, que lê caracteres no arquivo até chegar a um comando de nova linha, devolvendo o resultado como uma string:
14 |
15 | >>> fin.readline()
16 |
17 | 'aa\\r\\n'
18 |
19 | A primeira palavra nesta lista específica é “aa”, uma espécie de lava. A sequência \\r\\n representa dois caracteres de whitespace, um retorno de carro e uma nova linha, que separa esta palavra da seguinte.
20 |
21 | O objeto de arquivo grava a posição em que está no arquivo, então se você chamar readline mais uma vez, receberá a seguinte palavra:
22 |
23 | >>> fin.readline()
24 |
25 | 'aah\\r\\n'
26 |
27 | A palavra seguinte é “aah”, uma palavra perfeitamente legítima, então pare de olhar para mim desse jeito. Ou, se é o whitespace que está incomodando você, podemos nos livrar dele com o método de string strip:
28 |
29 | >>> line = fin.readline()
30 |
31 | >>> word = line.strip()
32 |
33 | >>> word
34 |
35 | 'aahed'
36 |
37 | Você também pode usar um objeto de arquivo como parte de um loop for. Este programa lê words.txt e imprime cada palavra, uma por linha:
38 |
39 | fin = open('words.txt')
40 |
41 | for line in fin:
42 |
43 | word = line.strip()
44 |
45 | print(word)
46 |
47 | Exercícios
48 |
49 | Há soluções para estes exercícios na próxima seção. Mas é bom você tentar fazer cada um antes de ver as soluções.
50 |
51 | Exercício 9.1
52 |
53 | Escreva um programa que leia words.txt e imprima apenas as palavras com mais de 20 caracteres (sem contar whitespace).
54 |
55 | Exercício 9.2
56 |
57 | Em 1939, Ernest Vincent Wright publicou uma novela de 50.000 palavras, chamada Gadsby, que não contém a letra “e”. Como o “e” é a letra mais comum em inglês, isso não é algo fácil de fazer.
58 |
59 | Na verdade, é difícil até construir um único pensamento sem usar o símbolo mais comum do idioma. No início é lento, mas com prudência e horas de treino, vai ficando cada vez mais fácil.
60 |
61 | Muito bem, agora eu vou parar.
62 |
63 | Escreva uma função chamada has\_no\_e que retorne True se a palavra dada não tiver a letra “e” nela.
64 |
65 | Altere seu programa na seção anterior para imprimir apenas as palavras que não têm “e” e calcule a porcentagem de palavras na lista que não têm “e”.
66 |
67 | Exercício 9.3
68 |
69 | Escreva uma função chamada avoids que receba uma palavra e uma série de letras proibidas, e retorne True se a palavra não usar nenhuma das letras proibidas.
70 |
71 | Altere o código para que o usuário digite uma série de letras proibidas e o programa imprima o número de palavras que não contêm nenhuma delas. Você pode encontrar uma combinação de cinco letras proibidas que exclua o menor número possível de palavras?
72 |
73 | Exercício 9.4
74 |
75 | Escreva uma função chamada uses\_only que receba uma palavra e uma série de letras e retorne True, se a palavra só contiver letras da lista. Você pode fazer uma frase usando só as letras acefhlo? Que não seja “Hoe alfalfa?”
76 |
77 | Exercício 9.5
78 |
79 | Escreva uma função chamada uses\_all que receba uma palavra e uma série de letras obrigatórias e retorne True se a palavra usar todas as letras obrigatórias pelo menos uma vez. Quantas palavras usam todas as vogais (aeiou)? E que tal aeiouy?
80 |
81 | Exercício 9.6
82 |
83 | Escreva uma função chamada is\_abecedarian que retorne True se as letras numa palavra aparecerem em ordem alfabética (tudo bem se houver letras duplas). Quantas palavras em ordem alfabética existem?
84 |
85 | Busca
86 |
87 | Todos os exercícios na seção anterior têm algo em comum; eles podem ser resolvidos com o modelo de busca que vimos em “Buscando”, na página 123. O exemplo mais simples é:
88 |
89 | def has\_no\_e(word):
90 |
91 | for letter in word:
92 |
93 | if letter == 'e':
94 |
95 | return False
96 |
97 | return True
98 |
99 | O loop for atravessa os caracteres em word. Se encontrarmos a letra “e”, podemos retornar False imediatamente; se não for o caso, temos que ir à letra seguinte. Se sairmos do loop normalmente, isso quer dizer que não encontramos um “e”, então retornamos True.
100 |
101 | Você pode escrever esta função de forma mais concisa usando o operador in, mas comecei com esta versão porque ela demonstra a lógica do modelo de busca.
102 |
103 | avoids é uma versão mais geral de has\_no\_e, mas tem a mesma estrutura:
104 |
105 | def avoids(word, forbidden):
106 |
107 | for letter in word:
108 |
109 | if letter in forbidden:
110 |
111 | return False
112 |
113 | return True
114 |
115 | Podemos retornar False logo que encontrarmos uma letra proibida; se chegarmos ao fim do loop, retornamos True.
116 |
117 | uses\_only é semelhante, exceto pelo sentido da condição, que se inverte:
118 |
119 | def uses\_only(word, available):
120 |
121 | for letter in word:
122 |
123 | if letter not in available:
124 |
125 | return False
126 |
127 | return True
128 |
129 | Em vez de uma lista de letras proibidas, temos uma lista de letras disponíveis. Se encontrarmos uma letra em word que não está em available, podemos retornar False.
130 |
131 | uses\_all é semelhante, mas invertemos a função da palavra e a string de letras:
132 |
133 | def uses\_all(word, required):
134 |
135 | for letter in required:
136 |
137 | if letter not in word:
138 |
139 | return False
140 |
141 | return True
142 |
143 | Em vez de atravessar as letras em word, o loop atravessa as letras obrigatórias. Se alguma das letras obrigatórias não aparecer na palavra, podemos retornar False.
144 |
145 | Se você realmente pensasse como um cientista da computação, teria reconhecido que uses\_all foi um exemplo de um problema resolvido anteriormente e escreveria:
146 |
147 | def uses\_all(word, required):
148 |
149 | return uses\_only(required, word)
150 |
151 | Esse é um exemplo de um plano de desenvolvimento de programa chamado redução a um problema resolvido anteriormente, ou seja, você reconhece o problema no qual está trabalhando como um exemplo de um problema já resolvido e aplica uma solução existente.
152 |
153 | Loop com índices
154 |
155 | Escrevi as funções na seção anterior com loops for porque eu só precisava dos caracteres nas strings; não precisava fazer nada com os índices.
156 |
157 | Para is\_abecedarian temos que comparar letras adjacentes, o que é um pouco complicado para o loop for:
158 |
159 | def is\_abecedarian(word):
160 |
161 | previous = word\[0\]
162 |
163 | for c in word:
164 |
165 | if c < previous:
166 |
167 | return False
168 |
169 | previous = c
170 |
171 | return True
172 |
173 | Uma alternativa é usar a recursividade:
174 |
175 | def is\_abecedarian(word):
176 |
177 | if len(word) <= 1:
178 |
179 | return True
180 |
181 | if word\[0\] > word\[1\]:
182 |
183 | return False
184 |
185 | return is\_abecedarian(word\[1:\])
186 |
187 | Outra opção é usar um loop while:
188 |
189 | def is\_abecedarian(word):
190 |
191 | i = 0
192 |
193 | while i < len(word)-1:
194 |
195 | if word\[i+1\] < word\[i\]:
196 |
197 | return False
198 |
199 | i = i+1
200 |
201 | return True
202 |
203 | O loop começa em i=0 e termina quando i=len(word)-1. Cada vez que passa pelo loop, o programa compara o “i-ésimo” caractere (que você pode considerar o caractere atual) com o caractere de posição i+1(que pode ser considerado o caractere seguinte).
204 |
205 | Se o próximo caractere for de uma posição anterior (alfabeticamente anterior) à atual, então descobrimos uma quebra na tendência alfabética, e retornamos False.
206 |
207 | Se chegarmos ao fim do loop sem encontrar uma quebra, então a palavra passa no teste. Para convencer-se de que o loop termina corretamente, considere um exemplo como 'flossy'. O comprimento da palavra é 6, então o loop é executado pela última vez quando i for igual a 4, que é o índice do segundo caractere de trás para frente. Na última iteração, o programa compara o penúltimo caractere com o último, que é o que queremos.
208 |
209 | Aqui está uma versão de is\_palindrome (veja o Exercício 6.3) que usa dois índices: um começa no início e aumenta; o outro começa no final e diminui.
210 |
211 | def is\_palindrome(word):
212 |
213 | i = 0
214 |
215 | j = len(word)-1
216 |
217 | while i<j:
218 |
219 | if word\[i\] != word\[j\]:
220 |
221 | return False
222 |
223 | i = i+1
224 |
225 | j = j-1
226 |
227 | return True
228 |
229 | Ou podemos reduzir a um problema resolvido anteriormente e escrever:
230 |
231 | def is\_palindrome(word):
232 |
233 | return is\_reverse(word, word)
234 |
235 | Usando is\_reverse da Figura 8.2.
236 |
237 | Depuração
238 |
239 | Testar programas é difícil. As funções neste capítulo são relativamente fáceis para testar porque é possível verificar os resultados à mão. Ainda assim, pode ser difícil ou até impossível escolher um grupo de palavras que teste todos os erros possíveis.
240 |
241 | Tomando has\_no\_e como exemplo, há dois casos óbvios para verificar: as palavras que têm um ‘e’ devem retornar False, e as palavras que não têm devem retornar True. Não deverá ser um problema pensar em um exemplo de cada uma.
242 |
243 | Dentro de cada caso, há alguns subcasos menos óbvios. Entre as palavras que têm um “e”, você deve testar palavras com um “e” no começo, no fim e em algum lugar no meio. Você deve testar palavras longas, palavras curtas e palavras muito curtas, como a string vazia. A string vazia é um exemplo de um caso especial, não óbvio, onde erros muitas vezes espreitam.
244 |
245 | Além dos casos de teste que você gerar, também pode ser uma boa ideia testar seu programa com uma lista de palavras como words.txt. Ao analisar a saída, pode ser que os erros apareçam, mas tenha cuidado: você pode pegar um tipo de erro (palavras que não deveriam ser incluídas, mas foram) e não outro (palavras que deveriam ser incluídas, mas não foram).
246 |
247 | Em geral, o teste pode ajudar a encontrar bugs, mas não é fácil gerar um bom conjunto de casos de teste, e, mesmo se conseguir, não há como ter certeza de que o programa está correto. Segundo um lendário cientista da computação:
248 |
249 | Testar programas pode ser usado para mostrar a presença de bugs, mas nunca para mostrar a ausência deles! – Edsger W. Dijkstra
250 |
251 | Glossário
252 |
253 | objeto de arquivo:
254 |
255 | Um valor que representa um arquivo aberto.
256 |
257 | redução a um problema resolvido anteriormente:
258 |
259 | Um modo de resolver um problema expressando-o como uma instância de um problema resolvido anteriormente.
260 |
261 | caso especial:
262 |
263 | Um caso de teste que é atípico ou não é óbvio (e com probabilidade menor de ser tratado corretamente).
264 |
265 | Exercícios
266 |
267 | Exercício 9.7
268 |
269 | Esta pergunta é baseada em um quebra-cabeça veiculado em um programa de rádio chamado Car Talk (http://www.cartalk.com/content/puzzlers):
270 |
271 | Dê uma palavra com três letras duplas consecutivas. Vou dar exemplos de palavras que quase cumprem a condição, mas não chegam lá. Por exemplo, a palavra committee, c-o-m-m-i-t-t-e-e. Seria perfeita se não fosse aquele ‘i’ que se meteu ali no meio. Ou Mississippi: M-i-s-s-i-s-s-i-p-p-i. Se pudesse tirar aqueles ‘is’, daria certo. Mas há uma palavra que tem três pares consecutivos de letras e, que eu saiba, pode ser a única palavra que existe. É claro que provavelmente haja mais umas 500, mas só consigo pensar nessa. Qual é a palavra?
272 |
273 | Escreva um programa que a encontre.
274 |
275 | Solução: http://thinkpython2.com/code/cartalk1.py.
276 |
277 | Exercício 9.8
278 |
279 | Aqui está outro quebra-cabeça do programa Car Talk (http://www.cartalk.com/content/puzzlers):
280 |
281 | “Estava dirigindo outro dia e percebi algo no hodômetro que chamou a minha atenção. Como a maior parte dos hodômetros, ele mostra seis dígitos, apenas em milhas inteiras. Por exemplo, se o meu carro tivesse 300.000 milhas, eu veria 3-0-0-0-0-0.
282 |
283 | “Agora, o que vi naquele dia foi muito interessante. Notei que os últimos 4 dígitos eram um palíndromo; isto é, podiam ser lidos da mesma forma no sentido correto e no sentido inverso. Por exemplo, 5-4-4-5 é um palíndromo, então no meu hodômetro poderia ser 3-1-5-4-4-5.
284 |
285 | “Uma milha depois, os últimos 5 números formaram um palíndromo. Por exemplo, poderia ser 3-6-5-4-5-6. Uma milha depois disso, os 4 números do meio, dentro dos 6, formavam um palíndromo. E adivinhe só? Um milha depois, todos os 6 formavam um palíndromo!
286 |
287 | “A pergunta é: o que estava no hodômetro quando olhei primeiro?”
288 |
289 | Escreva um programa Python que teste todos os números de seis dígitos e imprima qualquer número que satisfaça essas condições.
290 |
291 | Solução: http://thinkpython2.com/code/cartalk2.py.
292 |
293 | Exercício 9.9
294 |
295 | Aqui está outro problema do Car Talk que você pode resolver com uma busca (http://www.cartalk.com/content/puzzlers):
296 |
297 | “Há pouco tempo recebi uma visita da minha mãe e percebemos que os dois dígitos que compõem a minha idade, quando invertidos, representavam a idade dela. Por exemplo, se ela tem 73 anos, eu tenho 37 anos. Ficamos imaginando com que frequência isto aconteceu nos anos anteriores, mas acabamos mudando de assunto e não chegamos a uma resposta.
298 |
299 | “Quando cheguei em casa, cheguei à conclusão de que os dígitos das nossas idades tinham sido reversíveis seis vezes até então. Também percebi que, se tivéssemos sorte, isso aconteceria novamente dali a alguns anos, e se fôssemos muito sortudos, aconteceria mais uma vez depois disso. Em outras palavras, aconteceria 8 vezes no total. Então a pergunta é: quantos anos tenho agora?”
300 |
301 | Escreva um programa em Python que busque soluções para esse problema. Dica: pode ser uma boa ideia usar o método de string zfill.
302 |
303 | Solução: http://thinkpython2.com/code/cartalk3.py.
304 |
305 |
--------------------------------------------------------------------------------
/recebido/capitulos/15-classes-objetos.md:
--------------------------------------------------------------------------------
1 | # Capítulo 15: Classes e objetos
2 |
3 | A esta altura você já sabe como usar funções para organizar código e tipos integrados para organizar dados. O próximo passo é aprender “programação orientada a objeto”, que usa tipos definidos pelos programadores para organizar tanto o código quanto os dados. A programação orientada a objeto é um tópico abrangente; será preciso passar por alguns capítulos para abordar o tema.
4 |
5 | Os exemplos de código deste capítulo estão disponíveis em http://thinkpython2.com/code/Point1.py; as soluções para os exercícios estão disponíveis em http://thinkpython2.com/code/Point1\_soln.py.
6 |
7 | Tipos definidos pelos programadores
8 |
9 | Já usamos muitos tipos integrados do Python; agora vamos definir um tipo próprio. Como exemplo, criaremos um tipo chamado Point, que representa um ponto no espaço bidimensional.
10 |
11 | Na notação matemática, os pontos muitas vezes são escritos entre parênteses, com uma vírgula separando as coordenadas. Por exemplo, (0,0) representa a origem e (x, y) representa o ponto que está x unidades à direita e y unidades a partir da origem.
12 |
13 | Há várias formas para representar pontos no Python:
14 |
15 | • Podemos armazenar as coordenadas separadamente em duas variáveis, x e y.
16 |
17 | • Podemos armazenar as coordenadas como elementos em uma lista ou tupla.
18 |
19 | • Podemos criar um tipo para representar pontos como objetos.
20 |
21 | Criar um tipo é mais complicado que outras opções, mas tem vantagens que logo ficarão evidentes.
22 |
23 | Um tipo definido pelo programador também é chamado de classe. Uma definição de classe pode ser assim:
24 |
25 | class Point:
26 |
27 | """Represents a point in 2-D space."""
28 |
29 | O cabeçalho indica que a nova classe se chama Point. O corpo é uma docstring que explica para que a classe serve. Você pode definir variáveis e métodos dentro de uma definição de classe, mas voltaremos a isso depois.
30 |
31 | Definir uma classe denominada Point cria um objeto de classe:
32 |
33 | >>> Point
34 |
35 | <class '\_\_main\_\_.Point'>
36 |
37 | Como Point é definido no nível superior, seu “nome completo” é \_\_main\_\_.Point.
38 |
39 | O objeto de classe é como uma fábrica para criar objetos. Para criar um Point, você chama Point como se fosse uma função:
40 |
41 | >>> blank = Point()
42 |
43 | >>> blank
44 |
45 | <\_\_main\_\_.Point object at 0xb7e9d3ac>
46 |
47 | O valor de retorno é uma referência a um objeto Point, ao qual atribuímos blank.
48 |
49 | Criar um objeto chama-se instanciação, e o objeto é uma instância da classe.
50 |
51 | Quando você exibe uma instância, o Python diz a que classe ela pertence e onde está armazenada na memória (o prefixo o 0x significa que o número seguinte está em formato hexadecimal).
52 |
53 | Cada objeto é uma instância de alguma classe, então “objeto” e “instância” são intercambiáveis. Porém, neste capítulo uso “instância” para indicar que estou falando sobre um tipo definido pelo programador.
54 |
55 | Atributos
56 |
57 | Você pode atribuir valores a uma instância usando a notação de ponto:
58 |
59 | >>> blank.x = 3.0
60 |
61 | >>> blank.y = 4.0
62 |
63 | Essa sintaxe é semelhante à usada para selecionar uma variável de um módulo, como math.pi ou string.whitespace. Nesse caso, entretanto, estamos atribuindo valores a elementos nomeados de um objeto. Esses elementos chamam-se atributos.
64 |
65 | Em inglês, quando é um substantivo, a palavra “AT-trib-ute” é pronunciada com ênfase na primeira sílaba, ao contrário de “a-TRIB-ute”, que é um verbo.
66 |
67 | O diagrama seguinte mostra o resultado dessas atribuições. Um diagrama de estado que mostra um objeto e seus atributos chama-se diagrama de objeto; veja a Figura 15.1.
68 |
69 | Figura 15.1 – Diagrama de objeto.
70 |
71 | A variável blank refere-se a um objeto Point, que contém dois atributos. Cada atributo refere-se a um número de ponto flutuante.
72 |
73 | Você pode ler o valor de um atributo usando a mesma sintaxe:
74 |
75 | >>> blank.y
76 |
77 | 4.0
78 |
79 | >>> x = blank.x
80 |
81 | >>> x
82 |
83 | 3.0
84 |
85 | A expressão blank.x significa “Ir ao objeto a que blank se refere e obter o valor de x”. No exemplo, atribuímos este valor a uma variável x. Não há nenhum conflito entre a variável x e o atributo x.
86 |
87 | Você pode usar a notação de ponto como parte de qualquer expressão. Por exemplo:
88 |
89 | >>> '(%g, %g)' % (blank.x, blank.y)
90 |
91 | '(3.0, 4.0)'
92 |
93 | >>> distance = math.sqrt(blank.x\*\*2 + blank.y\*\*2)
94 |
95 | >>> distance
96 |
97 | 5.0
98 |
99 | Você pode passar uma instância como argumento da forma habitual. Por exemplo:
100 |
101 | def print\_point(p):
102 |
103 | print('(%g, %g)' % (p.x, p.y))
104 |
105 | print\_point toma um ponto como argumento e o exibe em notação matemática. Para invocá-lo, você pode passar blank como argumento:
106 |
107 | >>> print\_point(blank)
108 |
109 | (3.0, 4.0)
110 |
111 | Dentro da função, p é um alias para blank, então, se a função altera p, blank também muda.
112 |
113 | Como exercício, escreva uma função chamada distance\_between\_points, que toma dois pontos como argumentos e retorna a distância entre eles.
114 |
115 | Retângulos
116 |
117 | Às vezes, é óbvio quais deveriam ser os atributos de um objeto, mas outras é preciso decidir entre as possibilidades. Por exemplo, vamos supor que você esteja criando uma classe para representar retângulos. Que atributos usaria para especificar a posição e o tamanho de um retângulo? Você pode ignorar ângulo; para manter as coisas simples, suponha que o retângulo seja vertical ou horizontal.
118 |
119 | Há duas possibilidades, no mínimo:
120 |
121 | • Você pode especificar um canto do retângulo (ou o centro), a largura e a altura.
122 |
123 | • Você pode especificar dois cantos opostos.
124 |
125 | Nesse ponto é difícil dizer qual opção é melhor, então implementaremos a primeira, como exemplo.
126 |
127 | Aqui está a definição de classe:
128 |
129 | class Rectangle:
130 |
131 | """Represents a rectangle.
132 |
133 | attributes: width, height, corner.
134 |
135 | """
136 |
137 | A docstring lista os atributos: width e height são números; corner é um objeto Point que especifica o canto inferior esquerdo.
138 |
139 | Para representar um retângulo, você tem que instanciar um objeto Rectangle e atribuir valores aos atributos:
140 |
141 | box = Rectangle()
142 |
143 | box.width = 100.0
144 |
145 | box.height = 200.0
146 |
147 | box.corner = Point()
148 |
149 | box.corner.x = 0.0
150 |
151 | box.corner.y = 0.0
152 |
153 | A expressão box.corner.x significa “Vá ao objeto ao qual box se refere e selecione o atributo denominado corner; então vá a este objeto e selecione o atributo denominado x”.
154 |
155 | A Figura 15.2 mostra o estado deste objeto. Um objeto que é um atributo de outro objeto é integrado.
156 |
157 | Figura 15.2 – Diagrama de objeto.
158 |
159 | Instâncias como valores de retorno
160 |
161 | As funções podem retornar instâncias. Por exemplo, find\_center recebe Rectangle como argumento e retorna Point, que contém as coordenadas do centro de Rectangle:
162 |
163 | def find\_center(rect):
164 |
165 | p = Point()
166 |
167 | p.x = rect.corner.x + rect.width/2
168 |
169 | p.y = rect.corner.y + rect.height/2
170 |
171 | return p
172 |
173 | Aqui está um exemplo que passa box como um argumento e atribui o ponto resultante a center:
174 |
175 | >>> center = find\_center(box)
176 |
177 | >>> print\_point(center)
178 |
179 | (50, 100)
180 |
181 | Objetos são mutáveis
182 |
183 | Você pode alterar o estado de um objeto fazendo uma atribuição a um dos seus atributos. Por exemplo, para mudar o tamanho de um retângulo sem mudar sua posição, você pode alterar os valores de width e height:
184 |
185 | box.width = box.width + 50
186 |
187 | box.height = box.height + 100
188 |
189 | Você também pode escrever funções que alteram objetos. Por exemplo, grow\_rectangle recebe um objeto Rectangle e dois números, dwidth e dheight, e adiciona os números à largura e altura do retângulo:
190 |
191 | def grow\_rectangle(rect, dwidth, dheight):
192 |
193 | rect.width += dwidth
194 |
195 | rect.height += dheight
196 |
197 | Aqui está um exemplo que demonstra o efeito:
198 |
199 | >>> box.width, box.height
200 |
201 | (150.0, 300.0)
202 |
203 | >>> grow\_rectangle(box, 50, 100)
204 |
205 | >>> box.width, box.height
206 |
207 | (200.0, 400.0)
208 |
209 | Dentro da função, rect é um alias de box, então quando a função altera rect, box também muda.
210 |
211 | Como exercício, escreva uma função chamada move\_rectangle que toma um Rectangle e dois números chamados dx e dy. Ela deve alterar a posição do retângulo, adicionando dx à coordenada x de corner e adicionando dy à coordenada y de corner.
212 |
213 | Cópia
214 |
215 | Alias podem tornar um programa difícil de ler porque as alterações em um lugar podem ter efeitos inesperados em outro lugar. É difícil monitorar todas as variáveis que podem referir-se a um dado objeto.
216 |
217 | Em vez de usar alias, copiar o objeto pode ser uma alternativa. O módulo copy contém uma função chamada copy que pode duplicar qualquer objeto:
218 |
219 | >>> p1 = Point()
220 |
221 | >>> p1.x = 3.0
222 |
223 | >>> p1.y = 4.0
224 |
225 | >>> import copy
226 |
227 | >>> p2 = copy.copy(p1)
228 |
229 | p1 e p2 contêm os mesmos dados, mas não são o mesmo Point:
230 |
231 | >>> print\_point(p1)
232 |
233 | (3, 4)
234 |
235 | >>> print\_point(p2)
236 |
237 | (3, 4)
238 |
239 | >>> p1 is p2
240 |
241 | False
242 |
243 | >>> p1 == p2
244 |
245 | False
246 |
247 | O operador is indica que p1 e p2 não são o mesmo objeto, que é o que esperamos. Porém, você poderia ter esperado que == fosse apresentado como True, porque esses pontos contêm os mesmos dados. Nesse caso, pode ficar desapontado ao saber que, para instâncias, o comportamento-padrão do operador == é o mesmo que o do operador is; ele verifica a identidade dos objetos, não a sua equivalência. Isso acontece porque, para tipos definidos pelo programador, o Python não sabe o que deve ser considerado equivalente. Pelo menos, ainda não.
248 |
249 | Se você usar copy.copy para duplicar um retângulo, descobrirá que ele copia o objeto Rectangle, mas não o Point integrado:
250 |
251 | >>> box2 = copy.copy(box)
252 |
253 | >>> box2 is box
254 |
255 | False
256 |
257 | >>> box2.corner is box.corner
258 |
259 | True
260 |
261 | A Figura 15.3 mostra como fica o diagrama de objeto. Esta operação chama-se cópia superficial porque copia o objeto e qualquer referência que contenha, mas não os objetos integrados.
262 |
263 | Figura 15.3 – Diagrama de objeto.
264 |
265 | Para a maior parte das aplicações, não é isso que você quer. Nesse exemplo, invocar grow\_rectangle em um dos Rectangles não afetaria o outro, mas invocar move\_rectangle em qualquer um deles afetaria a ambos! Esse comportamento é confuso e propenso a erros.
266 |
267 | Felizmente, o módulo copy oferece um método chamado deepcopy que copia não só o objeto, mas também os objetos aos quais ele se refere, e os objetos aos quais estes se referem, e assim por diante. Você não se surpreenderá ao descobrir que esta operação se chama cópia profunda.
268 |
269 | >>> box3 = copy.deepcopy(box)
270 |
271 | >>> box3 is box
272 |
273 | False
274 |
275 | >>> box3.corner is box.corner
276 |
277 | False
278 |
279 | box3 e box são objetos completamente separados.
280 |
281 | Como exercício, escreva uma versão de move\_rectangle que cria e retorne um novo retângulo em vez de alterar o antigo.
282 |
283 | Depuração
284 |
285 | Ao começar a trabalhar com objetos, provavelmente você encontrará algumas novas exceções. Se tentar acessar um atributo que não existe, recebe um AttributeError:
286 |
287 | >>> p = Point()
288 |
289 | >>> p.x = 3
290 |
291 | >>> p.y = 4
292 |
293 | >>> p.z
294 |
295 | AttributeError: Point instance has no attribute 'z'
296 |
297 | Se não estiver certo sobre o tipo que um objeto é, pode perguntar:
298 |
299 | >>> type(p)
300 |
301 | <class '\_\_main\_\_.Point'>
302 |
303 | Você também pode usar isinstance para verificar se um objeto é uma instância de uma classe:
304 |
305 | >>> isinstance(p, Point)
306 |
307 | True
308 |
309 | Caso não tenha certeza se um objeto tem determinado atributo, você pode usar a função integrada hasattr:
310 |
311 | >>> hasattr(p, 'x')
312 |
313 | True
314 |
315 | >>> hasattr(p, 'z')
316 |
317 | False
318 |
319 | O primeiro argumento pode ser qualquer objeto; o segundo argumento é uma string que contém o nome do atributo.
320 |
321 | Você também pode usar uma instrução try para ver se o objeto tem os atributos de que precisa:
322 |
323 | try:
324 |
325 | x = p.x
326 |
327 | except AttributeError:
328 |
329 | x = 0
330 |
331 | Essa abordagem pode facilitar a escrita de funções que atuam com tipos diferentes; você verá mais informações sobre isso em “Polimorfismo”, na página 248.
332 |
333 | Glossário
334 |
335 | classe:
336 |
337 | Tipo definido pelo programador. Uma definição de classe cria um objeto de classe.
338 |
339 | objeto de classe:
340 |
341 | Objeto que contém a informação sobre um tipo definido pelo programador. O objeto de classe pode ser usado para criar instâncias do tipo.
342 |
343 | instância:
344 |
345 | Objeto que pertence a uma classe.
346 |
347 | instanciar:
348 |
349 | Criar um objeto.
350 |
351 | atributo:
352 |
353 | Um dos valores denominados associados a um objeto.
354 |
355 | objeto integrado:
356 |
357 | Objeto que é armazenado como um atributo de outro objeto.
358 |
359 | cópia superficial:
360 |
361 | Copiar o conteúdo de um objeto, inclusive qualquer referência a objetos integrados; implementada pela função copy no módulo copy.
362 |
363 | cópia profunda:
364 |
365 | Copiar o conteúdo de um objeto, bem como qualquer objeto integrado, e qualquer objeto integrado a estes, e assim por diante; implementado pela função deepcopy no módulo copy.
366 |
367 | diagrama de objeto:
368 |
369 | Diagrama que mostra objetos, seus atributos e os valores dos atributos.
370 |
371 | Exercícios
372 |
373 | Exercício 15.1
374 |
375 | Escreva uma definição para uma classe denominada Circle, com os atributos center e radius, onde center é um objeto Point e radius é um número.
376 |
377 | Instancie um objeto Circle, que represente um círculo com o centro em 150, 100 e raio 75.
378 |
379 | Escreva uma função denominada point\_in\_circle, que tome um Circle e um Point e retorne True, se o ponto estiver dentro ou no limite do círculo.
380 |
381 | Escreva uma função chamada rect\_in\_circle, que tome um Circle e um Rectangle e retorne True, se o retângulo estiver totalmente dentro ou no limite do círculo.
382 |
383 | Escreva uma função denominada rect\_circle\_overlap, que tome um Circle e um Rectangle e retorne True, se algum dos cantos do retângulo cair dentro do círculo. Ou, em uma versão mais desafiadora, retorne True se alguma parte do retângulo cair dentro do círculo.
384 |
385 | Solução: http://thinkpython2.com/code/Circle.py.
386 |
387 | Exercício 15.2
388 |
389 | Escreva uma função chamada draw\_rect que receba um objeto Turtle e um Rectangle e use o Turtle para desenhar o retângulo. Veja no Capítulo 4 os exemplos de uso de objetos Turtle.
390 |
391 | Escreva uma função chamada draw\_circle, que tome um Turtle e um Circle e desenhe o círculo.
392 |
393 | Solução: http://thinkpython2.com/code/draw.py.
394 |
395 |
--------------------------------------------------------------------------------
/recebido/capitulos/16-classes-funcoes.md:
--------------------------------------------------------------------------------
1 | # Capítulo 16: Classes e funções
2 |
3 | Agora que sabemos como criar tipos, o próximo passo deve ser escrever funções que recebam objetos definidos pelo programador como parâmetros e os retornem como resultados. Neste capítulo também vou apresentar o “estilo funcional de programação” e dois novos planos de desenvolvimento de programas.
4 |
5 | Os exemplos de código deste capítulo estão disponíveis em http://thinkpython2.com/code/Time1.py. As soluções para os exercícios estão em http://thinkpython2.com/code/Time1\_soln.py.
6 |
7 | Time
8 |
9 | Para ter mais um exemplo de tipo definido pelo programador, criaremos uma classe chamada Time, que registra o período do dia. A definição da classe é assim:
10 |
11 | class Time:
12 |
13 | """Represents the time of day.
14 |
15 | attributes: hour, minute, second
16 |
17 | """
18 |
19 | Podemos criar um objeto Time e ter atributos para horas, minutos e segundos:
20 |
21 | time = Time()
22 |
23 | time.hour = 11
24 |
25 | time.minute = 59
26 |
27 | time.second = 30
28 |
29 | O diagrama de estado do objeto Time está na Figura 16.1.
30 |
31 | Como exercício, escreva uma função chamada print\_time, que receba um objeto Time e o exiba na forma hour:minute:second. Dica: a sequência de formatação '%.2d' exibe um número inteiro com, pelo menos, dois dígitos, incluindo um zero à esquerda, se for necessário.
32 |
33 | Escreva uma função booleana chamada is\_after, que receba dois objetos Time, t1 e t2, e retorne True se t1 for seguido por t2 cronologicamente e False se não for. Desafio: não use uma instrução if.
34 |
35 | Figura 16.1 – Diagrama de objeto.
36 |
37 | Funções puras
38 |
39 | Nas próximas seções, vamos escrever duas funções que adicionam valores de tempo. Elas demonstram dois tipos de funções: funções puras e modificadores. Também demonstram um plano de desenvolvimento que chamarei de protótipo e correção, que é uma forma de atacar um problema complexo começando com um protótipo simples e lidando com as complicações de forma incremental.
40 |
41 | Aqui está um protótipo simples de add\_time:
42 |
43 | def add\_time(t1, t2):
44 |
45 | sum = Time()
46 |
47 | sum.hour = t1.hour + t2.hour
48 |
49 | sum.minute = t1.minute + t2.minute
50 |
51 | sum.second = t1.second + t2.second
52 |
53 | return sum
54 |
55 | A função cria um novo objeto Time, inicializa seus atributos e retorna uma referência ao novo objeto. A função pura é chamada assim porque não altera nenhum dos objetos passados a ela como argumentos; além disso, ela não tem efeitos, como exibir um valor ou receber entradas de usuário, apenas retorna um valor.
56 |
57 | Para testar esta função, criarei objetos Time: start, que contém o tempo de início de um filme, como Monty Python e o cálice sagrado, e duration, que contém o tempo de execução do filme, que é de 1 hora e 35 minutos.
58 |
59 | add\_time calcula quando o filme acaba:
60 |
61 | >>> start = Time()
62 |
63 | >>> start.hour = 9
64 |
65 | >>> start.minute = 45
66 |
67 | >>> start.second = 0
68 |
69 | >>> duration = Time()
70 |
71 | >>> duration.hour = 1
72 |
73 | >>> duration.minute = 35
74 |
75 | >>> duration.second = 0
76 |
77 | >>> done = add\_time(start, duration)
78 |
79 | >>> print\_time(done)
80 |
81 | 10:80:00
82 |
83 | O resultado, 10:80:00, pode não ser o que você esperava. O problema é que esta função não trata casos onde o número de segundos ou minutos é maior que 60. Quando isso acontece, precisamos “transportar” os segundos extras à coluna dos minutos ou os minutos extras à coluna das horas.
84 |
85 | Aqui está uma versão melhorada:
86 |
87 | def add\_time(t1, t2):
88 |
89 | sum = Time()
90 |
91 | sum.hour = t1.hour + t2.hour
92 |
93 | sum.minute = t1.minute + t2.minute
94 |
95 | sum.second = t1.second + t2.second
96 |
97 | if sum.second >= 60:
98 |
99 | sum.second -= 60
100 |
101 | sum.minute += 1
102 |
103 | if sum.minute >= 60:
104 |
105 | sum.minute -= 60
106 |
107 | sum.hour += 1
108 |
109 | return sum
110 |
111 | Embora esta função esteja correta, é um pouco extensa. Veremos uma alternativa menor mais adiante.
112 |
113 | Modificadores
114 |
115 | Às vezes é útil uma função alterar os objetos que recebe como parâmetros. Nesse caso, as mudanças são visíveis a quem chama a função. As funções que fazem isso chamam-se modificadores.
116 |
117 | increment, que acrescenta um dado número de segundos a um objeto Time, pode ser escrita naturalmente como um modificador. Aqui está um primeiro esboço:
118 |
119 | def increment(time, seconds):
120 |
121 | time.second += seconds
122 |
123 | if time.second >= 60:
124 |
125 | time.second -= 60
126 |
127 | time.minute += 1
128 |
129 | if time.minute >= 60:
130 |
131 | time.minute -= 60
132 |
133 | time.hour += 1
134 |
135 | A primeira linha executa a operação básica; o resto lida com os casos especiais que vimos antes.
136 |
137 | Esta função está correta? O que acontece se second for muito mais que 60?
138 |
139 | Neste caso não basta transportar uma vez, temos que continuar fazendo isso até que time.second seja menos de 60. Uma solução é substituir a instrução if pela instrução while. Isso tornaria a função correta, mas não muito eficiente. Como exercício, escreva uma versão correta de increment que não contenha loops.
140 |
141 | O que se faz com modificadores também pode ser feito com funções puras. Na verdade, algumas linguagens de programação só permitem funções puras. Há evidências de que os programas que usam funções puras são mais rápidos para serem desenvolvidos e menos propensos a erros que programas que usam modificadores. No entanto, modificadores são convenientes de vez em quando, e os programas funcionais tendem a ser menos eficientes.
142 |
143 | De forma geral, recomendo que você escreva funções puras sempre que achar razoável e recorra a modificadores só se houver alguma vantagem clara. Esta abordagem pode ser chamada de estilo funcional de programação.
144 |
145 | Como exercício, escreva uma versão “pura” de increment que cria e retorna um objeto Time em vez de alterar o parâmetro.
146 |
147 | Prototipação versus planejamento
148 |
149 | O plano de desenvolvimento que estou demonstrando chama-se “protótipo e correção”. Para cada função, escrevi um protótipo que executa o cálculo básico e então testa a função, corrigindo erros no decorrer do caminho.
150 |
151 | Esta abordagem pode ser eficaz, especialmente se você ainda não tem uma compreensão profunda do problema. Porém, as correções incrementais podem gerar código que se complica desnecessariamente (pois trata de muitos casos especiais) e pouco confiáveis (já que é difícil saber se todos os erros foram encontrados).
152 |
153 | Uma alternativa é o desenvolvimento planejado, no qual a compreensão de alto nível do problema pode facilitar muito a programação. Neste caso, descobre-se que um objeto Time é, na verdade, um número de três dígitos na base 60 (veja http://en.wikipedia.org/wiki/Sexagesimal)! O atributo second é a “coluna de unidades”, o atributo minute é a “coluna dos 60”, e o atributo hour é a “coluna do 3.600”.
154 |
155 | Quando escrevemos add\_time e increment, estávamos na verdade fazendo adições na base 60, e por isso transportávamos os resultados de uma coluna à seguinte.
156 |
157 | Essa observação sugere outra abordagem para o problema inteiro – podemos converter objetos Time em números inteiros e aproveitar o fato de que o computador sabe trabalhar com aritmética de números inteiros.
158 |
159 | Aqui está uma função que converte objetos Time em números inteiros:
160 |
161 | def time\_to\_int(time):
162 |
163 | minutes = time.hour \* 60 + time.minute
164 |
165 | seconds = minutes \* 60 + time.second
166 |
167 | return seconds
168 |
169 | E aqui está uma função que converte um número inteiro em um Time (lembre-se de que divmod divide o primeiro argumento pelo segundo e devolve o quociente e o resto como uma tupla):
170 |
171 | def int\_to\_time(seconds):
172 |
173 | time = Time()
174 |
175 | minutes, time.second = divmod(seconds, 60)
176 |
177 | time.hour, time.minute = divmod(minutes, 60)
178 |
179 | return time
180 |
181 | Você pode ter que pensar um pouco e fazer alguns testes, para se convencer de que essas funções estão corretas. Um modo de testá-las é ver se time\_to\_int (int\_to\_time (x)) == x para muitos valores de x. Este é um exemplo de uma verificação de consistência.
182 |
183 | Uma vez que esteja convencido de que estão corretas, você pode usá-las para reescrever add\_time:
184 |
185 | def add\_time(t1, t2):
186 |
187 | seconds = time\_to\_int(t1) + time\_to\_int(t2)
188 |
189 | return int\_to\_time(seconds)
190 |
191 | Esta versão é mais curta que a original, e mais fácil de verificar. Como exercício, reescreva increment usando time\_to\_int e int\_to\_time.
192 |
193 | Em algumas situações, converter da base 60 para a base 10 e de volta é mais difícil que apenas lidar com as horas. A conversão de base é mais abstrata; nossa intuição para lidar com valores temporais é melhor.
194 |
195 | No entanto, se tivermos discernimento para lidar com horas como números de base 60 e investirmos esforço em escrever as funções de conversão (time\_to\_int e int\_to\_time), chegamos a um programa que é mais curto, mais fácil de ler e depurar, e mais confiável.
196 |
197 | Também é mais fácil acrescentar recursos depois. Por exemplo, imagine subtrair dois objetos Time para encontrar a duração entre eles. Uma abordagem ingênua seria implementar a subtração com transporte. Porém, usar funções de conversão seria mais fácil e, provavelmente, mais correto.
198 |
199 | Ironicamente, tornar um problema mais difícil (ou mais geral) facilita (porque há menos casos especiais e menos oportunidades de erro).
200 |
201 | Depuração
202 |
203 | Um objeto Time é bem formado se os valores de minute e second estiverem entre 0 e 60 (incluindo 0, mas não 60) e se hour for positivo. hour e minute devem ser valores integrais, mas podemos permitir que second tenha uma parte fracionária.
204 |
205 | Requisitos como esses chamam-se invariáveis porque sempre devem ser verdadeiros. Para dizer de outra forma, se não forem verdadeiros, algo deu errado.
206 |
207 | Escrever código para verificar requisitos invariáveis pode ajudar a descobrir erros e encontrar suas causas. Por exemplo, você pode ter uma função como valid\_time, que receba um objeto Time e retorne False se ele violar um requisito invariável:
208 |
209 | def valid\_time(time):
210 |
211 | if time.hour < 0 or time.minute < 0 or time.second < 0:
212 |
213 | return False
214 |
215 | if time.minute >= 60 or time.second >= 60:
216 |
217 | return False
218 |
219 | return True
220 |
221 | No início de cada função você pode verificar os argumentos para ter certeza de que são válidos:
222 |
223 | def add\_time(t1, t2):
224 |
225 | if not valid\_time(t1) or not valid\_time(t2):
226 |
227 | raise ValueError('invalid Time object in add\_time')
228 |
229 | seconds = time\_to\_int(t1) + time\_to\_int(t2)
230 |
231 | return int\_to\_time(seconds)
232 |
233 | Ou você pode usar uma instrução assert, que verifica determinado requisito invariável e cria uma exceção se ela falhar:
234 |
235 | def add\_time(t1, t2):
236 |
237 | assert valid\_time(t1) and valid\_time(t2)
238 |
239 | seconds = time\_to\_int(t1) + time\_to\_int(t2)
240 |
241 | return int\_to\_time(seconds)
242 |
243 | Instruções assert são úteis porque distinguem o código que lida com condições normais do código que verifica erros.
244 |
245 | Glossário
246 |
247 | protótipo e correção:
248 |
249 | Plano de desenvolvimento no qual a escrita do programa parte de um esboço inicial, e depois segue ao teste e correção de erros, conforme sejam encontrados.
250 |
251 | desenvolvimento planejado:
252 |
253 | Plano de desenvolvimento que implica uma compreensão de alto nível do problema e mais planejamento que desenvolvimento incremental ou desenvolvimento prototipado.
254 |
255 | função pura:
256 |
257 | Função que não altera nenhum dos objetos que recebe como argumento. A maior parte das funções puras gera resultado.
258 |
259 | modificador:
260 |
261 | Função que modifica um ou vários dos objetos que recebe como argumento. A maior parte dos modificadores são nulos; isto é, retornam None.
262 |
263 | estilo funcional de programação:
264 |
265 | Estilo de projeto de programa no qual a maioria das funções são puras.
266 |
267 | invariável:
268 |
269 | Condição que sempre deve ser verdadeira durante a execução de um programa.
270 |
271 | instrução assert:
272 |
273 | Instrução que verifica uma condição e levanta uma exceção se esta falhar.
274 |
275 | Exercícios
276 |
277 | Os exemplos de código deste capítulo estão disponíveis em http://thinkpython2.com/code/Time1.py; as soluções para os exercícios estão disponíveis em http://thinkpython2.com/code/Time1\_soln.py.
278 |
279 | Exercício 16.1
280 |
281 | Escreva uma função chamada mul\_time que receba um objeto Time e um número e retorne um novo objeto Time que contenha o produto do Time original e do número.
282 |
283 | Então use mul\_time para escrever uma função que receba um objeto Time representando o tempo até o fim de uma corrida e um número que represente a distância, e retorne um objeto Time com o passo médio (tempo por milha).
284 |
285 | Exercício 16.2
286 |
287 | O módulo datetime fornece objetos time que são semelhantes aos objetos Time deste capítulo, mas ele oferece um grande conjunto de métodos e operadores. Leia a documentação em http://docs.python.org/3/library/datetime.html.
288 |
289 | 1. Use o módulo datetime para escrever um programa que receba a data atual e exiba o dia da semana.
290 |
291 | 2. Escreva um programa que receba um aniversário como entrada e exiba a idade do usuário e o número de dias, horas, minutos e segundos até o seu próximo aniversário.
292 |
293 | 3. Para duas pessoas nascidas em dias diferentes, há um dia em que a idade de uma equivale a duas vezes a da outra. Este é o Dia Duplo delas. Escreva um programa que receba dois aniversários e calcule o Dia Duplo dos aniversariantes.
294 |
295 | 4. Para um desafio um pouco maior, escreva a versão mais geral que calcule o dia em que uma pessoa é n vezes mais velha que a outra.
296 |
297 | Solução: http://thinkpython2.com/code/double.py.
298 |
299 |
--------------------------------------------------------------------------------
/recebido/figuras/p19f1.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/p19f1.pdf
--------------------------------------------------------------------------------
/recebido/figuras/p242f1.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/p242f1.pdf
--------------------------------------------------------------------------------
/recebido/figuras/p63f1.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/p63f1.pdf
--------------------------------------------------------------------------------
/recebido/figuras/p72f1.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/p72f1.pdf
--------------------------------------------------------------------------------
/recebido/figuras/p79f1.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/p79f1.pdf
--------------------------------------------------------------------------------
/recebido/figuras/p79f2.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/p79f2.pdf
--------------------------------------------------------------------------------
/recebido/figuras/p80f1.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/p80f1.pdf
--------------------------------------------------------------------------------
/recebido/figuras/p83f1.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/p83f1.pdf
--------------------------------------------------------------------------------
/recebido/figuras/tnkp_0201.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/tnkp_0201.ai
--------------------------------------------------------------------------------
/recebido/figuras/tnkp_0301.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/tnkp_0301.ai
--------------------------------------------------------------------------------
/recebido/figuras/tnkp_0401.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/tnkp_0401.ai
--------------------------------------------------------------------------------
/recebido/figuras/tnkp_0402.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/tnkp_0402.ai
--------------------------------------------------------------------------------
/recebido/figuras/tnkp_0501.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/tnkp_0501.ai
--------------------------------------------------------------------------------
/recebido/figuras/tnkp_0502.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/tnkp_0502.ai
--------------------------------------------------------------------------------
/recebido/figuras/tnkp_0601.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/tnkp_0601.ai
--------------------------------------------------------------------------------
/recebido/figuras/tnkp_0701.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/tnkp_0701.ai
--------------------------------------------------------------------------------
/recebido/figuras/tnkp_0801.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/tnkp_0801.ai
--------------------------------------------------------------------------------
/recebido/figuras/tnkp_0802.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/tnkp_0802.ai
--------------------------------------------------------------------------------
/recebido/figuras/tnkp_1001.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/tnkp_1001.ai
--------------------------------------------------------------------------------
/recebido/figuras/tnkp_1002.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/tnkp_1002.ai
--------------------------------------------------------------------------------
/recebido/figuras/tnkp_1003.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/tnkp_1003.ai
--------------------------------------------------------------------------------
/recebido/figuras/tnkp_1004.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/tnkp_1004.ai
--------------------------------------------------------------------------------
/recebido/figuras/tnkp_1005.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/tnkp_1005.ai
--------------------------------------------------------------------------------
/recebido/figuras/tnkp_1101.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/tnkp_1101.ai
--------------------------------------------------------------------------------
/recebido/figuras/tnkp_1102.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/tnkp_1102.ai
--------------------------------------------------------------------------------
/recebido/figuras/tnkp_1201.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/tnkp_1201.ai
--------------------------------------------------------------------------------
/recebido/figuras/tnkp_1202.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/tnkp_1202.ai
--------------------------------------------------------------------------------
/recebido/figuras/tnkp_1501.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/tnkp_1501.ai
--------------------------------------------------------------------------------
/recebido/figuras/tnkp_1502.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/tnkp_1502.ai
--------------------------------------------------------------------------------
/recebido/figuras/tnkp_1503.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/tnkp_1503.ai
--------------------------------------------------------------------------------
/recebido/figuras/tnkp_1601.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/tnkp_1601.ai
--------------------------------------------------------------------------------
/recebido/figuras/tnkp_1801.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/tnkp_1801.ai
--------------------------------------------------------------------------------
/recebido/figuras/tnkp_1802.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/tnkp_1802.ai
--------------------------------------------------------------------------------
/recebido/figuras/tnkp_2101.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/figuras/tnkp_2101.ai
--------------------------------------------------------------------------------
/recebido/sumario.md:
--------------------------------------------------------------------------------
1 | # Sumário
2 |
3 | Prefácio 13
4 |
5 | Capítulo 1 ■ A jornada do programa 25
6 |
7 | O que é um programa? 25
8 |
9 | Execução do Python 26
10 |
11 | O primeiro programa 27
12 |
13 | Operadores aritméticos 28
14 |
15 | Valores e tipos 29
16 |
17 | Linguagens formais e naturais 30
18 |
19 | Depuração 32
20 |
21 | Glossário 33
22 |
23 | Exercícios 35
24 |
25 | Capítulo 2 ■ Variáveis, expressões e instruções 37
26 |
27 | Instruções de atribuição 37
28 |
29 | Nomes de variáveis 38
30 |
31 | Expressões e instruções 39
32 |
33 | Modo script 39
34 |
35 | Ordem das operações 41
36 |
37 | Operações com strings 41
38 |
39 | Comentários 42
40 |
41 | Depuração 43
42 |
43 | Glossário 44
44 |
45 | Exercícios 46
46 |
47 | Capítulo 3 ■ Funções 47
48 |
49 | Chamada de função 47
50 |
51 | Funções matemáticas 48
52 |
53 | Composição 49
54 |
55 | Como acrescentar novas funções 50
56 |
57 | Uso e definições 51
58 |
59 | Fluxo de execução 52
60 |
61 | Parâmetros e argumentos 53
62 |
63 | As variáveis e os parâmetros são locais 54
64 |
65 | Diagrama da pilha 55
66 |
67 | Funções com resultado e funções nulas 56
68 |
69 | Por que funções? 57
70 |
71 | Depuração 57
72 |
73 | Glossário 58
74 |
75 | Exercícios 60
76 |
77 | Capítulo 4 ■ Estudo de caso: projeto de interface 63
78 |
79 | Módulo turtle 63
80 |
81 | Repetição simples 65
82 |
83 | Exercícios 66
84 |
85 | Encapsulamento 67
86 |
87 | Generalização 67
88 |
89 | Projeto da interface 68
90 |
91 | Refatoração 70
92 |
93 | Um plano de desenvolvimento 71
94 |
95 | docstring 71
96 |
97 | Depuração 72
98 |
99 | Glossário 73
100 |
101 | Exercícios 74
102 |
103 | Capítulo 5 ■ Condicionais e recursividade 76
104 |
105 | Divisão pelo piso e módulo 76
106 |
107 | Expressões booleanas 77
108 |
109 | Operadores lógicos 78
110 |
111 | Execução condicional 78
112 |
113 | Execução alternativa 79
114 |
115 | Condicionais encadeadas 79
116 |
117 | Condicionais aninhadas 80
118 |
119 | Recursividade 81
120 |
121 | Diagramas da pilha para funções recursivas 83
122 |
123 | Recursividade infinita 83
124 |
125 | Entrada de teclado 84
126 |
127 | Depuração 85
128 |
129 | Glossário 87
130 |
131 | Exercícios 88
132 |
133 | Capítulo 6 ■ Funções com resultado 92
134 |
135 | Valores de retorno 92
136 |
137 | Desenvolvimento incremental 94
138 |
139 | Composição 96
140 |
141 | Funções booleanas 97
142 |
143 | Mais recursividade 98
144 |
145 | Salto de fé 100
146 |
147 | Mais um exemplo 101
148 |
149 | Verificação de tipos 101
150 |
151 | Depuração 103
152 |
153 | Glossário 104
154 |
155 | Exercícios 105
156 |
157 | Capítulo 7 ■ Iteração 107
158 |
159 | Reatribuição 107
160 |
161 | Atualização de variáveis 108
162 |
163 | Instrução while 109
164 |
165 | break 110
166 |
167 | Raízes quadradas 111
168 |
169 | Algoritmos 113
170 |
171 | Depuração 114
172 |
173 | Glossário 115
174 |
175 | Exercícios 115
176 |
177 | Capítulo 8 ■ Strings 118
178 |
179 | Uma string é uma sequência 118
180 |
181 | len 119
182 |
183 | Travessia com loop for 120
184 |
185 | Fatiamento de strings 121
186 |
187 | Strings são imutáveis 122
188 |
189 | Buscando 123
190 |
191 | Loop e contagem 123
192 |
193 | Métodos de strings 124
194 |
195 | Operador in 125
196 |
197 | Comparação de strings 126
198 |
199 | Depuração 126
200 |
201 | Glossário 128
202 |
203 | Exercícios 130
204 |
205 | Capítulo 9 ■ Estudo de caso: jogos de palavras 133
206 |
207 | Leitura de listas de palavras 133
208 |
209 | Exercícios 134
210 |
211 | Busca 136
212 |
213 | Loop com índices 137
214 |
215 | Depuração 139
216 |
217 | Glossário 140
218 |
219 | Exercícios 140
220 |
221 | Capítulo 10 ■ Listas 142
222 |
223 | Uma lista é uma sequência 142
224 |
225 | Listas são mutáveis 143
226 |
227 | Percorrendo uma lista 144
228 |
229 | Operações com listas 145
230 |
231 | Fatias de listas 145
232 |
233 | Métodos de listas 146
234 |
235 | Mapeamento, filtragem e redução 147
236 |
237 | Como excluir elementos 148
238 |
239 | Listas e strings 149
240 |
241 | Objetos e valores 150
242 |
243 | Alias 151
244 |
245 | Argumentos de listas 152
246 |
247 | Depuração 154
248 |
249 | Glossário 156
250 |
251 | Exercícios 157
252 |
253 | Capítulo 11 ■ Dicionários 161
254 |
255 | Um dicionário é um mapeamento 161
256 |
257 | Um dicionário como uma coleção de contadores 163
258 |
259 | Loop e dicionários 165
260 |
261 | Busca reversa 165
262 |
263 | Dicionários e listas 167
264 |
265 | Memos 169
266 |
267 | Variáveis globais 170
268 |
269 | Depuração 172
270 |
271 | Glossário 173
272 |
273 | Exercícios 175
274 |
275 | Capítulo 12 ■ Tuplas 178
276 |
277 | Tuplas são imutáveis 178
278 |
279 | Atribuição de tuplas 180
280 |
281 | Tuplas como valores de retorno 181
282 |
283 | Tuplas com argumentos de comprimento variável 181
284 |
285 | Listas e tuplas 182
286 |
287 | Dicionários e tuplas 184
288 |
289 | Sequências de sequências 186
290 |
291 | Depuração 187
292 |
293 | Glossário 188
294 |
295 | Exercícios 189
296 |
297 | Capítulo 13 ■ Estudo de caso: seleção de estrutura de dados 192
298 |
299 | Análise de frequência de palavras 192
300 |
301 | Números aleatórios 193
302 |
303 | Histograma de palavras 195
304 |
305 | Palavras mais comuns 196
306 |
307 | Parâmetros opcionais 197
308 |
309 | Subtração de dicionário 198
310 |
311 | Palavras aleatórias 199
312 |
313 | Análise de Markov 200
314 |
315 | Estruturas de dados 202
316 |
317 | Depuração 203
318 |
319 | Glossário 205
320 |
321 | Exercícios 206
322 |
323 | Capítulo 14 ■ Arquivos 207
324 |
325 | Persistência 207
326 |
327 | Leitura e escrita 208
328 |
329 | Operador de formatação 208
330 |
331 | Nomes de arquivo e caminhos 210
332 |
333 | Captura de exceções 211
334 |
335 | Bancos de dados 212
336 |
337 | Usando o Pickle 213
338 |
339 | Pipes 214
340 |
341 | Escrevendo módulos 216
342 |
343 | Depuração 217
344 |
345 | Glossário 218
346 |
347 | Exercícios 219
348 |
349 | Capítulo 15 ■ Classes e objetos 221
350 |
351 | Tipos definidos pelos programadores 221
352 |
353 | Atributos 222
354 |
355 | Retângulos 224
356 |
357 | Instâncias como valores de retorno 225
358 |
359 | Objetos são mutáveis 225
360 |
361 | Cópia 226
362 |
363 | Depuração 228
364 |
365 | Glossário 229
366 |
367 | Exercícios 230
368 |
369 | Capítulo 16 ■ Classes e funções 231
370 |
371 | Time 231
372 |
373 | Funções puras 232
374 |
375 | Modificadores 233
376 |
377 | Prototipação versus planejamento 234
378 |
379 | Depuração 236
380 |
381 | Glossário 237
382 |
383 | Exercícios 238
384 |
385 | Capítulo 17 ■ Classes e métodos 240
386 |
387 | Recursos orientados a objeto 240
388 |
389 | Exibição de objetos 241
390 |
391 | Outro exemplo 243
392 |
393 | Um exemplo mais complicado 244
394 |
395 | Método init 244
396 |
397 | Método \_\_str\_\_ 245
398 |
399 | Sobrecarga de operadores 246
400 |
401 | Despacho por tipo 247
402 |
403 | Polimorfismo 248
404 |
405 | Interface e implementação 249
406 |
407 | Depuração 250
408 |
409 | Glossário 251
410 |
411 | Exercícios 252
412 |
413 | Capítulo 18 ■ Herança 253
414 |
415 | Objetos Card 253
416 |
417 | Atributos de classe 255
418 |
419 | Comparação de cartas 256
420 |
421 | Baralhos 257
422 |
423 | Exibição do baralho 258
424 |
425 | Adição, remoção, embaralhamento e classificação 258
426 |
427 | Herança 259
428 |
429 | Diagramas de classe 261
430 |
431 | Encapsulamento de dados 262
432 |
433 | Depuração 264
434 |
435 | Glossário 265
436 |
437 | Exercícios 267
438 |
439 | Capítulo 19 ■ Extra 270
440 |
441 | Expressões condicionais 270
442 |
443 | Abrangência de listas 271
444 |
445 | Expressões geradoras 273
446 |
447 | any e all 274
448 |
449 | Conjuntos 274
450 |
451 | Contadores 276
452 |
453 | defaultdict 277
454 |
455 | Tuplas nomeadas 279
456 |
457 | Reunindo argumentos de palavra-chave 280
458 |
459 | Glossário 282
460 |
461 | Exercícios 282
462 |
463 | Capítulo 20 ■ Depuração 284
464 |
465 | Erros de sintaxe 284
466 |
467 | !Continuo fazendo alterações e não faz nenhuma diferença 286
468 |
469 | Erros de tempo de execução 286
470 |
471 | !Meu programa não faz nada 286
472 |
473 | !Meu programa fica suspenso 287
474 |
475 | !Quando executo o programa recebo uma exceção 288
476 |
477 | !Acrescentei tantas instruções print que fui inundado pelos resultados 290
478 |
479 | Erros semânticos 291
480 |
481 | !Meu programa não funciona 291
482 |
483 | !Tenho uma baita expressão cabeluda e ela não faz o que espero 292
484 |
485 | !Tenho uma função que não retorna o que espero 293
486 |
487 | !Estou perdido e preciso de ajuda 293
488 |
489 | !Sério, preciso mesmo de ajuda 293
490 |
491 | Capítulo 21 ■ Análise de algoritmos 295
492 |
493 | Ordem de crescimento 296
494 |
495 | Análise de operações básicas do Python 299
496 |
497 | Análise de algoritmos de busca 301
498 |
499 | Hashtables 302
500 |
501 | Glossário 306
502 |
503 | Sobre o autor 308
504 |
--------------------------------------------------------------------------------
/recebido/thinkpython2.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PenseAllen/PensePython2e/afa460130599dbde01620e86c38923f785023956/recebido/thinkpython2.pdf
--------------------------------------------------------------------------------
/util/epub.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | from glob import glob
4 | import shutil
5 | import subprocess
6 | import os
7 |
8 |
9 | URL_REPO = 'https://github.com/PenseAllen/PensePython2e/raw/master'
10 |
11 |
12 | def _project_path():
13 | return os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
14 |
15 |
16 | def _get_path(p):
17 | return os.path.join(_project_path(), p)
18 |
19 |
20 | def _fix_images_url(files, tmp_dir):
21 | """ Corrige as urls das imagens.
22 | Por algum motivo o pandoc não estava conseguindo baixar as imagens
23 | do site para embedar no epub. Com esse código eu gero arquivos
24 | temporários com as essas referências acertadas para a mesma imagem
25 | dentro do projeto.
26 | """
27 | os.makedirs(tmp_dir)
28 | fixed_files = []
29 | fixed_path = os.path.relpath(_project_path())
30 | for fp in files:
31 | file_name = os.path.split(fp)[1]
32 | output = os.path.join(tmp_dir, file_name)
33 | with open(fp) as input_file:
34 | fixed_str = input_file.read().replace(URL_REPO, fixed_path)
35 | with open(output, 'w') as output_file:
36 | output_file.write(fixed_str)
37 | fixed_files.append(output)
38 | return fixed_files
39 |
40 |
41 | def main():
42 | glob_filter = _get_path('docs/*.md')
43 | capa = _get_path('img/Capa_PenseEmPython332x461-borda.png')
44 | metadata = _get_path('ebooks/metadata.xml')
45 | output = _get_path('ebooks/PenseEmPython2e.epub')
46 | files = glob(glob_filter)
47 | files.sort()
48 | files.pop()
49 | tmp_dir = _get_path('tmp')
50 | files = _fix_images_url(files, tmp_dir)
51 | # Monta os argumentos do pandoc
52 | args = ['pandoc', '--epub-cover-image=' + capa, '--epub-metadata=' + metadata]
53 | args.extend(files)
54 | args.append('-o')
55 | args.append(output)
56 | # Executa o pandoc
57 | subprocess.call(args)
58 | # Remove arquivos temporários
59 | shutil.rmtree(tmp_dir)
60 | print('Gerado epub em', output)
61 |
62 |
63 | if __name__ == '__main__':
64 | main()
65 |
--------------------------------------------------------------------------------
/util/gloss_e_exerc.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import re
4 |
5 | GLOSSARIO_RE = re.compile(r'^## [B|\d]\d?\.\d\d? - Glossário$', re.MULTILINE)
6 | EXERCICIOS_RE = re.compile(r'^## \d\d?\.\d\d? - Exercícios$', re.MULTILINE)
7 |
8 | VERBETE_RE = re.compile(r'^(.+?):\n\n', re.MULTILINE)
9 | VERBETE_REPL = r'__\1__
\n'
10 |
11 | EXERCICIO_RE = re.compile(r'^(Exercício \d\d?\.\d\d?)$', re.MULTILINE)
12 | EXERCICIO_REPL = r'### \1'
13 |
14 |
15 | def marcar_verbetes(md):
16 | casa_glossario = GLOSSARIO_RE.search(md)
17 | assert casa_glossario
18 | inicio = casa_glossario.span()[1] + 1
19 | casa_exercicios = EXERCICIOS_RE.search(md[inicio:])
20 | if casa_exercicios:
21 | fim = inicio + casa_exercicios.span()[0]
22 | else:
23 | fim = len(md)
24 | corpo = md[inicio:fim]
25 | casa_verbete = VERBETE_RE.search(corpo)
26 | assert casa_verbete
27 | corpo = VERBETE_RE.sub(VERBETE_REPL, corpo)
28 | return md[:inicio] + corpo + md[fim:]
29 |
30 |
31 | def marcar_exercicios(md):
32 | casa_exercicio = EXERCICIO_RE.search(md)
33 | assert casa_exercicio
34 | md = EXERCICIO_RE.sub(EXERCICIO_REPL, md)
35 | return md
36 |
37 |
38 | def main():
39 | import sys
40 | caminho_arq = sys.argv[1]
41 | with open(caminho_arq, encoding='utf8') as fp:
42 | md = fp.read()
43 | md = marcar_verbetes(md)
44 | md = marcar_exercicios(md)
45 | with open(caminho_arq, 'wt', encoding='utf8') as fp:
46 | fp.write(md)
47 |
48 |
49 | if __name__ == '__main__':
50 | main()
51 |
--------------------------------------------------------------------------------
/util/glossario_dl.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import re
4 |
5 | GLOSSARIO_RE = re.compile(r'^## [B|\d]\d?\.\d\d? - Glossário$', re.MULTILINE)
6 | EXERCICIOS_RE = re.compile(r'^## \d\d?\.\d\d? - Exercícios$', re.MULTILINE)
7 |
8 | VERBETE_RE = re.compile(r'\n__(.+?)__
\n([^\n]+)\n')
9 | VERBETE_REPL = r'\n\1\n\2\n'
10 |
11 |
12 | def marcar_verbetes(md):
13 | casa_glossario = GLOSSARIO_RE.search(md)
14 | assert casa_glossario
15 | inicio = casa_glossario.span()[1] + 1
16 | casa_exercicios = EXERCICIOS_RE.search(md[inicio:])
17 | if casa_exercicios:
18 | fim = inicio + casa_exercicios.span()[0]
19 | else:
20 | fim = len(md)
21 | corpo = md[inicio:fim]
22 | casa_verbete = VERBETE_RE.search(corpo)
23 | assert casa_verbete
24 | corpo = '\n' + VERBETE_RE.sub(VERBETE_REPL, corpo) + '
\n\n'
25 | return md[:inicio] + corpo + md[fim:]
26 |
27 |
28 | def main():
29 | import sys
30 | caminho_arq = sys.argv[1]
31 | with open(caminho_arq, encoding='utf8') as fp:
32 | md = fp.read()
33 | md = marcar_verbetes(md)
34 | with open(caminho_arq.replace('-', 'glos-', 1), 'wt', encoding='utf8') as fp:
35 | fp.write(md)
36 |
37 |
38 | if __name__ == '__main__':
39 | main()
40 |
--------------------------------------------------------------------------------
/util/marcar_listagens.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import re
4 |
5 | from glossario_dl import marcar_verbetes
6 |
7 | MAX_LEN_CODIGO = 50
8 | PREFIXOS_NAO_CODIGO = '# *
'.split()
9 |
10 | def pode_ser_codigo(lin):
11 | if len(lin) > MAX_LEN_CODIGO:
12 | return False
13 | for pre in PREFIXOS_NAO_CODIGO:
14 | if lin.startswith(pre):
15 | return False
16 | return True
17 |
18 |
19 | def marcar_listagens(md):
20 | lin_ant = ''
21 | bloco = []
22 | saida = []
23 | for lin in md.split('\n'):
24 | if pode_ser_codigo(lin):
25 | if lin:
26 | lin = lin.replace('>', '>')
27 | lin = lin.replace('<', '<')
28 | lin = lin.replace(r'\_', '_')
29 | lin = lin.replace(r'\#', '#')
30 | lin = lin.replace(r'\*', '*')
31 | bloco.append(lin)
32 | else:
33 | saida.append(lin)
34 | else:
35 | if bloco:
36 | saida.append('```python')
37 | saida.extend(bloco)
38 | saida.append('```\n')
39 | bloco = []
40 | saida.append(lin)
41 | lin_ant = lin
42 | return '\n'.join(saida).replace('\n\n\n', '\n\n').replace('\n\n\n', '\n\n')
43 |
44 |
45 | def main():
46 | import sys
47 | caminho_arq = sys.argv[1]
48 | with open(caminho_arq, encoding='utf8') as fp:
49 | md = fp.read()
50 | #md = marcar_verbetes(md)
51 | md = marcar_listagens(md)
52 | with open(caminho_arq.replace('-', 'list-', 1), 'wt', encoding='utf8') as fp:
53 | fp.write(md)
54 |
55 |
56 | if __name__ == '__main__':
57 | main()
58 |
--------------------------------------------------------------------------------
/util/marcar_secoes.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import re
4 | import collections
5 | import glob
6 | import os
7 |
8 | from separar_capitulos import NOME_CAPS
9 |
10 | SUMARIO = '../recebido/sumario.md'
11 | DIR_DOCS = '../docs/'
12 |
13 | CAP_RE = re.compile('^Capítulo (\d+)', re.MULTILINE)
14 | SEC_RE = re.compile('(.+?)\s+\d+$', re.MULTILINE)
15 |
16 | Secao = collections.namedtuple('Secao', 'num titulo')
17 |
18 | def id_cap(num_cap):
19 | if num_cap == 20:
20 | return 'A'
21 | elif num_cap == 21:
22 | return 'B'
23 | return str(num_cap)
24 |
25 |
26 | def ler_sumario():
27 |
28 | sumario = {}
29 |
30 | with open(SUMARIO, encoding='utf8') as fp:
31 | md = fp.read()
32 |
33 | num_cap = None
34 | for lin in md.split('\n\n'):
35 | casa_cap = CAP_RE.search(lin)
36 | if casa_cap:
37 | num_cap = int(casa_cap.group(1))
38 | num_secao = 0
39 | elif num_cap is not None:
40 | lin = lin.replace('\xa0', ' ') # \xa0 = NBSP
41 | casa_secao = SEC_RE.search(lin)
42 | assert casa_secao, 'NAO CASOU: ' + lin
43 | tit_secao = casa_secao.group(1)
44 |
45 | if tit_secao[0] == '!':
46 | num_subsecao += 1
47 | secao = Secao('{}.{}.{}'.format(id_cap(num_cap), num_secao, num_subsecao),
48 | tit_secao[1:])
49 | else:
50 | num_secao += 1
51 | num_subsecao = 0
52 | secao = Secao('{}.{}'.format(id_cap(num_cap), num_secao), tit_secao)
53 | # print(secao)
54 | sumario.setdefault(id_cap(num_cap), []).append(secao)
55 |
56 | return sumario
57 |
58 | def marcar(md, sumario_cap):
59 | ultimo_local = 0
60 | for secao in sumario_cap:
61 | local = md.find('\n' + secao.titulo, ultimo_local+1)
62 | assert local > ultimo_local, secao
63 | ultimo_local = local
64 | decoracao = '## {} - '.format(secao.num)
65 | if secao.num.count('.') == 2:
66 | decoracao = '#' + decoracao
67 | md = md[:local+1] + decoracao + md[local+1:]
68 |
69 | return md
70 |
71 |
72 | def marcar_caps(sumario):
73 | for path_arq in glob.glob(DIR_DOCS+'*-*.md'):
74 | nome_arq = os.path.basename(path_arq)
75 | id_cap = nome_arq.split('-')[0].lstrip('0')
76 | if not id_cap:
77 | continue # prefácio não tem seções no sumário
78 |
79 | with open(path_arq, encoding='utf8') as fp:
80 | md = fp.read()
81 | print(nome_arq, id_cap)
82 | md = marcar(md, sumario[id_cap])
83 | with open(path_arq, 'wt', encoding='utf8') as fp:
84 | fp.write(md)
85 |
86 |
87 | if __name__ == '__main__':
88 | sumario = ler_sumario()
89 | marcar_caps(sumario)
90 |
--------------------------------------------------------------------------------
/util/separar_capitulos.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import re
4 |
5 | NOME_CAPS = {
6 | 0 : 'prefacio',
7 | 1 : 'jornada',
8 | 2 : 'vars-expr-instr',
9 | 3 : 'funcoes',
10 | 4 : 'caso-interface',
11 | 5 : 'cond-recur',
12 | 6 : 'funcoes-result',
13 | 7 : 'iteracao',
14 | 8 : 'strings',
15 | 9 : 'caso-palavras',
16 | 10 : 'listas',
17 | 11 : 'dicionarios',
18 | 12 : 'tuplas',
19 | 13 : 'caso-estruturas',
20 | 14 : 'arquivos',
21 | 15 : 'classes-objetos',
22 | 16 : 'classes-funcoes',
23 | 17 : 'classes-metodos',
24 | 18 : 'heranca',
25 | 19 : 'extra',
26 | 20 : 'depuracao',
27 | 21 : 'analise-algorit',
28 | }
29 |
30 | DIR_CAPITULOS = '../recebido/capitulos/'
31 |
32 | def main():
33 | with open('../recebido/PenseEmPython.md', encoding='utf8') as fp:
34 | md = fp.read()
35 |
36 | cap_sep = re.compile(r'^capítulo\s+\d+\n\n', re.MULTILINE)
37 |
38 | caps = cap_sep.split(md)
39 |
40 | for i, cap in enumerate(caps):
41 | quebra = cap.find('\n\n')
42 | titulo = cap[:quebra]
43 | corpo = cap[quebra:]
44 | parte = 'Apêndice'
45 | if i == 20:
46 | prefixo = 'A'
47 | elif i == 21:
48 | prefixo = 'B'
49 | else:
50 | parte = 'Capítulo'
51 | prefixo = format(i, '02d')
52 | nome_arq = prefixo + '-' + NOME_CAPS[i] + '.md'
53 | parte += ' ' + prefixo.lstrip('0')
54 | print('{}. [{}]({})'.format(prefixo.lstrip('0'), titulo, nome_arq))
55 | # ATENÇÃO: as instruções a seguir SOBRESCREVEM os arquivos no diretório
56 | # DIR_CAPITULOS
57 | #with open(DIR_CAPITULOS + nome_arq, 'wt', encoding='utf8') as fp:
58 | # fp.write('# ' + parte + ': ' + titulo + corpo)
59 |
60 | if __name__ == '__main__':
61 | main()
62 |
--------------------------------------------------------------------------------