Você está na página 1de 150

Machine Translated by Google

ENQUANTO LOOPS 151

9 print("Números agora: ", números) print(f"No


10 fundo i está {i}")
11

12

13 print("Os números: ")


14

15 para num em números:


16 imprimir (número)

O que você deve ver

Exercício 33 Sessão

$ python3.6 ex33.py No topo i


é 0 Números agora: [0]

Na parte inferior eu sou 1

No topo eu sou 1
Números agora: [0, 1]
Na parte inferior eu tenho 2

No topo eu tenho 2
Números agora: [0, 1, 2]
Na parte inferior eu tenho 3

No topo eu tenho 3
Números agora: [0, 1, 2, 3]
Na parte inferior eu tenho 4

No topo eu tenho 4
Números agora: [0, 1, 2, 3, 4]
Na parte inferior eu tenho 5

No topo eu tenho 5
Números agora: [0, 1, 2, 3, 4, 5]
Na parte inferior eu tenho 6
Os números:
0
1
2
3
4
5
Machine Translated by Google

152 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

Exercícios de estudo

1. Converta este loop while em uma função que você possa chamar e substitua 6 no teste (i < 6) por um
variável.

2. Use esta função para reescrever o script para tentar números diferentes.

3. Adicione outra variável aos argumentos da função que você pode passar e que permite alterar o +
1 na linha 8 para que você possa alterar o quanto ele aumenta.

4. Reescreva o script novamente para usar esta função e ver o efeito que isso tem.

5. Escreva-o para usar loops for e intervalo. Você precisa mais do incrementador no meio? O que
acontece se você não se livrar dele?

Se a qualquer momento você estiver fazendo isso, ele enlouquecer (provavelmente irá), apenas mantenha pressionada a tecla CTRL e
pressione c (CTRL-c) e o programa será abortado.

Perguntas comuns dos alunos

Qual é a diferença entre um loop for e um loop while? Um loop for só pode iterar (loop) “sobre” coleções de coisas. Um loop while pode
fazer qualquer tipo de iteração (loop) que você desejar. No entanto, os loops while são mais difíceis de acertar e normalmente
você pode realizar muitas coisas com os loops for.

Loops são difíceis. Como faço para descobri-los? A principal razão pela qual as pessoas não entendem os loops é porque elas não
conseguem acompanhar os “saltos” que o código faz. Quando um loop é executado, ele passa pelo seu bloco de código e, no
final, volta ao topo. Para visualizar isso, coloque instruções de impressão em todo o loop, mostrando onde o Python está sendo
executado e quais variáveis estão definidas nesses pontos. Escreva linhas de impressão antes do loop, na parte superior do
loop, no meio e na parte inferior. Estude o resultado e tente entender o salto que está acontecendo.
Machine Translated by Google

ENQUANTO LOOPS 153


Machine Translated by Google

154

EXERCÍCIO 34

Acessando Elementos de Listas


As listas são muito úteis, mas, a menos que você consiga entender o que elas contêm, elas não são tão boas.
Você já pode percorrer os elementos de uma lista em ordem, mas e se quiser dizer o quinto elemento? Você
precisa saber como acessar os elementos de uma lista. Veja como você acessaria o primeiro elemento de uma
lista:
'
animais = [ 'urso' urso , 'muito rs , 'pinguim' , 'zebra']
= animais [0]

Você pega uma lista de animais e depois pega o primeiro (1º) usando 0?! Como isso funciona? Devido à forma
como a matemática funciona, o Python inicia suas listas em 0 em vez de 1. Parece estranho, mas há muitas
vantagens nisso, embora seja em grande parte arbitrário.

A melhor maneira de explicar o porquê é mostrar a diferença entre como você usa os números e como os
programadores usam os números.

Imagine que você está observando os quatro animais da nossa lista (['urso', 'tigre', 'pinguim', 'zebra']) participando
de uma corrida. Eles cruzam a linha de chegada na ordem em que os temos nesta lista. A corrida foi realmente
emocionante porque os animais não se comeram e de alguma forma conseguiram correr. Seu amigo chega
atrasado e quer saber quem ganhou. Seu amigo diz: “Ei, quem chegou no zero?” Não, ele diz: “Ei, quem chegou
primeiro?”

Isso ocorre porque a ordem dos animais é importante. Você não pode ter o segundo animal sem o primeiro
(primeiro) animal, e não pode ter o terceiro sem o segundo. Também é impossível ter um animal “zero”, já que
zero não significa nada. Como você pode fazer com que nada ganhe uma corrida? Simplesmente não faz sentido.
Chamamos esses tipos de números de números “ordinais”, porque indicam uma ordem das coisas.

Os programadores, entretanto, não podem pensar dessa forma porque podem escolher qualquer elemento de uma lista a qualquer momento.
Para os programadores, a lista de animais é mais parecida com um baralho de cartas. Se eles querem o tigre, eles o
agarram. Se quiserem a zebra, também podem pegá-la. Essa necessidade de extrair elementos das listas aleatoriamente
significa que eles precisam de uma maneira de indicar os elementos consistentemente por um endereço, ou um “índice”, e
a melhor maneira de fazer isso é iniciar os índices em 0. Confie em mim: a matemática é bem mais fácil para esse tipo de acesso.
Esse tipo de número é um número “cardinal” e significa que você pode escolher aleatoriamente, portanto é necessário que haja
um elemento 0.

Como isso ajuda você a trabalhar com listas? Simples, toda vez que você diz para si mesmo: “Eu quero o
terceiro animal”, você traduz esse número “ordinal” para um número “cardinal” subtraindo 1. O “terceiro” animal
está no índice 2 e é o pinguim. Você tem que fazer isso porque passou a vida inteira usando números ordinais
e agora tem que pensar em números cardinais. Basta subtrair 1 e você ficará bem.

Lembre-se: ordinal == ordenado, 1º; cardinal == cartas aleatoriamente, 0.

Vamos praticar isso. Pegue esta lista de animais e siga os exercícios onde eu digo para você anotar qual animal
você obteve para aquele número ordinal ou cardinal. Lembre-se, se eu disser “primeiro”, “segundo”, então estou usando
Machine Translated by Google

ACESSAR ELEMENTOS DE LISTAS 155

ordinal, então subtraia 1. Se eu lhe der cardeal (como “O animal em 1”), use-o diretamente.

animais = [ 'urso' , 'python3. 6' , 'pavão' , 'canguru' , 'baleia ' , 'ornitorrinco']

1. O animal em 1.

2. O terceiro (3º) animal.

3. O primeiro (1º) animal.

4. O animal às 3.

5. O quinto (5º) animal.

6. O animal às 2.

7. O sexto (6º) animal.

8. O animal às 4.

Para cada um deles, escreva uma frase completa no formato: “O primeiro (1º) animal está em 0 e é um urso”. Então
diga ao contrário: “O animal em 0 é o primeiro animal e é um urso”.

Use seu Python para verificar suas respostas.

Exercícios de estudo

1. Com o que você sabe sobre a diferença entre esses tipos de números, você pode explicar por que
o ano de 2010 em “1º de janeiro de 2010” é realmente 2010 e não 2009? (Dica: você não pode escolher anos aleatoriamente.)

2. Escreva mais algumas listas e elabore índices semelhantes até poder traduzi-los.

3. Use Python para verificar suas respostas.

AVISO! Os programadores dirão para você ler esse cara chamado “Dijkstra” sobre esse assunto.
Eu recomendo que você evite os escritos dele sobre isso, a menos que você goste de ouvir gritos de alguém
que parou de programar ao mesmo tempo em que a programação começou.
Machine Translated by Google

156

EXERCÍCIO 35

Ramos e Funções

Você aprendeu instruções if, funções e listas. Agora é hora de dobrar sua mente. Digite isso,
e veja se você consegue descobrir o que está fazendo.

ex35.py

1 da saída de importação do sistema


2

3 def gold_room():
4 print("Esta sala está cheia de ouro. Quanto você leva?")
5

6 escolha = entrada("> ")


7 se "0" na escolha ou "1" na escolha:
8 quanto_quanto = int(escolha)
9 outro:
10 dead("Cara, aprenda a digitar um número.")
11

12 se quanto_quanto < 50:


13 print("Legal, você não é ganancioso, você venceu!")
14 saída(0)
15 outro:
16 morto("Seu bastardo ganancioso!")
17

18

19 def sala_urso():
20 print("Tem um urso aqui.")
21 print("O urso tem um monte de mel.")
22 print("O urso gordo está na frente de outra porta.")
23 print("Como você vai mover o urso?")
24 bear_moved = Falso
25

26 enquanto Verdadeiro:

27 escolha = entrada("> ")


28

29 if choice == "levar mel":


30 morto("O urso olha para você e depois dá um tapa na sua cara.")
31 elif escolha == "taunt bear" e não bear_moved:
32 print("O urso saiu da porta.")
33 print("Você pode passar por isso agora.")
34 bear_moved = Verdadeiro
35 escolha elif == "taunt bear" e bear_moved:
Machine Translated by Google

RAMOS E FUNÇÕES 157

36 morto("O urso fica chateado e arranca sua perna.")


37 elif escolha == "porta aberta" e bear_moved:
38 sala_ouro()
39 outro:
40 print(" Não tenho ideia do que isso significa.")
41

42

43 def cthulhu_room():
44 print("Aqui você vê o grande malvado Cthulhu.")
45 print("Ele, aquilo, o que quer que fique olhando para você e você enlouquece.")
46 print(" Você foge para salvar sua vida ou come sua cabeça?")
47

48 escolha = entrada("> ")


49

50 se "fugir" na escolha:
51 começar()
52 elif "cabeça" na escolha:
53 morto("Bem, isso foi gostoso!")
54 outro:
55 cthulhu_room()
56

57

58 mortos definitivamente (por quê):

59 print(por que, "Bom trabalho!")


60 saída(0)
61

62 definição início():
63 print("Você está em um quarto escuro.")
64 print("Há uma porta à sua direita e à sua esquerda.")
65 print("Qual você escolhe?")
66

67 escolha = entrada("> ")


68

69 if escolha == "esquerda":
70 sala_urso()
71 elif escolha == "certo":
72 cthulhu_room()
73 outro:
74 dead("Você tropeça pela sala até morrer de fome.")
75

76

77 início()
Machine Translated by Google

158 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

O que você deve ver

Aqui estou eu jogando:

Exercício 35 Sessão

$ python3.6 ex35.py
Você está em um quarto escuro.
Há uma porta à sua direita e à sua esquerda.
Qual você leva? > esquerda

Há um urso aqui.

O urso tem um monte de mel.


O urso gordo está na frente de outra porta.

Como você vai mover o urso? > provocação do urso

O urso saiu da porta.

Você pode passar por isso agora. > porta


aberta Esta sala
está cheia de ouro. Quanto você leva? > 1000

Seu bastardo ganancioso! Bom trabalho!

Exercícios de estudo

1. Desenhe um mapa do jogo e como você flui nele.

2. Corrija todos os seus erros, incluindo erros ortográficos.

3. Escreva comentários para as funções que você não entende.

4. Adicione mais ao jogo. O que você pode fazer para simplificá-lo e expandi-lo?

5. O gold_room tem uma maneira estranha de fazer você digitar um número. Quais são todos os bugs dessa maneira de
fazer isso? Você pode torná-lo melhor do que o que escrevi? Veja como int() funciona para obter pistas.

Perguntas comuns dos alunos

Ajuda! Como é que este programa funciona!? Quando você não conseguir entender um trecho de código, simplesmente
escreva um comentário em inglês acima de cada linha explicando o que essa linha faz. Mantenha seus comentários curtos
Machine Translated by Google

RAMOS E FUNÇÕES 159

e semelhante ao código. Em seguida, faça um diagrama de como o código funciona ou escreva um parágrafo descrevendo-o.
Se você fizer isso você vai conseguir.

Por que você escreveu enquanto True? Isso faz um loop infinito.

O que exit(0) faz? Em muitos sistemas operacionais, um programa pode ser abortado com exit(0), e o
número passado indicará um erro ou não. Se você fizer exit(1) então será um erro, mas exit(0) será
uma boa saída. A razão pela qual está ao contrário da lógica booleana normal (com 0==False) é que
você pode usar números diferentes para indicar diferentes resultados de erro. Você pode executar
exit(100) para um resultado de erro diferente de exit(2) ou exit(1).

Por que input() às vezes é escrito como input('> ')? O parâmetro a ser inserido é uma string que deve
imprima como um prompt antes de obter a entrada do usuário.
Machine Translated by Google

160

EXERCÍCIO 36

Projetando e depurando
Agora que você conhece as instruções if, vou lhe dar algumas regras para loops for e loops while que o manterão longe de
problemas. Também darei algumas dicas sobre depuração para que você possa descobrir problemas com seu programa. Por fim,
você criará um joguinho semelhante ao exercício anterior, mas com uma ligeira variação.

Regras para instruções If

1. Cada instrução if deve ter um else.

2. Se this else nunca deve ser executado porque não faz sentido, então você deve usar uma função die no else que imprime
uma mensagem de erro e morre, assim como fizemos no último exercício. Isso encontrará muitos erros.

3. Nunca aninhe instruções if com mais de duas profundidades e sempre tente fazê-las com uma profundidade.

4. Trate as instruções if como parágrafos, onde cada agrupamento if-elif-else é como um conjunto de sentidos.
tences. Coloque linhas em branco antes e depois.

5. Seus testes booleanos devem ser simples. Se forem complexos, mova seus cálculos para variáveis anteriores em sua
função e use um bom nome para a variável.

Se você seguir essas regras simples, começará a escrever códigos melhores do que a maioria dos programadores. Volte ao
último exercício e veja se segui todas essas regras. Se não, corrija meus erros.

AVISO! Nunca seja escravo das regras da vida real. Para fins de treinamento, você precisa seguir estas regras
para fortalecer sua mente, mas na vida real, às vezes, essas regras são simplesmente estúpidas. Se você
acha que uma regra é estúpida, tente não usá-la.

Regras para Loops

1. Use um loop while apenas para fazer um loop para sempre, e isso significa provavelmente nunca. Isto só se aplica a
Pitão; outras línguas são diferentes.

2. Use um loop for para todos os outros tipos de loop, especialmente se houver um número fixo ou limitado de
coisas para repetir.
Machine Translated by Google

PROJETO E DEPURAÇÃO 161

Dicas para depuração

1. Não use um “depurador”. Um depurador é como fazer uma varredura de corpo inteiro em uma pessoa doente. Você não obtém
nenhuma informação útil específica e encontra muitas informações que não ajudam e são apenas confusas.

2. A melhor maneira de depurar um programa é usar print para imprimir os valores das variáveis em pontos do programa para ver onde
elas estão erradas.

3. Certifique-se de que partes dos seus programas funcionem enquanto você trabalha neles. Não escreva arquivos enormes de código
antes de tentar executá-los. Codifique um pouco, execute um pouco, conserte um pouco.

Trabalho de casa

Agora escreva um jogo semelhante ao que criei no último exercício. Pode ser qualquer tipo de jogo que você quiser do mesmo sabor. Passe
uma semana nisso, tornando-o o mais interessante possível. Para exercícios de estudo, use listas, funções e módulos (lembra daqueles do
Exercício 13?) tanto quanto possível e encontre o máximo possível de novas peças de Python para fazer o jogo funcionar.

Antes de começar a codificar, você deve desenhar um mapa para o seu jogo. Crie no papel as salas, monstros e armadilhas pelas quais o
jogador deve passar antes de codificar.

Depois de ter seu mapa, tente codificá-lo. Se você encontrar problemas com o mapa, ajuste-o e faça com que o código corresponda.

A melhor maneira de trabalhar em um software é em pequenos pedaços como este:

1. Em uma folha de papel ou ficha, escreva uma lista de tarefas que você precisa realizar para concluir o
Programas. Esta é a sua lista de tarefas.

2. Escolha a coisa mais fácil que você pode fazer na sua lista.

3. Escreva comentários em inglês em seu arquivo de origem como um guia de como você realizaria esta tarefa
no seu código.

4. Escreva parte do código nos comentários em inglês.

5. Execute seu script rapidamente para ver se o código funcionou.

6. Continue trabalhando em um ciclo de escrever algum código, executá-lo para testá-lo e corrigi-lo até que funcione.

7. Risque esta tarefa da sua lista, escolha a próxima tarefa mais fácil e repita.

Este processo o ajudará a trabalhar no software de maneira metódica e consistente. À medida que você trabalha, atualize sua lista removendo
tarefas que você realmente não precisa e adicionando aquelas que você realmente precisa.
Machine Translated by Google

162

EXERCÍCIO 37

Revisão do símbolo

É hora de revisar os símbolos e palavras Python que você conhece e tentar escolher mais alguns para o
próximas aulas. Escrevi todos os símbolos e palavras-chave do Python que são importantes de saber.

Nesta lição, pegue cada palavra-chave e primeiro tente escrever de memória o que ela faz. Em seguida, pesquise on-line
para isso e ver o que ele realmente faz. Isto pode ser difícil porque alguns deles são difíceis de pesquisar,
mas tente mesmo assim.

Se você errar de memória, faça uma ficha com a definição correta e tente
“corrija” sua memória.

Por fim, use cada um deles em um pequeno programa Python, ou em tantos quantos você puder fazer. O objetivo é encontrar
descubra o que o símbolo faz, certifique-se de que acertou, corrija-o se não o fez e use-o para bloqueá-lo.

Palavras-chave

Palavra-chave Descrição Exemplo


e Lógico e. Verdadeiro e Falso == Falso
como Parte da instrução with-as . com X como Y: aprovado
afirmar Afirme (garanta) que algo é verdade. afirmar Falso, "Erro!"
quebrar Pare esse ciclo agora mesmo. enquanto True: quebrar

aula Defina uma classe. classe Pessoa (objeto)


continue Não processe mais do loop, faça novamente. enquanto True: continuar
definição Defina uma função. def X(): passar
do Excluir do dicionário. de X[Y]
Elifa Caso contrário, se for condição. se: X; Elif: Y; mais: J
outro Outra condição. se: X; Elif: Y; mais: J
exceto Se acontecer uma exceção, faça isso. exceto ValueError como e: print(e)
executivo Execute uma string como Python. exec 'imprimir("olá")'
finalmente Exceções ou não, finalmente faça isso, não importa finalmente: passar
o que.

para Faça um loop sobre uma coleção de coisas. para X em Y: aprovado


de Importando partes específicas de um módulo. de x importar Y
global Declare que você deseja uma variável global. global X
se Se condição. se: X; Elif: Y; mais: J
... Continua na próxima página
Machine Translated by Google

REVISÃO DO SÍMBOLO 163

Importação de Descrição Exemplo

palavras-chave Importe um módulo para este para usar. importe-nos


em Parte dos loops for. Também um teste de X em Y. para X em Y: passe também 1 em [1] ==
Verdadeiro

é Como == para testar a igualdade. 1 é 1 == Verdadeiro


lambda Crie uma função anônima curta. **
s = lambda y: y e; s(3)
não Lógico não. não é verdade == falso
ou Lógico ou. Verdadeiro ou Falso == Verdadeiro

passar Este bloco está vazio. def vazio(): passar


imprimir Imprima esta string. print('esta string')
elevação Crie uma exceção quando as coisas derem errado. aumentar ValueError("Não")
retornar Saia da função com um valor de retorno. def X(): retorna Y

tentar Experimente este bloco e, em caso de exceção, vá para exceto. tentar: passar
enquanto Enquanto loop. enquanto X: passa
com Com uma expressão como variável, faça. com X como Y: aprovado
Faça uma pausa aqui e retorne ao chamador.
colheita def X(): rendimento Y; X().próximo()

Tipos de dados

Para tipos de dados, escreva o que constitui cada um. Por exemplo, com strings, escreva como você cria
uma linha. Para números, escreva alguns números.

Tipo Descrição Exemplo

Verdadeiro Valor booleano verdadeiro. Verdadeiro ou Falso == Verdadeiro

Falso Valor booleano falso. Falso e Verdadeiro == Falso


Nenhum Representa “nada” ou “nenhum valor”. x = Nenhum

cadeias Armazena bytes, talvez de texto, PNG, arquivo, etc. x = b"olá"


Armazena informações textuais. x = "olá"
de bytes
números Armazena números inteiros. eu = 100
flutua Armazena decimais. eu = 10,389
listas Armazena uma lista de coisas. j = [1,2,3,4]
provérbios Armazena um mapeamento chave=valor das coisas. e = {'x': 1, 'y': 2}

Sequências de escape de string

Para sequências de escape de strings, use-as em strings para garantir que elas façam o que você pensa que fazem.
Machine Translated by Google

164 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

Escapar Descrição

\\ Barra invertida

\' Citação única

\" Citação dupla

\a Sino

\b Retrocesso

\f Formfeed

\n Nova linha

\r Transporte

\t Aba

\em Guia Vertical

Formatos de string de estilo antigo

A mesma coisa para formatos de string: use-os em algumas strings para saber o que fazem.

Escapar Descrição Exemplo

%d Inteiros decimais (não ponto flutuante). "%d"% 45 == '45'

%eu O mesmo que %d. "%i"% 45 == '45'

%o Número octal. "%o" % 1000 == '1750'

%em Decimal sem sinal. "%u"% -1000 == '-1000'

%x Letras hexadecimais minúsculas. "%x"% 1000 == '3e8'

%X Maiúsculas hexadecimais. "%X"% 1000 == '3E8'

%e Notação exponencial, 'e' minúsculo. "%e"% 1000 == '1.000000e+03'

%E Notação exponencial, 'E' maiúsculo. "%E"% 1000 == '1.000000E+03'

%f Número real de ponto flutuante. "%f"% 10,34 == '10,340000'

%F O mesmo que %f. "%F"% 10,34 == '10,340000'

%g %f ou %e, o que for menor. "%g"% 10,34 == '10,34'


%G O mesmo que %g, mas em letras maiúsculas. "%G"% 10,34 == '10,34'
Formato de caractere. '"'
%c "%c"% 34 ==

%r Formato Repr (formato de depuração). "%r"% int == "<tipo 'int'>"


%s Formato de string. "% está aí" % 'oi' == 'oi
lá'

%% Um sinal de porcentagem. "%g%%"% 10,34 == '10,34%'

O código Python 2 mais antigo usa esses caracteres de formatação para fazer o que as strings f fazem. Experimente-os como alternativa.
Machine Translated by Google

REVISÃO DO SÍMBOLO 165

Operadores

Alguns deles podem não ser familiares para você, mas procure-os mesmo assim. Descubra o que eles fazem e se você
ainda não consegui descobrir, guarde para mais tarde.

Descrição do Operador Exemplo


+ Adição 2 + 4 == 6
- Subtração 2 - 4 == -2
* Multiplicação 2 * 4 == 8
** Desligar 2 ** 4 == 16

/ Divisão 2/4 == 0,5

// Divisão de piso 2 // 4 == 0

% Interpolação de string ou módulo 2% 4 == 2


< Menor que 4 <4 == Falso
> Maior que 4 > 4 == Falso
<= Menos que igual 4 <= 4 == Verdadeiro
>= Maior que igual 4 >= 4 == Verdadeiro
== Igual 4 == 5 == Falso

!= Não igual 4!= 5 == Verdadeiro


Parêntese
() len('oi') == 2
Listar colchetes
[ ] [1,3,4]

{} Ditar chaves {'x': 5, 'y': 10}


@ Em (decoradores) @classmethod
Vírgula
, intervalo(0, 10)
: Cólon
defX():
. Ponto eu.x = 10
= Atribuir igual x = 10
ponto e vírgula
; imprimir("oi"); imprimir("lá")
+= Adicionar e atribuir x = 1; x + = 2
-= Subtrair e atribuir x = 1; x-= 2
*= Multiplicar e atribuir x = 1; x*= 2
/= Dividir e atribuir x = 1; x /= 2
//= Divisão e atribuição de piso x = 1; x //= 2
%= Atribuição de módulo x = 1; x % = 2
**= Atribuição de energia x = 1; x ** = 2

Passe cerca de uma semana nisso, mas se terminar mais rápido, ótimo. O objetivo é tentar obter cobertura
todos esses símbolos e certifique-se de que estejam gravados em sua cabeça. O que também é importante é descobrir o que
você não sabe, então pode consertar mais tarde.
Machine Translated by Google

166 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

Lendo código

Agora encontre algum código Python para ler. Você deveria ler qualquer código Python que puder e tentar roubar as ideias que
encontrar. Na verdade, você deve ter conhecimento suficiente para poder ler, mas talvez não entenda o que o código faz. O que
esta lição ensina é como aplicar o que você aprendeu para entender o código de outras pessoas.

Primeiro, imprima o código que deseja entender. Sim, imprima, porque seus olhos e cérebro estão mais acostumados a ler papel
do que telas de computador. Certifique-se de imprimir algumas páginas por vez.

Em segundo lugar, leia sua impressão e faça anotações sobre o seguinte:

1. Funções e o que fazem.

2. Onde cada variável recebe primeiro um valor.

3. Quaisquer variáveis com os mesmos nomes em diferentes partes do programa. Isso pode ser um problema mais tarde.

4. Quaisquer instruções if sem cláusulas else. Eles estão certos?

5. Quaisquer loops while que possam não terminar.

6. Quaisquer partes do código que você não consegue entender por qualquer motivo.

Terceiro, depois de marcar tudo isso, tente explicar para si mesmo escrevendo comentários à medida que avança.
Explique as funções, como elas são usadas, quais variáveis estão envolvidas e tudo o que você puder para descobrir esse código.

Por último, em todas as partes difíceis, trace os valores de cada variável linha por linha, função por função. Na verdade, faça outra
impressão e escreva na margem o valor de cada variável que você precisa “rastrear”.

Depois de ter uma boa ideia do que o código faz, volte ao computador e leia-o novamente para ver se encontra coisas novas.
Continue encontrando mais código e fazendo isso até não precisar das impressões
não mais.

Exercícios de estudo

1. Descubra o que é um “fluxograma” e desenhe alguns.

2. Se você encontrar erros no código que está lendo, tente corrigi-los e envie ao autor suas alterações.

3. Outra técnica para quando você não estiver usando papel é colocar # comentários junto com suas anotações no código. Às
vezes, esses podem se tornar comentários reais para ajudar a próxima pessoa.
Machine Translated by Google

REVISÃO DO SÍMBOLO 167

Perguntas comuns dos alunos

Como eu pesquisaria essas coisas online? Basta colocar “python3.6” antes de qualquer coisa que você queira encontrar.
Por exemplo, para encontrar o rendimento , pesquise o rendimento do python3.6.
Machine Translated by Google

168

EXERCÍCIO 38

Fazendo coisas com listas


Você aprendeu sobre listas. Quando você aprendeu sobre loops while, você “acrescentou” números ao final de uma lista
e os imprimiu. Havia também exercícios de estudo onde você deveria encontrar todas as outras coisas que pode fazer nas
listas da documentação do Python. Isso foi há algum tempo, então revise esses tópicos se você não sabe do que estou
falando.

Encontrei? Lembre se? Bom. Quando você fez isso, você tinha uma lista e “chamou” a função anexada a ela. No entanto,
você pode não entender realmente o que está acontecendo, então vamos ver o que podemos fazer com as listas.

Quando você escreve mystuff.append('hello') você está na verdade desencadeando uma cadeia de eventos dentro do
Python para fazer com que algo aconteça com a lista mystuff . Veja como funciona:

1. Python vê que você mencionou minhas coisas e procura essa variável. Talvez seja necessário olhar para trás para
ver se você o criou com =, se é um argumento de função ou se é uma variável global. De qualquer forma, ele
precisa encontrar o mistério primeiro.

2. Depois de encontrar minhas coisas , ele lê o arquivo . (ponto final) e começa a observar as variáveis que fazem
parte do meu material. Como mystuff é uma lista, ele sabe que mystuff tem várias funções.

3. Em seguida, ele clica em anexar e compara o nome com todos os nomes que mystuff diz possuir. Se o anexo
estiver lá (está), então o Python o pega para usar.

4. Em seguida, Python vê o ( (parênteses) e percebe: "Ah, ei, isso deveria ser uma função." Nesse ponto, ele chama
(executa, executa) a função normalmente, mas em vez disso, chama a função com um argumento extra .

5. Esse argumento extra é... coisa minha! Eu sei, estranho, certo? Mas é assim que o Python funciona, então é melhor
apenas lembrar disso e presumir que esse é o resultado. O que acontece, no final de tudo isso, é uma chamada
de função que se parece com: append(mystuff, 'hello') em vez do que você leu, que é mystuff.append('hello').

Na maioria das vezes você não precisa saber que isso está acontecendo, mas ajuda quando você recebe mensagens de
erro do Python como esta:

$python3. 6 >>>
classe Coisa (objeto): def teste
... (mensagem): impressão
... (mensagem)
...
>>> a = Coisa ( ) >>>
a . teste (“olá”)
Traceback (chamada mais recente durar ) :
Machine Translated by Google

FAZENDO COISAS COM LISTAS 169

Página inicial "<s tdin>" , linha 1 , em <módulo>


TypeError: test () leva exatamente 1 argumento (2 dados)
>>>

O que foi tudo isso? Bem, sou eu digitando no shell do Python e mostrando um pouco de mágica. Você
ainda não vi a aula , mas falaremos disso mais tarde. Por enquanto você vê como Python disse test() leva
exatamente 1 argumento (2 dados). Se você vir isso, significa que o Python mudou a.test("hello") para
test(a, "hello") e que em algum lugar alguém errou e não adicionou o argumento para a.

Isso pode ser muito para entender, mas vamos gastar alguns exercícios para firmar esse conceito em seu
cérebro. Para começar, aqui está um exercício que mistura strings e listas para todos os tipos de diversão.

ex38.py

1 ten_things = "Maçãs Laranjas Corvos Telefone Luz Açúcar"


2

3 print("Espere , não há 10 coisas nessa lista. Vamos consertar isso.")


4

5 coisas = dez_coisas.split(' ')


6 more_stuff = ["Dia", "Noite", "Música", "Frisbee",
7 "Milho", "Banana", "Menina", "Menino"]
8

9 enquanto len(coisas) != 10:


10 próximo_um = mais_coisas.pop()
11 print("Adicionando: ", next_one)
12 coisas.append(próximo_um)
13 print(f"Existem {len(stuff)} itens agora.")
14

15 print("Lá vamos nós: ", coisas)


16

17 print("Vamos fazer algumas coisas com as coisas.")


18

19 imprimir (coisas[1])
20 print(coisa[-1]) # uau! chique
21 imprimir(coisa.pop())
22 print(' '.join(coisas)) # o quê? legal!
23 print('#'.join(stuff[3:5])) # super estelar!

O que você deve ver

Espere, não há 10 coisas nessa lista. Vamos consertar isso.


Adicionando: Garoto
Existem 7 itens agora.
Machine Translated by Google

170 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

Adicionando: Garota
Existem 8 itens agora.
Adicionando: Banana
Existem 9 itens agora.
Adicionando: Milho
Existem 10 itens agora.
Lá vamos nós: ['Maçãs' 'Laranjas' ,'Garota' , 'Corvos' , ' Telefone ' , ' Luz ' ,
,
'Menino' 'Banana' , 'Açúcar'
Vamos ,
fazer algumas , ' Milho ' ]
coisas com essas coisas.
Laranjas
Milho
Milho
Maçãs Laranjas Corvos Telefone Luz Sugar Boy Girl Banana
Telefone# Luz

O que as listas podem fazer

Digamos que você queira criar um jogo de computador baseado em Go Fish. Se você não sabe o que é Go Fish, pegue
agora é hora de ler sobre isso na internet. Para fazer isso, você precisaria ter alguma maneira de tomar
o conceito de “baralho de cartas” e coloque-o em seu programa Python. Você então tem que escrever Python
código que sabe como funcionar essa versão imaginária de um baralho de cartas para que uma pessoa jogando seu
jogo pensa que é real, mesmo que não seja. O que você precisa é de uma estrutura de “baralho de cartas” e de programadores
chame esse tipo de coisa de “estrutura de dados”.

O que é uma estrutura de dados? Se você pensar bem, uma “estrutura de dados” é apenas uma forma formal de estruturar
(organizar) alguns dados (fatos). É realmente muito simples. Mesmo que algumas estruturas de dados possam ficar insanamente
complexos, tudo o que eles são é apenas uma forma de armazenar fatos dentro de um programa para que você possa acessá-los de diferentes maneiras.

caminhos. Eles estruturam dados.

Abordarei mais isso no próximo exercício, mas as listas são uma das estruturas de dados mais comuns
os programadores usam. Eles são simplesmente listas ordenadas de fatos que você deseja armazenar e acessar de forma aleatória ou linear.
por um índice. O que?! Lembre-se do que eu disse, só porque um programador disse “lista é uma lista” não significa
significa que é mais complexo do que uma lista já é no mundo real. Vejamos o baralho de
cartões como exemplo de lista:

1. Você tem um monte de cartas com valores.

2. Essas cartas estão em uma pilha, lista ou lista da carta de cima para a de baixo.

3. Você pode tirar cartas de cima, de baixo e do meio aleatoriamente.

4. Se quiser encontrar uma carta específica, você deve pegar o baralho e examiná-lo um de cada vez.

Vejamos o que eu disse:


Machine Translated by Google

FAZENDO COISAS COM LISTAS 171

“Uma lista ordenada” Sim, o baralho de cartas está em ordem com o primeiro e o último.

”de coisas que você deseja armazenar” Sim, cartões são coisas que eu quero armazenar.

”e acessar aleatoriamente” Sim, posso pegar uma carta de qualquer lugar do baralho.

”ou linearmente” Sim, se eu quiser encontrar um cartão específico posso começar do início e ir na ordem.

”por um índice” Quase, já que com um baralho de cartas se eu lhe dissesse para pegar a carta no índice 19 você teria que contar até encontrar
aquela. Em nossas listas Python, o computador pode simplesmente ir direto para qualquer índice que você fornecer.

Isso é tudo que uma lista faz e deve fornecer uma maneira de descobrir conceitos de programação. Todo conceito de programação geralmente
tem alguma relação com o mundo real. Pelo menos os úteis sim. Se você conseguir descobrir o que é o analógico no mundo real, poderá usar
isso para descobrir o que a estrutura de dados deve ser capaz de fazer.

Quando usar listas

Você usa uma lista sempre que tiver algo que corresponda aos recursos úteis da estrutura de dados da lista:

1. Se você precisar manter a ordem. Lembre-se de que esta é uma ordem listada, não uma ordem classificada . Listas não classificam
para você.

2. Se precisar acessar o conteúdo aleatoriamente por um número. Lembre-se, isso está usando números cardinais
números começando em 0.

3. Se precisar percorrer o conteúdo de forma linear (do primeiro ao último). Lembre-se, é isso que for-loops
são para.

Então é aí que você usa uma lista.

Exercícios de estudo

1. Pegue cada função chamada e siga as etapas das chamadas de função para traduzi-las para
o que Python faz. Por exemplo, more_stuff.pop() é pop(more_stuff).

2. Traduza essas duas formas de visualizar as chamadas de função em inglês. Por exemplo, more_stuff.pop() é lido como “Chame pop em
more_stuff”. Enquanto isso, pop(more_stuff) significa, “Chame pop com argumento more_stuff”. Entenda como eles são realmente a
mesma coisa.
Machine Translated by Google

172 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

3. Leia sobre “programação orientada a objetos” online. Confuso? Eu também estava. Não se preocupe. Você aprenderá o
suficiente para ser perigoso e poderá aprender mais lentamente mais tarde.

4. Leia sobre o que é uma “classe” em Python. Não leia sobre como outras línguas usam a palavra
"aula." Isso só vai atrapalhar você.

5. Não se preocupe se você não tem ideia do que estou falando. Os programadores gostam de se sentir inteligentes, então
inventaram a programação orientada a objetos, chamaram-na de OOP e depois a usaram demais. Se você acha que isso
é difícil, tente usar “programação funcional”.

6. Encontre 10 exemplos de coisas do mundo real que caberiam em uma lista. Tente escrever alguns scripts para
trabalhar com eles.

Perguntas comuns dos alunos

Você não disse para não usar loops while? Sim, então lembre-se que às vezes você pode quebrar as regras se
você tem um bom motivo. Somente os idiotas são escravos das regras o tempo todo.

Por que join(' ', stuff) não funciona? A forma como a documentação do join é escrita não faz sentido. Não funciona assim e, em
vez disso, é um método que você chama na string inserida para colocar entre a lista a ser unida. Reescreva-o como '
'.join(stuff).

Por que você usou um loop while? Tente reescrevê-lo com um loop for e veja se é mais fácil.

O que as coisas[3:5] fazem? Isso extrai uma “fatia” da lista de coisas que vai do elemento 3 ao elemento
4, o que significa que não inclui o elemento 5. É semelhante a como range(3,5) funcionaria.
Machine Translated by Google

FAZENDO COISAS COM LISTAS 173


Machine Translated by Google

174

EXERCÍCIO 39

Dicionários, oh, lindos dicionários


Agora você aprenderá sobre a estrutura de dados do Dicionário em Python. Um Dicionário (ou “dict”) é uma forma de
armazenar dados como uma lista, mas em vez de usar apenas números para obter os dados, você pode usar quase tudo.
Isso permite tratar um dict como se fosse um banco de dados para armazenar e organizar dados.

Vamos comparar o que os dictos podem fazer com o que as listas podem fazer. Veja, uma lista permite que você faça isso:

Exercício 39 Sessão Python

>>> coisas = ['a', 'b', 'c', 'd'] >>>


print(coisas[1]) b >>>

coisas[1] = 'z' >>>


print(coisas[ 1]) [1])
Com

>>> coisas
['a', 'z', 'c', 'd']

Você pode usar números para “indexar” uma lista, o que significa que você pode usar números para descobrir o que está
nas listas. Você já deve saber isso sobre listas, mas certifique-se de entender que só pode usar números para retirar itens
de uma lista.

O que um dict faz é permitir que você use qualquer coisa, não apenas números. Sim, um dict associa uma coisa a outra,
não importa o que seja. Dê uma olhada:

Exercício 39 Sessão Python

>>> coisas = {'nome': 'Zed', 'idade': 39, 'altura': 6 * 12 + 2} >>>


imprimir(coisas['nome'])
Zede

>>> print(coisa['idade']) 39

>>> imprimir(coisa['altura']) 74

>>> coisas['cidade'] = "SF" >>>


print(coisas['cidade'])
SF

Você verá que em vez de apenas números estamos usando strings para dizer o que queremos do dicionário de coisas .
Também podemos colocar coisas novas no dicionário com strings. Não precisa ser cordas. Também podemos fazer isso:
Machine Translated by Google

DICIONÁRIOS, OH ADORÁVEIS DICIONÁRIOS 175

Exercício 39 Sessão Python

>>> coisas[1] = "Uau" >>>


coisas[2] = "Neato" >>>
print(coisas[1])
Uau
>>> imprimir(coisa[2])
Neato

Neste código usei números, e então você pode ver que há números e strings como chaves no ditado quando eu o
imprimo. Eu poderia usar qualquer coisa. Bem, quase, mas finja que você pode usar qualquer coisa por enquanto.

Claro, um dicionário onde você só pode inserir coisas é muito estúpido, então veja como você exclui coisas, com a função
pop() .

Exercício 39 Sessão Python

>>> stuff.pop('cidade')
'SF'
>>> coisas.pop(1)
'Uau'
>>> coisas.pop(2)
'Neato'
>>> coisas
{'nome': 'Zed', 'idade': 39, 'altura': 74}

Um exemplo de dicionário

Faremos agora um exercício que você deve estudar com muito cuidado. Quero que você digite esse código e tente
entender o que está acontecendo. Anote quando você coloca coisas em um dict, obtém-as de um hash e todas as
operações que você usa. Observe como este exemplo mapeia os estados para suas abreviações e, em seguida, as
abreviações para as cidades nos estados. Lembre-se de que “mapear” ou “associar” é o conceito-chave em um dicionário.

ex39.py

1 # crie um mapeamento de estado para abreviar 2 estados =


{
3 'Oregon': 'OU',
4 'Flórida': 'FL',
5 'Califórnia': 'CA',
6 'Nova York': 'NY',
Machine Translated by Google

176 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

7 'Michigan': 'MI'
8}
9

10 # crie um conjunto básico de estados e algumas cidades neles

11 cidades = {
12 'CA': 'São Francisco',
13 'MI': 'Detroit',
14 'FL': 'Jacksonville'
15 }
16

17 # adicione mais algumas cidades


18 cidades['NY'] = 'Nova York'
19 cidades['OR'] = 'Portland'
20

21 # imprima algumas cidades


* 10)
22 print('-' 23
print(" Estado de NY tem: ", cidades['NY'])
24 print("OU Estado tem: ", cidades['OR'])
25

26 # imprima alguns estados


*
27 imprimir('-' 10)
28 print("A abreviatura de Michigan é: ", afirma['Michigan'])
29 print("A abreviatura da Flórida é: ", states['Florida'])
30

31 # faça isso usando o estado e depois o ditado das cidades


* 10)
32 print('-' 33
print("Michigan tem: ", cidades[estados['Michigan']])
34 print("Flórida tem: ", cidades[estados['Flórida']])
35

36 # imprima todas as abreviações de estado


*
37 imprimir('-' 10)
38 para estado, abreviatura em list(states.items()):
39 print(f"{state} é abreviado {abrev}")
40

41 # imprima todas as cidades do estado


*
42 imprimir('-' 10)
43 para abreviatura, cidade na lista(cities.items()):
44 print(f"{abrev} tem a cidade {city}")
45

46 # agora faça as duas coisas ao mesmo tempo


* 10)
47 print('-' 48
para estado, abreviação em list(states.items()):
49 print(f"{state} estado é abreviado {abbrev}")
50 print(f"e tem cidade {cidades[abrev]}")
51
Machine Translated by Google

DICIONÁRIOS, OH ADORÁVEIS DICIONÁRIOS 177

*
52 print('-' 10) 53 #
obtenha com segurança uma abreviação por estado que pode não estar lá 54 state =
states.get('Texas')
55

56 se não indique:
57 print("Desculpe, não é Texas.")
58

59 # obtém uma cidade com um valor padrão 60


city = cidades.get('TX', 'Does Not Exist') 61 print(f"A cidade
para o estado 'TX' é: {city}")

O que você deve ver

Exercício 39 Sessão

$ python3.6 ex39.py
----------
Estado de NY tem: Nova York
OR Estado tem: Portland
----------

A abreviatura de Michigan é: MI
A abreviatura da Flórida é: FL
----------

Michigan tem: Detroit


Flórida tem: Jacksonville
----------

Oregon é abreviado OU
Flórida é abreviada como FL
Califórnia é abreviada como CA
Nova York é abreviada como NY
Michigan é abreviado como MI
----------

CA tem a cidade de São Francisco


MI tem a cidade de Detroit
FL tem a cidade Jacksonville
NY tem a cidade de Nova York
OU tem a cidade Portland
----------

O estado de Oregon é abreviado como


OR e tem a cidade de Portland
O estado da Flórida é abreviado como FL
e tem a cidade de Jacksonville
O estado da Califórnia é abreviado como CA
Machine Translated by Google

178 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

e tem a cidade de São Francisco


O estado de Nova York é abreviado como NY
e tem a cidade de Nova York
O estado de Michigan é abreviado como MI
e tem a cidade de Detroit
----------

Desculpe, não, Texas.


A cidade para o estado 'TX' é: Não Existe

O que os dicionários podem fazer

Os dicionários são outro exemplo de estrutura de dados e, assim como as listas, são uma das estruturas de dados mais
comumente usadas em programação. Um dicionário é usado para mapear ou associar coisas que você deseja armazenar às
chaves necessárias para obtê-las. Novamente, os programadores não usam um termo como “dicionário” para algo que não
funciona como um dicionário cheio de palavras, então vamos usar isso como nosso exemplo do mundo real.

Digamos que você queira descobrir o que significa a palavra “Honorificabilitudinitatibus”. Hoje você simplesmente copiaria e
colaria essa palavra em um mecanismo de busca e então descobriria a resposta, e poderíamos dizer que um mecanismo de
busca é como uma versão enorme e supercomplexa do Oxford English Dictionary (OED). Antes dos motores de busca, o que
você faria é o seguinte:

1. Vá até sua biblioteca e pegue o “dicionário”. Digamos que seja o OED.

2. Você sabe que “honorificabilitudinitatibus” começa com a letra 'H', então você olha na lateral do
reserve para a pequena aba que tem 'H'.

3. Em seguida, você folheia as páginas até chegar perto de onde “querido” começou.

4. Então você folhearia mais algumas páginas até encontrar “honorificabilitudinitatibus” ou chegaria ao início das palavras
“hp” e perceberia que essa palavra não está no OED.

5. Depois de encontrar a entrada, você lerá a definição para descobrir o que ela significa.

Este processo é quase exatamente como funciona um dict, e você está basicamente “mapeando” a palavra “honori-
ficabilitudinitatibus” para sua definição. Um dict em Python é como um dicionário do mundo real, como o OED.

Exercícios de estudo

1. Faça esse mesmo tipo de mapeamento com cidades e estados/regiões do seu país ou de algum outro país.
Machine Translated by Google

DICIONÁRIOS, OH ADORÁVEIS DICIONÁRIOS 179

2. Encontre a documentação do Python para dicionários e tente fazer ainda mais coisas com eles.

3. Descubra o que você não pode fazer com dicionários. Um grande problema é que eles não têm ordem, então tente
brincando com isso.

Perguntas comuns dos alunos

Qual é a diferença entre uma lista e um dicionário? Uma lista é uma lista ordenada de itens. Um dicionário
(ou dict) serve para combinar alguns itens (chamados de “chaves”) com outros itens (chamados de “valores”).

Para que eu usaria um dicionário? Quando você tem que pegar um valor e “procurar” outro valor. Em
na verdade, você poderia chamar os dicionários de “tabelas de consulta”.

Para que eu usaria uma lista? Use uma lista para qualquer sequência de coisas que precisam estar em ordem, e você só
precisa procurá-los por um índice numérico.

E se eu precisar de um dicionário, mas precisar que ele esteja em ordem? Dê uma olhada na estrutura de dados
Collections.OrderedDict em Python. Pesquise on-line para encontrar a documentação.
Machine Translated by Google

180

EXERCÍCIO 40

Módulos, classes e objetos


Python é chamado de “linguagem de programação orientada a objetos”. Isso significa que existe uma construção em Python
chamada classe que permite estruturar seu software de uma maneira específica. Usando classes, você pode adicionar consistência
aos seus programas para que eles possam ser usados de maneira mais limpa. Pelo menos essa é a teoria.

Agora vou ensinar a você o início da programação, classes e objetos orientados a objetos usando o que você já sabe sobre
dicionários e módulos. Meu problema é que a programação orientada a objetos (OOP) é simplesmente estranha. Você tem que
lutar com isso, tentar entender o que eu digo aqui, digitar o código e no próximo exercício eu irei martelá-lo.

Aqui vamos nós.

Módulos são como dicionários


Você sabe como um dicionário é criado e usado e que é uma forma de mapear uma coisa para outra. Isso significa que se você
tiver um dicionário com a chave “maçã” e quiser obtê-lo, faça o seguinte:

ex40a.py

1 mystuff = {'apple': "EU SOU MAÇÃS!"} 2


print(mystuff['apple'])

Mantenha essa ideia de “tirar X de Y” na cabeça e agora pense em módulos. Você fez alguns até agora e deve saber que são:

1. Um arquivo Python com algumas funções ou variáveis.

2. Você importa esse arquivo.

3. E você pode acessar as funções ou variáveis nesse módulo com o arquivo . operador (ponto).

Imagine que eu tenho um módulo que decido chamar de mystuff.py e coloquei nele uma função chamada apple. Aqui está o
módulo mystuff.py:

mystuff.py

1 def apple():
2 print("EU SOU MAÇÃS!")
Machine Translated by Google

MÓDULOS, AULAS E OBJETOS 181

Depois de ter esse código, posso usar o módulo MyStuff com import e depois acessar a função apple :

ex40a.py

1 importar minhas
coisas 2 minhas coisas.apple()

Eu também poderia colocar uma variável chamada tangerina:

ex40a.py

1 def apple():
2 print("EU SOU MAÇÃS!")
3

4 # isso é apenas uma variável 5 tangerina


= “Reflexo vivo de um sonho”

Posso acessar isso da mesma maneira:

ex40a.py

1 importar minhas coisas


2

3 mystuff.apple() 4
print(mystuff.tangerine)

Consulte o dicionário e você começará a ver como isso é semelhante ao uso de um dicionário, mas a sintaxe é diferente. Vamos
comparar:

ex40a.py

1 mystuff['apple'] # obtém a maçã do dict 2 mystuff.apple() #


obtém a maçã do módulo 3 mystuff.tangerine # a mesma coisa, é
apenas uma variável

Isso significa que temos um padrão muito comum em Python:

1. Pegue um contêiner de estilo chave = valor.

2. Obtenha algo pelo nome da chave.

No caso do dicionário, a chave é uma string e a sintaxe é [chave]. No caso do módulo, a chave é um identificador e a sintaxe é .key.
Fora isso, eles são quase a mesma coisa.
Machine Translated by Google

182 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

40.1.1 As aulas são como módulos

Você pode pensar em um módulo como um dicionário especializado que pode armazenar código Python para que você possa acessá-
lo com o arquivo . operador. Python também possui outra construção que serve a um propósito semelhante, chamada classe. Uma

classe é uma forma de agrupar funções e dados e colocá-los dentro de um contêiner para que você possa acessá-los com o arquivo .
operador (ponto).

Se eu fosse criar uma classe como o módulo mystuff , faria algo assim:

ex40a.py

1 classe MyStuff (objeto):


2

3 def __init__(self):
4 self.tangerine = "E agora mil anos entre"
5

6 def apple(self): print("EU


7 SOU MAÇÃS DE CLASSE!")

Isso parece complicado comparado aos módulos, e definitivamente há muita coisa acontecendo em comparação, mas você deve ser
capaz de entender como isso é como um “minimódulo” com MyStuff tendo uma função apple() nele. O que provavelmente é confuso
é a função __init__() e o uso de self.tangerine para definir a variável de instância tangerina .

Veja por que classes são usadas em vez de módulos: Você pode pegar esta classe MyStuff e usá-la para criar muitos deles, milhões
de cada vez, se quiser, e cada um deles não interferirá um no outro. Quando você importa um módulo, há apenas um para todo o
programa, a menos que você faça alguns truques monstruosos.

Antes que você possa entender isso, você precisa saber o que é um “objeto” e como trabalhar com MyStuff da mesma forma que faz
com o módulo mystuff.py .

40.1.2 Objetos são como importação

Se uma classe é como um “minimódulo”, então deve haver um conceito semelhante ao de importação , mas para classes. Esse
conceito é chamado de “instanciar”, que é apenas uma maneira sofisticada, desagradável e excessivamente inteligente de dizer “criar”.
Quando você instancia uma classe, o que você obtém é chamado de objeto.

Você instancia (cria) uma classe chamando-a como se fosse uma função, assim:

ex40a.py

1 coisa = MinhasCoisas() 2
coisa.apple() 3
print(coisa.tangerine)
Machine Translated by Google

MÓDULOS, AULAS E OBJETOS 183

A primeira linha é a operação “instanciar” e é muito parecida com chamar uma função. Entretanto, Python coordena
uma sequência de eventos para você nos bastidores. Seguirei estas etapas usando o código anterior para MyStuff:

1. Python procura MyStuff() e vê que é uma classe que você definiu.

2. Python cria um objeto vazio com todas as funções que você especificou na classe usando def.

3. Python então verifica se você criou uma função __init__ “mágica” e, se tiver, chama isso
função para inicializar seu objeto vazio recém-criado.

4. Na função MyStuff __init__ eu obtenho essa variável extra self, que é aquele objeto vazio que o Python fez para
mim, e posso definir variáveis nele exatamente como você faria com um módulo, dicionário ou outro objeto.

5. Nesse caso, configurei self.tangerine para a letra de uma música e então inicializei esse objeto.

6. Agora o Python pode pegar esse objeto recém-criado e atribuí-lo à variável thing para eu trabalhar
com.

Esse é o básico de como o Python faz essa “mini-importação” quando você chama uma classe como uma função.
Lembre-se de que isso não significa dar a você a classe, mas sim usá-la como um modelo para construir uma cópia
desse tipo de coisa.

Lembre-se de que estou lhe dando uma ideia um pouco imprecisa de como isso funciona, para que você possa
começar a compreender as aulas com base no que sabe sobre os módulos. A verdade é que classes e objetos
divergem repentinamente dos módulos neste ponto. Se eu fosse totalmente honesto, diria algo mais parecido com isto:

• As aulas são como modelos ou definições para a criação de novos minimódulos.

• Instanciação é como você cria um desses minimódulos e o importa ao mesmo tempo. "Em-
stantiate” significa apenas criar um objeto a partir da classe.

• O minimódulo criado resultante é chamado de objeto e você então o atribui a uma variável para funcionar
com isso.

Neste ponto, os objetos se comportam de maneira diferente dos módulos, e isso deve servir apenas como uma forma
de você passar para a compreensão de classes e objetos.

40.1.3 Obtendo coisas das coisas

Agora tenho três maneiras de obter coisas das coisas:


Machine Translated by Google

184 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

ex40a.py

1 # dict estilo 2
coisas minhas['maçãs']
3

4 # estilo do módulo
5 mystuff.apples() 6
print(mystuff.tangerine)
7

8 # estilo de classe
9 thing = MyStuff() 10
thing.apples() 11
print(thing.tangerine)

40.1.4 Um Exemplo de Primeira Classe

Você deve começar a ver as semelhanças nesses três tipos de contêineres chave=valor e provavelmente terá
um monte de perguntas. Continue com as perguntas, pois o próximo exercício irá aprofundar seu “vocabulário
orientado a objetos”. Neste exercício, quero apenas que você digite este código e faça-o funcionar para que
você tenha alguma experiência antes de prosseguir.

ex40.py

1 classe Canção (objeto):


2

3 def __init__(self, letra): self.lyrics


4 = letra
5

6 def sing_me_a_song(self):
7 para linha em self.lyrics:
8 print(line)
9

10 happy_bday = Song(["Parabéns para você",


11 “Não quero ser processado”,
12 "Então vou parar por aí"])
13

14 bulls_on_parade = Song(["Eles se reúnem em torno da família",


15 "Com os bolsos cheios de conchas"])
16

17feliz_bday.sing_me_a_song ()
18

19 touros_on_parade.sing_me_a_song()
Machine Translated by Google

MÓDULOS, AULAS E OBJETOS 185

O que você deve ver


Exercício 40 Sessão

$ python3.6 ex40.py
Parabéns para você Eu
não quero ser processado
Então vou parar por aí Eles se
reúnem em torno da família Com os
bolsos cheios de conchas

Exercícios de estudo

1. Escreva mais algumas músicas usando isso e certifique-se de entender que está passando uma lista de
cordas como a letra.

2. Coloque a letra em uma variável separada e passe essa variável para a classe usar.

3. Veja se você consegue hackear isso e fazer com que ele faça mais coisas. Não se preocupe se você não tem ideia de como, apenas
experimente, veja o que acontece. Quebre, jogue fora, destrua, você não pode machucá-lo.

4. Pesquise online por “programação orientada a objetos” e tente transbordar seu cérebro com o que você lê. Não se
preocupe se isso não fizer absolutamente nenhum sentido para você. Metade dessas coisas também não faz sentido
para mim.

Perguntas comuns dos alunos

Por que preciso de self quando faço __init__ ou outras funções para classes? Se você não possui o self, então um código
como cheese = 'Frank' é ambíguo. Esse código não está claro se você se refere ao atributo cheese da instância ou a
uma variável local chamada cheese. Com self.cheese = 'Frank' é
muito claro que você se refere ao atributo de instância self.cheese.
Machine Translated by Google

186

EXERCÍCIO 41

Aprendendo a falar orientado a objetos


Neste exercício vou te ensinar como falar “orientado a objetos”. O que farei é fornecer um pequeno conjunto de palavras com
definições que você precisa saber. Então darei a você um conjunto de frases com lacunas que você terá que entender. Por fim,
darei a você um grande conjunto de exercícios que você deverá realizar para tornar essas frases sólidas em seu vocabulário.

Exercícios de palavras

class Diga ao Python para criar um novo tipo de coisa.

objeto Dois significados: o tipo mais básico de coisa e qualquer instância de alguma coisa.

instância O que você obtém quando diz ao Python para criar uma classe.

def Como você define uma função dentro de uma classe.

self Dentro das funções de uma classe, self é uma variável para a instância/objeto que está sendo acessada.

herança O conceito de que uma classe pode herdar características de outra classe, assim como você e seu
pais.

composição O conceito de que uma classe pode ser composta de outras classes como peças, da mesma forma que um carro
tem rodas.

atributo Uma propriedade que as classes possuem que são de composição e geralmente são variáveis.

is-a Uma frase para dizer que algo herda de outro, como em um “salmão” é um “peixe”.

has-a Uma frase para dizer que algo é composto de outras coisas ou tem uma característica, como em “um salmão tem-a
boca."

Reserve algum tempo para fazer cartões de memória para esses termos e memorizá-los. Como sempre, isso não vai adiantar muito

faz muito sentido até terminar este exercício, mas primeiro você precisa conhecer as palavras básicas.

Exercícios de frases

A seguir, tenho uma lista de trechos de código Python à esquerda e as frases em inglês para eles:
Machine Translated by Google

APRENDENDO A FALAR ORIENTADO A OBJETOS 187

class X(Y) ”Faça uma classe chamada X que seja um Y.”

classe X (objeto): def __init__ (self, J) ”a classe X possui um __init__ que usa os parâmetros self e J.”

class X(objeto): def M(self, J) ”a classe X possui uma função chamada M que recebe os parâmetros self e J.”

foo = X() ”Defina foo para uma instância da classe X.”

foo.M(J) ”De foo, obtenha a função M e chame-a com os parâmetros self, J.”

foo.K = Q ”De foo, obtenha o atributo K e defina-o como Q.”

Em cada um deles, onde você vê X, Y, M, J, K, Q e foo, você pode tratá-los como espaços em branco. Por exemplo, também posso
escrever essas frases da seguinte forma:

1. ”Faça uma classe chamada ??? isso é um Y.

2. ”classe ??? has-a __init__ que leva self e ??? parâmetros.”

3. ”classe ??? tem uma função chamada ??? isso leva a si mesmo e ??? parâmetros.”

4. ”Definir ??? para uma instância da classe ???.”

5. ”De ???, pegue o ??? função e chame-a com self=??? e parâmetros ???.”

6. ”De ???, pegue o ??? atributo e defina-o como ???.”

Novamente, escreva isso em alguns cartões de memória flash e perfure-os. Coloque o trecho de código Python na frente e a frase no
verso. Você tem que ser capaz de dizer a frase exatamente da mesma forma sempre que vir essa forma. Não é o mesmo, mas
exatamente o mesmo.

Exercícios Combinados

A preparação final para você é combinar as palavras exercícios com as frases exercícios. O que eu quero que você faça para este
exercício é o seguinte:

1. Pegue um cartão com frases e perfure-o.

2. Vire-o e leia a frase, e para cada palavra da frase que está em suas palavras, faça exercícios,
pegue esse cartão.

3. Perfure essas palavras para aquela frase.

4. Continue até ficar entediado, depois faça uma pausa e faça novamente.
Machine Translated by Google

188 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

Um teste de leitura

Agora tenho um pequeno script de hack em Python que irá treiná-lo com essas palavras que você conhece de uma maneira infinita.

Este é um script simples que você deve ser capaz de descobrir, e a única coisa que ele faz é usar uma biblioteca chamada

urllib para baixar uma lista de palavras que possuo. Aqui está o script, que você deve inserir em oop_test.py
para trabalhar com isso:

ex41.py

1 importação aleatória
2 de urllib.request importar urlopen
3 sistemas de importação
4

5 WORD_URL = "http://learncodethehardway.org/words.txt"
6 PALAVRAS = []
7

8 FRASES = {
9 "aula %%%(%%%):":
10 "Faça uma classe chamada %%% que seja %%%",
11
"class %%%(objeto):\n\tdef __init__(self, ***)" :
12 "a classe %%% possui um __init__ que leva parâmetros self e ***.",
13
"classe %%%(objeto):\n\tdef ***(self, @@@)":
14
"classe %%% tem uma função *** que usa parâmetros self e @@@.",
15
"*** =%%%()":
16 "Definir *** para uma instância da classe %%%",
17 "***.***(@@@)":
18 "De *** obtenha a função ***, chame-a com os parâmetros self, @@@.",
19 "***.*** = '***'":
20 "De *** pegue o atributo *** e defina-o como '***'."
21 }
22

23 # eles querem detalhar as frases primeiro


24 se len(sys.argv) == 2 e sys.argv[1] == "inglês":
25 PHRASE_FIRST = Verdadeiro
26 mais:
27 PHRASE_FIRST = Falso
28

29 # carregue as palavras do site


30 para palavra em urlopen(WORD_URL).readlines():
31
PALAVRAS.append(str(word.strip(), encoding="utf-8"))
32

33

34 def convert(fragmento, frase):


35
class_names = [w.capitalize() para w em
Machine Translated by Google

APRENDENDO A FALAR ORIENTADO A OBJETOS 189

36 random.sample(PALAVRAS, snippet.count("%%%"))]
37 outros_nomes = random.sample(WORDS, snippet.count("***"))
38 resultados = []
39 nomes_param = []
40

41 para i no intervalo(0, snippet.count("@@@")):


42 param_count = random.randint(1,3)
43 param_names.append(', '.join(
44 random.sample(PALAVRAS, param_count)))
45

46 para frase em snippet, frase:


47 # é assim que você duplica uma lista ou string
48 resultado = sentença[:]
49

50 #nomes de classe falsos


51 para palavra em class_names:
52 resultado = resultado.replace("%%%", palavra, 1)
53

54 #falsificar outros nomes


55 para palavra em outros_nomes:
56 resultado = resultado.replace("***", palavra, 1)
57

58 # listas de parâmetros falsas


59 para palavra em param_names:
60 resultado = resultado.replace("@@@", palavra, 1)
61

62 resultados.append(resultado)
63

64 retornar resultados
65

66

67 # continue até apertar CTRL-D


68 tente:
69 enquanto Verdadeiro:

70 trechos = lista(FRASES.keys())
71 random.shuffle(fragmentos)
72

73 para trecho em trechos:


74 frase = FRASES[trecho]
75 pergunta, resposta = converter(snippet, frase)
76 se PHRASE_FIRST:
77 pergunta, resposta = resposta, pergunta
78

79 imprimir(pergunta)
80
Machine Translated by Google

190 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

81 input("> ")
82 print(f"RESPOSTA: {resposta}\n\n")
83 exceto EOFError:
84 print("\nTchau")

Execute este script e tente traduzir as “frases orientadas a objetos” para traduções em inglês. Você verá que o ditado PHRASES
possui as duas formas e basta inserir a correta.

Pratique inglês para codificar

A seguir você deve executar o script com a opção “inglês” para realizar o drill da operação inversa:

$python oop_test. em inglês sh

Lembre-se de que essas frases usam palavras sem sentido. Parte de aprender a ler bem o código é parar de atribuir tanto
significado aos nomes usados para variáveis e classes. Muitas vezes as pessoas leem uma palavra como “Cork” e de repente
ficam descarriladas porque essa palavra as confunde sobre o significado. No exemplo acima, “Cork” é apenas um nome
arbitrário escolhido para uma classe. Não atribua nenhum outro significado a isso e, em vez disso, trate-o como os padrões
que lhe dei.

Lendo mais código

Agora você partirá em uma nova busca para ler ainda mais código, para ler as frases que acabou de aprender no código que
leu. Você irá procurar todos os arquivos com classes e depois fazer o seguinte:

1. Para cada classe dê seu nome e de quais outras classes ela herda.

2. Abaixo disso, liste todas as funções que possui e os parâmetros que elas utilizam.

3. Liste todos os atributos que ele usa.

4. Para cada atributo, indique a classe em que esse atributo pertence.

O objetivo é passar pelo código real e começar a aprender a “combinar os padrões” das frases que você acabou de aprender
com a forma como elas são usadas. Se você perfurar isso o suficiente, começará a ver esses padrões gritando para você no
código, enquanto antes eles pareciam apenas espaços em branco que você não conhecia.
Machine Translated by Google

APRENDENDO A FALAR ORIENTADO A OBJETOS 191

Perguntas comuns dos alunos

O que result = sentença[:] faz? Essa é uma maneira Python de copiar uma lista. Você está usando a fatia da lista
sintaxe [:] para efetivamente fazer uma fatia do primeiro ao último elemento.

Este script é difícil de executar! Neste ponto, você deverá ser capaz de digitar isso e fazê-lo funcionar. Ele tem alguns pequenos truques
aqui e ali, mas não há nada de complexo nisso. Basta fazer tudo o que você aprendeu até agora para depurar scripts. Digite cada
linha, confirme se é exatamente igual à minha e pesquise tudo o que você não conhece online.

Ainda é muito difícil! Você consegue fazer isso. Vá bem devagar, caractere por caractere se for necessário, mas digite
exatamente e descobrir o que ele faz.
Machine Translated by Google

192

EXERCÍCIO 42

É-A, Tem-A, Objetos e Classes


Um conceito importante que você precisa entender é a diferença entre uma classe e um objeto. O problema é que não existe
“diferença” real entre uma classe e um objeto. Na verdade, eles são a mesma coisa em momentos diferentes. Vou demonstrar
através de um koan Zen:

Qual é a diferença entre um peixe e um salmão?

Essa pergunta meio que confundiu você? Realmente sente-se e pense sobre isso por um minuto. Quer dizer, um peixe e um salmão
são diferentes, mas espere, são a mesma coisa, certo? O salmão é um tipo de peixe, então quero dizer que não é diferente. Mas,
ao mesmo tempo, o salmão é um tipo específico de peixe, por isso é diferente de todos os outros peixes. É isso que o torna um
salmão e não um linguado. Então, um salmão e um peixe são iguais, mas
diferente. Esquisito.

Esta questão é confusa porque a maioria das pessoas não pensa sobre as coisas reais desta forma, mas elas as compreendem
intuitivamente. Você não precisa pensar na diferença entre um peixe e um salmão porque sabe como eles estão relacionados. Você
sabe que o salmão é um tipo de peixe e que existem outros tipos de peixe sem precisar entender isso.

Vamos dar um passo adiante. Digamos que você tenha um balde cheio de três salmões e, por ser uma pessoa legal, decidiu chamá-
los de Frank, Joe e Mary. Agora pense nesta questão:

Qual é a diferença entre Maria e um salmão?

Novamente, esta é uma pergunta estranha, mas é um pouco mais fácil do que a questão do peixe versus salmão. Você sabe que
Mary é um salmão, então ela não é realmente diferente. Ela é apenas uma “instância” específica de salmão. Joe e Frank também
são exemplos de salmão. O que quero dizer quando digo instância? Quero dizer, eles foram criados a partir de algum outro salmão
e agora representam algo real com atributos semelhantes aos do salmão.

Agora, a ideia alucinante: Fish é uma classe, Salmon é uma classe e Mary é um objeto. Pense nisso por um segundo. Vamos
decompô-lo lentamente e ver se você entende.

Um peixe é uma classe, o que significa que não é uma coisa real , mas sim uma palavra que atribuímos a instâncias de coisas com
atributos semelhantes. Tem barbatanas? Tem guelras? Vive na água? Tudo bem, provavelmente é um peixe.

Alguém com Ph.D. então chega e diz: “Não, meu jovem amigo, este peixe é na verdade Salmo salar, carinhosamente conhecido
como salmão”. Este professor acaba de esclarecer melhor o peixe e criou uma nova classe chamada “Salmão” que possui atributos
mais específicos. Nariz mais comprido, polpa avermelhada, grande, vive no oceano ou em água doce, gostoso? Provavelmente um
salmão.

Finalmente, um cozinheiro chega e diz ao Ph.D.: “Não, você está vendo este salmão bem aqui, vou chamá-lo de Mary e vou fazer
dele um filé saboroso com um molho gostoso”. Agora você tem esta instância de um salmão (que também é uma instância de um
peixe) chamada Maria transformada em algo real que está enchendo sua barriga. Tornou-se um objeto.

Aí está: Maria é uma espécie de salmão que é uma espécie de peixe - objeto é uma classe é uma classe.
Machine Translated by Google

É-A, TEM-A, OBJETOS E CLASSES 193

Como isso aparece no código

Este é um conceito estranho, mas para ser sincero, você só precisa se preocupar com isso quando fizer novos
classes e quando você usa uma classe. Vou mostrar dois truques para ajudá-lo a descobrir se algo está
uma classe ou um objeto.

Primeiro, você precisa aprender duas frases de efeito “é um” e “tem um”. Você usa a frase é-a quando fala
sobre objetos e classes estarem relacionados entre si por um relacionamento de classe. Você usa has-a quando você
fale sobre objetos e classes que estão relacionados apenas porque fazem referência entre si.

Agora, analise este trecho de código e substitua cada ##?? comente com um comentário que diga se
a próxima linha representa um relacionamento é-a ou tem-um e qual é esse relacionamento. No início de
o código, coloquei alguns exemplos, então você só precisa escrever os restantes.

Lembre-se, is-a é a relação entre peixe e salmão, enquanto has-a é a relação entre
salmão e guelras.

ex42.py

1 ## Animal é um objeto (sim, meio confuso) veja o crédito extra


Animal de 2 classes (objeto):
3
passar
4

5 ## ??
Cão de 6 classes (Animal):
7

8 def __init__(self, nome):


9 ## ??
10 self.name = nome
11

12 ## ??
13 classe Gato(Animal):
14

15 def __init__(self, nome):


16 ## ??
17 self.name = nome
18

19 ## ??
Pessoa de 20 classes (objeto):
21

22 def __init__(self, nome):


23 ## ??
24 self.name = nome
25

26
## A pessoa tem algum tipo de animal de estimação
Machine Translated by Google

194 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

27 self.pet = Nenhum
28

29 ## ??
Funcionário da classe 30 (Pessoa):
31

32 def __init__(próprio, nome, salário):


33 ## ?? hmm, o que é essa magia estranha?
34 super(Funcionário, self).__init__(nome) ## ??
35

36 self.salary = salário
37

38 ## ??
Classe 39 Peixe (objeto):
40 passar
41

42 ## ??
Salmão classe 43 (peixe):
44 passar
45

46 ## ??
Classe 47 Halibut (Peixe):
48 passar
49

50

51 ## rover é-um Cachorro


52 rover = Cachorro("Rover")
53

54 ## ??
55 satanás = Gato("Satanás")
56

57 ## ??
58 Maria = Pessoa("Maria")
59

60 ## ??
61 mary.pet = satanás
62

63 ## ??
64 frank = Funcionário("Frank", 120000)
65

66 ## ??
67 frank.pet = rover
68

69 ## ??
70 nadadeira = Peixe()
71
Machine Translated by Google

É-A, TEM-A, OBJETOS E CLASSES 195

72 ## ??
73 crouse = salmão()
74

75 ## ??
76 Harry = Halibut()

Sobre o nome da classe (objeto)

No Python 3 você não precisa adicionar o (objeto) após o nome da classe, mas a comunidade Python acredita em “explícito é
melhor que implícito”, então eu e outros especialistas em Python decidimos incluí-lo. Você pode encontrar código que não possui
(objeto) após classes simples, e essas classes são perfeitamente adequadas e funcionarão com classes que você cria e que
possuem (objeto). Neste ponto, é simplesmente uma documentação extra e não tem impacto no funcionamento das suas aulas.

No Python 2 havia uma diferença entre os dois tipos de classes, mas agora você não precisa se preocupar com isso. A única parte
complicada de usar (objeto) envolve a ginástica mental de dizer “o nome da classe é uma classe do tipo objeto”. Isso pode parecer
confuso para você agora, já que é uma classe cujo nome é objeto que é uma classe, mas não se sinta mal por isso. Basta pensar
no nome da classe (objeto) como dizendo “esta é uma classe simples e básica” e você ficará bem.

Finalmente, no futuro os estilos e gostos dos programadores Python podem mudar e este uso explícito de (objeto) pode ser visto
como um sinal de que você é um mau programador. Se isso acontecer, simplesmente pare de usá-lo ou diga a eles: “Python Zen
diz que explícito é melhor que implícito”.

Exercícios de estudo

1. Pesquise por que o Python adicionou essa classe de objeto estranha e o que isso significa.

2. É possível usar uma classe como se fosse um objeto?

3. Preencha os animais, peixes e pessoas neste exercício com funções que os levem a fazer coisas. Ver
o que acontece quando as funções estão em uma “classe base” como Animal versus, digamos, Dog.

4. Encontre o código de outras pessoas e resolva todos os relacionamentos é-um e tem-um.

5. Faça alguns novos relacionamentos que sejam listas e dicionários para que você também possa ter “tem muitos”
relacionamentos.

6. Você acha que existe um relacionamento “são muitos”? Leia sobre “herança múltipla”
então evite-o se puder.
Machine Translated by Google

196 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

Perguntas comuns dos alunos

Quem são esses ## ?? comentários para? Esses são comentários de “preencher as lacunas” que você deve preencher com os
conceitos corretos de “é um”, “tem um”. Leia este exercício novamente e veja os outros comentários para ver o que quero
dizer.

Qual é o objetivo de self.pet = None? Isso garante que o atributo self.pet dessa classe seja
definido como padrão Nenhum.

O que super(Employee, self).__init__(nome) faz? É assim que você pode executar o método __init__ de uma classe pai de forma
confiável. Procure por “python3.6 super” e leia os vários conselhos sobre isso ser mau e bom para você.
Machine Translated by Google

É-A, TEM-A, OBJETOS E CLASSES 197


Machine Translated by Google

198

EXERCÍCIO 43

Análise e Design Básico Orientado a Objetos

Vou descrever um processo para usar quando você quiser construir algo usando Python, especificamente com programação
orientada a objetos (OOP). O que quero dizer com “processo” é que darei a você um conjunto de etapas que você executa em
ordem, mas das quais você não deve ser escravo ou que sempre funcionará totalmente para todos os problemas. Eles são
apenas um bom ponto de partida para muitos problemas de programação e não devem ser considerados a única forma de
resolver esses tipos de problemas. Este processo é apenas uma maneira de fazer isso que você pode seguir.

O processo é como se segue:

1. Escreva ou desenhe sobre o problema.

2. Extraia os conceitos-chave de 1 e pesquise-os.

3. Crie uma hierarquia de classes e um mapa de objetos para os conceitos.

4. Codifique as classes e faça um teste para executá-las.

5. Repita e refine.

A maneira de encarar esse processo é que ele é “de cima para baixo”, o que significa que ele começa com uma ideia muito
abstrata e vaga e depois a refina lentamente até que a ideia seja sólida e algo que você possa codificar.

Começo apenas escrevendo sobre o problema e tentando pensar em tudo que posso sobre ele. Talvez eu até desenhe um ou
dois diagramas, talvez algum tipo de mapa, ou até mesmo escreva uma série de e-mails descrevendo o problema. Isso me dá
uma maneira de expressar os conceitos-chave do problema e também de explorar o que já posso saber sobre ele.

Em seguida, analiso essas notas, desenhos e descrições e retiro os conceitos-chave. Há um truque simples para fazer isso: basta
fazer uma lista de todos os substantivos e verbos em seus escritos e desenhos e, em seguida, escrever como eles estão
relacionados. Isso me dá uma boa lista de nomes para classes, objetos e funções na próxima etapa. Pego esta lista de conceitos
e pesquiso aqueles que não entendo para poder refiná-los ainda mais, se necessário.

Depois de ter minha lista de conceitos, crio um esboço/árvore simples dos conceitos e como eles estão relacionados como
classes. Geralmente você pode pegar sua lista de substantivos e começar a perguntar “Este é como outros substantivos conceituais?
Isso significa que eles têm uma classe pai comum, então como ela se chama?” Continue fazendo isso até ter uma hierarquia de
classes que seja apenas uma simples lista em árvore ou um diagrama. Então pegue os verbos que você tem e veja se esses são
nomes de funções para cada classe e coloque-os em sua árvore.
Machine Translated by Google

ANÁLISE E PROJETO ORIENTADO A OBJETOS BÁSICOS 199

Com essa hierarquia de classes definida, sento-me e escrevo um esqueleto de código básico que contém apenas as classes,
suas funções e nada mais. Em seguida, escrevo um teste que executa esse código e garante que as classes que criei façam
sentido e funcionem corretamente. Às vezes, posso escrever o teste primeiro, e outras vezes, posso escrever um pequeno
teste, um pequeno código, um pequeno teste, etc., até ter tudo construído.

Por fim, continuo repetindo esse processo, repetindo-o e refinando-o à medida que prossigo e deixando-o o mais claro
possível antes de fazer mais implementações. Se eu ficar preso em alguma parte específica por causa de um conceito ou
problema que não previ, então me sento e começo o processo apenas naquela parte para descobrir mais antes de continuar.

Agora passarei por esse processo enquanto crio um mecanismo de jogo e um jogo para este exercício.

A análise de um mecanismo de jogo simples

O jogo que quero fazer se chama “Gothons from Planet Percal #25” e será um pequeno jogo de aventura espacial. Com
nada mais do que esse conceito em mente, posso explorar a ideia e descobrir como dar vida ao jogo.

43.1.1 Escreva ou desenhe sobre o problema

Vou escrever um pequeno parágrafo para o jogo:

“Alienígenas invadiram uma nave espacial e nosso herói tem que passar por um labirinto de salas para derrotá-los para que
ele possa escapar para uma cápsula de fuga para o planeta abaixo. O jogo será mais parecido com um jogo do tipo Zork ou
Aventura, com saídas de texto e maneiras engraçadas de morrer. O jogo envolverá um motor que roda um mapa cheio de
salas ou cenas. Cada sala imprimirá sua própria descrição quando o jogador entrar nela e então informará ao motor qual sala
será a próxima a sair do mapa.”

Neste ponto eu tenho uma boa ideia do jogo e de como ele funcionaria, então agora quero descrever cada
cena:

Morte É quando o jogador morre e deve ser algo engraçado.

Corredor Central Este é o ponto de partida e já tem um Gothon parado que os jogadores devem derrotar com uma piada
antes de continuar.

Arsenal de armas a laser É aqui que o herói recebe uma bomba de nêutrons para explodir a nave antes de chegar à cápsula
de fuga. Possui um teclado pelo qual o herói deve adivinhar o número.

A Ponte Outra cena de batalha com um Gothon onde o herói coloca a bomba.

Cápsula de Fuga Onde o herói escapa, mas somente depois de adivinhar a cápsula de fuga correta.

Neste ponto, posso desenhar um mapa deles, talvez escrever mais descrições de cada cômodo – o que vier à mente enquanto
exploro o problema.
Machine Translated by Google

200 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

43.1.2 Extraia conceitos-chave e pesquise-os

Agora tenho informações suficientes para extrair alguns dos substantivos e analisar sua hierarquia de classes. Primeiro faço
uma lista de todos os substantivos:

• Estrangeiro

• Jogador

• Enviar

• Labirinto

• Sala

• Cena

• Gotão

• Viagem de fuga

• Planeta

• Mapa

• Motor

• Morte

• Corredor Central

• Arsenal de Armas Laser

• A Ponte

Eu também possivelmente examinaria todos os verbos e veria se eles são algo que possa ser um bom nome de função, mas
vou pular isso por enquanto.

Neste ponto, você também pode pesquisar cada um desses conceitos e qualquer coisa que não saiba no momento.
Por exemplo, posso jogar alguns desses tipos de jogos e saber como eles funcionam. Posso pesquisar como os navios são
projetados ou como funcionam as bombas. Talvez eu pesquise alguma questão técnica como armazenar o estado do jogo em
um banco de dados. Depois de fazer essa pesquisa, posso recomeçar na etapa 1 com base nas novas informações que
possuo, reescrever minha descrição e extrair novos conceitos.
Machine Translated by Google

ANÁLISE E PROJETO BÁSICOS ORIENTADOS A OBJETOS 201

43.1.3 Criar uma hierarquia de classes e um mapa de objetos para os conceitos

Depois de conseguir isso, transformo-o em uma hierarquia de classes perguntando "O que é semelhante a outras coisas?" Também
pergunto: “O que é basicamente apenas mais uma palavra para outra coisa?”

Imediatamente vejo que “Room” e “Scene” são basicamente a mesma coisa dependendo de como eu quero fazer
as coisas. Vou escolher “Cena” para este jogo. Então vejo que todas as salas específicas como “Corredor Central”
são basicamente apenas cenas. Vejo também que a Morte é basicamente uma Cena, o que confirma minha
escolha de “Cena” em vez de “Quarto”, já que você pode ter uma cena de morte, mas uma sala de morte é meio
estranha. “Maze” e “Map” são basicamente iguais, então vou usar “Map”, já que o uso com mais frequência. Não
quero fazer um sistema de batalha, então vou ignorar “Alien” e “Player” e guardar isso para mais tarde. O “Planeta”
também poderia ser apenas mais uma cena em vez de algo específico.

Depois de todo esse processo de pensamento, começo a fazer uma hierarquia de classes parecida com esta em meu editor de texto:

* Mapa
* Motor
* Cena
* Morte
* Corredor Central
* La se r Arsenal de Armas
* A Ponte
* Viagem de fuga

Eu então analisaria e descobriria quais ações são necessárias em cada coisa com base nos verbos da descrição.
Por exemplo, eu sei pela descrição que precisarei de uma maneira de “ligar” o motor, “obter a próxima cena” do
mapa, obter a “cena de abertura” e “entrar” em uma cena. Vou adicioná-los assim:

* Mapa
ÿ next_scene ÿ
opening_scene
* Motor -
jogar
* Cena
- entrar
* Morte
* Corredor Central
* La se r Arsenal de Armas
* A Ponte
* Viagem de fuga

Observe como acabei de colocar -enter em Scene , pois sei que todas as cenas abaixo dele irão herdá-lo e terão
que substituí-lo mais tarde.
Machine Translated by Google

202 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

43.1.4 Codifique as classes e um teste para executá-las

Depois de ter essa árvore de classes e algumas funções, abro um arquivo fonte em meu editor e tento
escreva o código para isso. Normalmente, apenas copio e colo a árvore no arquivo de origem e depois a edito nas classes.
Aqui está um pequeno exemplo de como isso pode parecer à primeira vista, com um pequeno teste simples no final do arquivo.

ex43_classes.py

Cena de 1 classe (objeto):


2

3 def entrar(próprio):
4 passar
5

Motor de 7 classes (objeto):


8

9 def __init__(self, mapa_de_cena):


10 passar
11

12 jogo def (próprio):


13 passar
14

15ª classe Morte (Cena):


16

17 def entrar(próprio):
18 passar
19

Corredor Central da classe 20 (Cena):


21

22 def entrar(próprio):
23 passar
24

25 classe LaserWeaponArmory (Cena):


26

27 def entrar(próprio):
28 passar
29

30 aula TheBridge(Cena):
31

32 def entrar(próprio):
33 passar
34

EscapePod de 35 classes (cena):


36

37 def entrar(próprio):
Machine Translated by Google

ANÁLISE E PROJETO BÁSICO ORIENTADOS A OBJETOS 203

38 passar
39

40

Mapa de 41 classes (objeto):


42

43 def __init__(self, start_scene):


44 passar
45

46 def next_scene(self, nome_da_cena):


47 passar
48

49 def cena_deabertura(self):
50 passar
51

52

53 a_map = Mapa('central_corredor') 54
a_game = Engine(a_map) 55
a_game.play()

Neste arquivo você pode ver que eu simplesmente repliquei a hierarquia que queria e depois adicionei um pouco de código
no final para executá-lo e ver se tudo funciona nesta estrutura básica. Nas seções posteriores deste exercício você
preencherá o restante deste código e fará com que ele funcione de acordo com a descrição do jogo.

43.1.5 Repetir e refinar

A última etapa do meu pequeno processo não é tanto uma etapa, mas um loop while. Você nunca faz isso como uma
operação de uma só passagem. Em vez disso, você repassa todo o processo novamente e o refina com base nas informações
que aprendeu nas etapas posteriores. Às vezes chego ao passo 3 e percebo que preciso trabalhar mais no 1 e no 2, então
paro e volto e trabalho neles. Às vezes, tenho um lampejo de inspiração e vou até o fim para codificar a solução em minha
cabeça enquanto a tenho lá, mas depois voltarei e executarei as etapas anteriores para garantir que cobri todas as
possibilidades que tenho. .

A outra ideia neste processo é que não é apenas algo que você faz em um único nível, mas algo que você pode fazer em
todos os níveis quando se depara com um problema específico. Digamos que ainda não sei escrever o método Engine.play .
Posso parar e fazer todo esse processo apenas naquela função para descobrir como escrevê-la.

De cima para baixo versus de baixo para cima

O processo é normalmente rotulado como “de cima para baixo”, pois começa nos conceitos mais abstratos (o topo) e segue
seu caminho até a implementação real. Quero que você use esse processo que acabei de descrever quando
Machine Translated by Google

204 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

analisando os problemas do livro a partir de agora, mas você deve saber que existe outra maneira de resolver problemas de
programação que começa com código e vai “subindo” até os conceitos abstratos. Essa outra forma é rotulada como “de baixo para
cima”. Aqui estão as etapas gerais que você segue para fazer isso:

1. Pegue um pequeno pedaço do problema; hackear algum código e fazê-lo funcionar mal.

2. Refine o código para algo mais formal com classes e testes automatizados.

3. Extraia os conceitos-chave que você está usando e tente encontrar pesquisas para eles.

4. Escreva uma descrição do que realmente está acontecendo.

5. Volte e refine o código, possivelmente descartando-o e recomeçando.

6. Repita, passando para outra parte do problema.

Acho que esse processo é melhor quando você é mais sólido em programação e pensa naturalmente em código sobre os problemas.
Este processo é muito bom quando você conhece pequenas peças do quebra-cabeça geral, mas talvez ainda não tenha informações
suficientes sobre o conceito geral. Dividi-lo em pequenos pedaços e explorar com o código ajuda você a resolver lentamente o
problema até resolvê-lo. No entanto, lembre-se de que sua solução provavelmente será sinuosa e estranha, e é por isso que minha
versão desse processo envolve voltar e encontrar pesquisas e, em seguida, limpar as coisas com base no que você aprendeu.

O Código para ”Gothons do Planeta Percal #25”

Parar! Vou mostrar minha solução final para o problema anterior, mas não quero que você simplesmente digite isso. Quero que você
pegue o código básico que fiz e tente fazê-lo funcionar com base na descrição. Depois de ter sua solução, você poderá voltar e ver
como eu fiz isso.

Vou dividir esse arquivo final ex43.py em seções e explicar cada uma delas, em vez de despejar todo o código de uma vez.

ex43.py

1 da saída de importação do
sys 2 da importação aleatória randint
3 da importação do textwrap dedent

Estas são apenas as nossas importações básicas para o jogo. A única novidade é a importação da função dedent do módulo textwrap .
Esta pequena função nos ajudará a escrever as descrições de nossas salas usando strings """ (aspas triplas). Ela simplesmente
remove os espaços em branco iniciais do início das linhas em uma string. Sem esta função, usar strings de estilo """ falha porque são
recuado na tela no mesmo nível do código Python .
Machine Translated by Google

ANÁLISE E PROJETO ORIENTADO A OBJETOS BÁSICOS 205

ex43.py

Cena de 1 classe (objeto):


2

3 def entrar(próprio):
4 print("Esta cena ainda não está configurada.")
5 print("Subclasse-o e implemente enter().")
6 saída(1)

Como você viu no código esqueleto, tenho uma classe base para Scene que terá as coisas comuns que
todas as cenas fazem. Neste programa simples eles não fazem muita coisa, então isso é mais uma demonstração do que você
faria para criar uma classe base.

ex43.py

1 classe Motor (objeto):


2

3 def __init__(self, mapa_de_cena):


4 self.scene_map = cena_map
5

6 jogo def (próprio):


7 cena_atual = self.scene_map.opening_scene()
8 last_scene = self.scene_map.next_scene('terminado')
9

10 enquanto cena_atual ! = última cena:


11 next_scene_name = cena_atual.enter()
12 cena_atual = self.scene_map.next_scene(next_scene_name)
13

14 # certifique-se de imprimir a última cena


15 cena_atual.enter()

Também tenho minha classe Engine , e você pode ver como já estou usando os métodos para Map.opening_scene
e Map.next_scene. Como planejei um pouco, posso presumir que vou escrevê-los e depois usar
antes de escrever a classe Map .

ex43.py

1 classe Morte(Cena):
2

3 piadas = [
4 "Você morreu. Você é péssimo nisso.",
5 "Sua mãe ficaria orgulhosa... se ela fosse mais inteligente.",
6 "Que luser.",
7 "Eu tenho um cachorrinho que é melhor nisso.",
8 "Você é pior do que as piadas do seu pai."
Machine Translated by Google

206 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

10 ]
11

12 def entrar(próprio):
13
imprimir(Death.quips[randint(0, len(self.quips)-1)])
14 saída(1)

Minha primeira cena é uma cena estranha chamada Morte, que mostra o tipo de cena mais simples que você pode escrever.

ex43.py

1 classe Corredor Central(Cena):


2

3 def entrar(próprio):
4
imprimir(dedent("""
5
Os Gothons do Planeta Percal #25 invadiram sua nave e
6
destruiu toda a sua tripulação. Você é o último sobrevivente
7
membro e sua última missão é obter a destruição de nêutrons
8
bomba do Arsenal de Armas, coloque-a na ponte e
9
explodir o navio depois de entrar em uma cápsula de fuga.
10

11
Você está correndo pelo corredor central em direção às Armas
12
Arsenal quando um Gothon salta, pele vermelha escamosa, escura e suja
13
dentes e fantasia de palhaço malvado fluindo em torno de seu ódio
14
corpo cheio. Ele está bloqueando a porta do Arsenal e
15
prestes a puxar uma arma para explodir você.
16 """))
17

18
ação = entrada("> ")
19

20 if ação == "atirar!":
21
imprimir(dedent("""
22
Rápido no saque, você puxa seu blaster e dispara
23
isso no Gothon. Sua fantasia de palhaço está fluindo e
24
movendo-se ao redor do corpo dele, o que atrapalha sua mira.
25
Seu laser atinge sua fantasia, mas erra completamente.
26
Isso estraga completamente sua nova fantasia de sua mãe
27
comprei ele, o que o faz ficar furioso
28
e acertá-lo repetidamente na cara até que você esteja
29
morto. Então ele come você.
30 """))
31 retornar 'morte'
32

33
ação elif == "esquivar!":
34
imprimir(dedent("""
Machine Translated by Google

ANÁLISE E PROJETO ORIENTADO A OBJETOS BÁSICOS 207

35 Como um boxeador de classe mundial, você se esquiva, tece, escorrega e


36 deslize para a direita enquanto o blaster do Gothon aciona um laser
37 além da sua cabeça. No meio de sua esquiva astuta
38 seu pé escorrega e você bate a cabeça no metal
39 parede e desmaiar. Você acorda pouco depois apenas para
40 morra enquanto o Gothon pisa em sua cabeça e te come.
41 """))
42 retornar 'morte'
43

44 ação elif == "conte uma piada":


45 imprimir(dedent("""
46 Sorte sua que eles fizeram você aprender os insultos de Gothon em
47 a Academia. Você conta a única piada de Gothon que você conhece:
48 Lbhe zbgure vf fb sng, jura fur fvgf nebhaq gur ubhfr,
49 pele fvgf nebhaq gur ubhfr. O Gothon para, tenta
50 para não rir, então começa a rir e não consegue se mover.
51 Enquanto ele está rindo, você corre e atira nele
52 a cabeça colocando-o no chão, então pule através do
53 Porta do Arsenal de Armas.
54 """))
55 retornar 'laser_weapon_armory'
56

57 outro:
58 print(" NÃO COMPUTA!")
59 retornar 'corredor_central'

Depois disso criei o CentralCorridor, que é o início do jogo. Estou fazendo as cenas para
o jogo antes do Mapa porque preciso referenciá-los mais tarde. Você também deve ver como eu uso o
função dedent na linha 4. Tente removê-la mais tarde para ver o que ela faz.

ex43.py

1 classe LaserWeaponArmory(Cena):
2

3 def entrar(próprio):
4 imprimir(dedent("""
5 Você faz um mergulho no Arsenal de Armas, agacha-se e examina
6 o espaço para mais Gothons que possam estar escondidos. Está morto
7 quieto, muito quieto. Você se levanta e corre para o outro lado
8 a sala e encontre a bomba de nêutrons em seu recipiente.
9 Há um bloqueio de teclado na caixa e você precisa do código para
10 tire a bomba. Se você errar o código 10 vezes, então
11 a fechadura fecha para sempre e você não consegue pegar a bomba. O
12 o código tem 3 dígitos.
13 """))
Machine Translated by Google

208 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

14

15 código = f"{randint(1,9)}{randint(1,9)}{randint(1,9)}"
16 adivinhar = input("[teclado]> ")
17 suposições = 0
18

19 enquanto adivinha ! = código e adivinha < 10:


20 print("BZZZZEDDD!")
21 adivinha += 1
22 adivinhar = input("[teclado]> ")
23

24 se adivinhar == código:
25 imprimir(dedent("""
26 O recipiente abre e o selo quebra, deixando
27 gás para fora. Você pega a bomba de nêutrons e corre o mais rápido que puder
28 você pode até a ponte onde você deve colocá-lo no
29 lugar certo.
30 """))
31 retornar 'a_ponte'
32 outro:
33 imprimir(dedent("""
34 A fechadura vibra uma última vez e então você ouve um
35 som de derretimento nauseante quando o mecanismo é fundido
36 junto. Você decide sentar lá e, finalmente, o
37 Gothons explodem o navio deles e você morre.
38 """))
39 retornar 'morte'
40

41

42

43 classe TheBridge(Cena):
44

45 def entrar(próprio):
46 imprimir(dedent("""
47 Você invadiu a ponte com a bomba de destruição Netron
48 debaixo do seu braço e surpreenda 5 Gothons que estão tentando
49 assumir o controle do navio. Cada um deles tem um aspecto ainda mais feio
50 fantasia de palhaço do que a última. Eles não puxaram seus
51 armas ainda em punho, quando eles veem a bomba ativa sob seu
52 braço e não quero detoná-lo.

53 """))
54

55 ação = entrada("> ")


56

57 if action == "jogar a bomba":


Machine Translated by Google

ANÁLISE E PROJETO ORIENTADO A OBJETOS BÁSICOS 209

58 imprimir(dedent("""
59 Em pânico você joga a bomba no grupo de Gothons
60 e dê um salto para a porta. Assim que você deixa cair um
61 Gothon atira em você pelas costas, matando você. Como
62 você morre, você vê outro Gothon tentando freneticamente
63 desarmar a bomba. Você morre sabendo que eles provavelmente irão
64 explodir quando ele disparar.
65 """))
66 retornar 'morte'
67

68 elif action == "coloque a bomba lentamente":


69 imprimir(dedent("""
70 Você aponta seu blaster para a bomba debaixo do seu braço e
71 os Gothons levantam as mãos e começam a suar.
72 Você recua lentamente em direção à porta, abre-a e então
73 coloque cuidadosamente a bomba no chão, apontando seu
74 blaster nisso. Você então pula de volta pela porta,
75 aperte o botão Fechar e acione a fechadura para que o
76 Gothons não podem sair. Agora que a bomba está colocada
77 você corre para a cápsula de fuga para sair dessa lata.
78 """))
79

80 retornar 'escape_pod'
81 outro:
82 print(" NÃO COMPUTA!")
83 retorne "a_ponte"
84

85

EscapePod de 86 classes (cena):


87

88 def entrar(próprio):
89 imprimir(dedent("""
90 Você corre pelo navio tentando desesperadamente chegar
91 a cápsula de fuga antes que toda a nave exploda. Parece
92 como se quase nenhum Gothons estivesse no navio, então sua corrida é
93 livre de interferências. Você chega à câmara com o
94 cápsulas de fuga e agora preciso escolher uma para levar. Alguns
95 eles podem estar danificados, mas você não tem tempo para olhar.
96 São 5 cápsulas, qual você pega?
97 """))
98

99 bom_pod = aleatório(1,5)
100 adivinhar = input("[pod #]> ")
101

102
Machine Translated by Google

210 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

103 if int(adivinhar) != good_pod:


104 print(dedent(f"""
105 Você entra no pod {guess} e aperta o botão de ejetar.
106 A cápsula escapa para o vazio do espaço, então
107 implode quando o casco se rompe, esmagando seu corpo em
108 geléia.
109 """))
110 retornar 'morte'
111 outro:
112 print(dedent(f"""
113 Você entra no pod {guess} e aperta o botão de ejetar.
114 A cápsula desliza facilmente para o espaço em direção ao
115 planeta abaixo. Enquanto voa para o planeta, você olha
116 voltar e ver sua nave implodir e depois explodir como um
117 estrela brilhante, destruindo a nave Gothon ao mesmo tempo
118 tempo. Você ganhou!

119 """))
120

121 retornar 'terminado'


122

123 aula concluída (cena):


124

125 def entrar(próprio):


126 print("Você ganhou! Bom trabalho.")
127 retornar 'terminado'

Este é o resto das cenas do jogo, e como sei que preciso delas e pensei em como elas funcionarão
fluem juntos, sou capaz de codificá-los diretamente.

Aliás, eu não digitaria todo esse código. Lembre-se de que eu disse para tentar construir isso de forma incremental, um
um pouco de cada vez. Estou apenas mostrando o resultado final.

ex43.py

Mapa de 1 classe (objeto):


2

3 cenas = {
4 'corredor_central': Corredor Central(),
5 'laser_weapon_armory': LaserWeaponArmory(),
6 'a_ponte': APonte(),
7 'escape_pod': EscapePod(),
8 'morte': Morte(),
9 'terminado': Concluído(),
10 }
11

12 def __init__(self, start_scene):


Machine Translated by Google

ANÁLISE E PROJETO BÁSICOS ORIENTADOS A OBJETOS 211

13 self.start_scene = start_scene
14

15 def next_scene(self, nome_da_cena):


16 val = Map.scenes.get(scene_name) retornar
17 val
18

19 def opening_scene(self): return


20 self.next_scene(self.start_scene)

Depois disso eu tenho minha classe Map , e você pode ver que ela está armazenando cada cena por nome em um dicionário, e então me
refiro a esse dict com Map.scenes. É também por isso que o mapa vem depois das cenas, porque o dicionário tem que se referir às cenas,
então elas têm que existir.

ex43.py

1 a_map = Mapa('central_corredor') 2 a_game


= Motor(a_map) 3 a_game.play()

Finalmente consegui meu código que executa o jogo criando um mapa e, em seguida, entregando esse mapa a um mecanismo antes de
chamar play para fazer o jogo funcionar.

O que você deve ver

Certifique-se de entender o jogo e de tentar resolvê-lo sozinho primeiro. Uma coisa a fazer se você estiver perplexo é trapacear um pouco
lendo meu código e depois continuar tentando resolvê-lo sozinho.

Quando executo meu jogo fica assim:

Exercício 43 Sessão

$ python3.6 ex43.py

Os Gothons do Planeta Percal #25 invadiram sua nave e destruíram toda a sua
tripulação. Você é o último membro sobrevivente e sua última missão é
pegar a bomba de destruição de nêutrons do Arsenal de Armas, colocá-la na
ponte e explodir a nave após entrar em uma cápsula de fuga.

Você está correndo pelo corredor central em direção ao Arsenal de Armas


quando um Gothon salta, pele vermelha escamosa, dentes escuros e sujos e
fantasia de palhaço maligno fluindo ao redor de seu corpo cheio de
ódio. Ele está bloqueando a porta do Arsenal e
Machine Translated by Google

212 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

prestes a puxar uma arma para explodir você.

> esquivar!

Como um boxeador de classe mundial, você se esquiva, tece,


escorrega e desliza para a direita enquanto o blaster do Gothon
aciona um laser perto de sua cabeça. No meio de sua esquiva
artística, seu pé escorrega e você bate a cabeça na parede de
metal e desmaia. Você acorda pouco depois e morre quando Gothon
pisa em sua cabeça e o come.

Eu tenho um cachorrinho que é melhor nisso.

Exercícios de estudo

1. Mude! Talvez você odeie esse jogo. Pode ser muito violento ou talvez você não goste de ficção científica. Faça o jogo funcionar
e depois mude para o que você gosta. Este é o seu computador; você faz com que ele faça o que quiser.

2. Tenho um bug neste código. Por que a fechadura da porta está adivinhando 11 vezes?

3. Explique como funciona o retorno para a próxima sala.

4. Adicione códigos de trapaça ao jogo para poder passar pelas salas mais difíceis. Eu posso fazer isso com dois
palavras em uma linha.

5. Volte para minha descrição e análise e tente construir um pequeno sistema de combate para o herói e
os vários Gothons que ele encontra.

6. Esta é na verdade uma versão pequena de algo chamado “máquina de estados finitos”. Leia sobre eles.
Eles podem não fazer sentido, mas tente mesmo assim.

Perguntas comuns dos alunos

Onde posso encontrar histórias para meus próprios jogos? Você pode inventá-los, da mesma forma que contaria uma história a
um amigo. Ou você pode tirar cenas simples de um livro ou filme de sua preferência.
Machine Translated by Google

ANÁLISE E PROJETO BÁSICO ORIENTADOS A OBJETOS 213


Machine Translated by Google

214

EXERCÍCIO 44

Herança versus composição


Nos contos de fadas sobre heróis derrotando vilões malignos, sempre há algum tipo de floresta escura. Poderia ser uma
caverna, uma floresta, outro planeta, apenas algum lugar onde todos sabem que o herói não deveria ir. Claro, logo após
o vilão ser apresentado você descobre, sim, que o herói tem que ir até aquela floresta idiota para matar o bandido. Parece
que o herói continua se metendo em situações que exigem que ele arrisque sua vida nesta floresta maligna.

Você raramente lê contos de fadas sobre heróis que são inteligentes o suficiente para evitar completamente toda a
situação. Você nunca ouve um herói dizer: “Espere um minuto, se eu partir para fazer fortuna em alto mar, deixando
Buttercup para trás, posso morrer e então ela terá que se casar com um príncipe feio chamado Humperdink.
Humperdink! Acho que vou ficar aqui e começar um negócio de Farm Boy for Rent.” Se ele fizesse isso não haveria
pântano de fogo, morte, reanimação, lutas de espadas, gigantes ou qualquer tipo de história, na verdade. Por causa disso,
a floresta nessas histórias parece existir como um buraco negro que arrasta o herói, não importa o que ele faça.

Na programação orientada a objetos, a herança é a floresta do mal. Programadores experientes sabem como evitar esse
mal porque sabem que nas profundezas da Herança da Floresta Negra está a Herança Múltipla da Rainha Má. Ela gosta
de comer software e programadores com seus dentes de enorme complexidade, mastigando a carne dos caídos. Mas a
floresta é tão poderosa e tentadora que quase todo programador precisa entrar nela e tentar sair vivo com a cabeça da
Rainha Má antes de poder se autodenominar programador de verdade. Você simplesmente não consegue resistir à
atração da Floresta da Herança, então você entra. Após a aventura, você aprende a ficar fora daquela floresta estúpida e
trazer um exército se for forçado a entrar novamente.

Esta é basicamente uma maneira engraçada de dizer que vou lhe ensinar algo que você deve usar com cuidado, chamado
herança. Os programadores que estão atualmente na floresta lutando contra a Rainha provavelmente dirão que você
precisa entrar. Eles dizem isso porque precisam da sua ajuda, já que o que eles criaram provavelmente é demais para
eles aguentarem. Mas você deve sempre se lembrar disso:

A maioria dos usos da herança pode ser simplificada ou substituída pela composição, e a herança múltipla
deve ser evitada a todo custo.

O que é herança?

A herança é usada para indicar que uma classe obterá a maioria ou todos os seus recursos de uma classe pai. Isso
acontece implicitamente sempre que você escreve a classe Foo(Bar), que diz “Faça uma classe Foo que herda de Bar”.
Quando você faz isso, a linguagem faz com que qualquer ação realizada em instâncias de Foo também funcione como se
tivesse sido realizada em uma instância de Bar. Fazer isso permite colocar funcionalidades comuns na classe Bar e, em
seguida, especializar essa funcionalidade na classe Foo conforme necessário.

Quando você está fazendo esse tipo de especialização, há três maneiras pelas quais as classes pai e filho podem interagir:
Machine Translated by Google

HERANÇA VERSUS COMPOSIÇÃO 215

1. As ações sobre a criança implicam uma ação sobre os pais.

2. As ações no filho substituem as ações no pai.

3. As ações sobre o filho alteram as ações sobre os pais.

Agora demonstrarei cada um deles em ordem e mostrarei o código para eles.

44.1.1 Herança Implícita

Primeiro mostrarei as ações implícitas que acontecem quando você define uma função no pai, mas não no filho.

ex44a.py

1 classe Pai (objeto):


2

3 def implícito(self):
4 print("PARENT implícito()")
5

6 classe Criança (pai):


7 passar
8

9 pai = Pai()
10 filho = Filho()
11

12 pai.implícito() 13
filho.implícito()

O uso de pass na classe Child: é como você diz ao Python que deseja um bloco vazio. Isso cria uma classe chamada
Child , mas diz que não há nada de novo para definir nela. Em vez disso, ele herdará todo o seu comportamento do
Pai. Ao executar este código você obtém o seguinte:

Exercício 44a Sessão

$ python3.6 ex44a.py PAI


implícito()
pai implícito()

Observe como, embora eu esteja chamando son.implicit() na linha 13 e mesmo que Child não tenha uma função
implícita definida, ela ainda funciona e chama aquela definida em Parent. Isso mostra que se você colocar funções em
uma classe base (ou seja, Parent), então todas as subclasses (ou seja, Child) obterão automaticamente esses recursos.
Muito útil para código repetitivo necessário em muitas classes.
Machine Translated by Google

216 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

44.1.2 Substituir explicitamente

O problema de ter funções chamadas implicitamente é que às vezes você quer que o filho se comporte de maneira diferente.
Neste caso você deseja substituir a função no filho, substituindo efetivamente a funcionalidade.
Para fazer isso basta definir uma função com o mesmo nome em Child. Aqui está um exemplo:

ex44b.py

1 classe Pai (objeto):


2

3 def substituição(self):
4 print("Substituição PAI()")
5

6 classe Criança (pai):


7

8 def substituição(self):
9 print("Substituição CRIANÇA()")
10

11 pai = Pai() 12 filho =


Filho()
13

14 pai.override() 15
filho.override()

Neste exemplo tenho uma função chamada override em ambas as classes, então vamos ver o que acontece quando você a
executa.

Sessão do Exercício 44b

$ python3.6 ex44b.py
substituição PAI ()
Substituição CRIANÇA()

Como você pode ver, quando a linha 14 é executada, ela executa a função Parent.override porque essa variável (dad) é
Parent. Mas quando a linha 15 é executada, ela imprime as mensagens Child.override porque son é uma instância de Child e
Child substitui essa função definindo sua própria versão.

Faça uma pausa agora mesmo e experimente brincar com esses dois conceitos antes de continuar.

44.1.3 Alterar antes ou depois

A terceira maneira de usar herança é um caso especial de substituição onde você deseja alterar o comportamento antes ou
depois da execução da versão da classe Pai . Você primeiro substitui a função como no último exemplo, mas depois usa uma
função interna do Python chamada super para fazer com que a versão Parent seja chamada. Aqui está o exemplo de como
fazer isso para que você possa entender esta descrição:
Machine Translated by Google

HERANÇA VERSUS COMPOSIÇÃO 217

ex44c.py

1 classe Pai (objeto):


2

3 def alterado(self):
4 print("PARENT alterado()")
5

6 classe Criança (pai):


7

8 def alterado(self):
9 print("CRIANÇA, ANTES DOS PAIS alterados()")
10 super(Criança, self).altered()
11 print("CRIANÇA, APÓS OS PAIS alterados()")
12

13 pai = Pai() 14 filho =


Filho()
15

16 pai.altered() 17
filho.altered()

As linhas importantes aqui são 9-11, onde no Child eu faço o seguinte quando son.altered() é chamado:

1. Como substituí Parent.altered , a versão Child.altered é executada e a linha 9 é executada


como você esperaria.

2. Neste caso quero fazer um antes e depois, então depois da linha 9 quero usar super para obter o
Versão pai.alterada .

3. Na linha 10 eu chamo super(Child, self).altered(), que reconhece a herança e obterá a classe Parent para você. Você deve
ser capaz de ler isso como “chamar super com argumentos Child e self e, em seguida, chamar a função alterada em tudo o
que ela retornar”.

4. Neste ponto, a versão Parent.altered da função é executada e imprime o Parent .


mensagem.

5. Finalmente, isso retorna de Parent.altered e a função Child.altered continua a imprimir a mensagem posterior.

Se você executar isso, deverá ver isto:

Sessão do Exercício 44c

$ python3.6 ex44c.py PAI


alterado()
CRIANÇA, ANTES DOS PAIS alterados()
PAI alterado()
Machine Translated by Google

218 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

CRIANÇA, APÓS PAIS alterados()

44.1.4 Todos os Três Combinados

Para demonstrar tudo isso, tenho uma versão final que mostra cada tipo de interação desde herança
em um arquivo:

ex44d.py

1 classe Pai (objeto):


2

3 substituição def (auto):


4 print("Substituição PAI()")
5

6 def implícito(próprio):
7 print("PARENT implícito()")
8

9 def alterado (auto):


10 print("PAI alterado()")
11

12ª classe Criança (pai):


13

14 substituição def (auto):


15 print("Substituição CRIANÇA()")
16

17 def alterado (auto):


18 print("CRIANÇA, ANTES DOS PAIS alterados()")
19 super(criança, self).altered()
20 print("CRIANÇA, APÓS PAIS alterado()")
21

22 pai = Pai()
23 filho = Filho()
24

25 pai.implícito()
26 filho.implícito()
27

28 pai.override()
29 filho.override()
30

31 pai.altered()
32 filho.alterado()

Percorra cada linha deste código e escreva um comentário explicando o que essa linha faz e se é
uma substituição ou não. Em seguida, execute-o e confirme que você obteve o que esperava:
Machine Translated by Google

HERANÇA VERSUS COMPOSIÇÃO 219

Exercício 44d Sessão

$ python3.6 ex44d.py
pai implícito()
pai implícito()
Substituição PAI ()
Substituição CRIANÇA()
PAI alterado()
CRIANÇA, ANTES DOS PAIS alterados()
PAI alterado()
CRIANÇA, APÓS PAIS alterados()

A razão para super()


Isso deveria parecer senso comum, mas então temos problemas com uma coisa chamada herança múltipla. Herança múltipla é
quando você define uma classe que herda de uma ou mais classes, assim:

classe SuperFun (Criança , Coisas ruins):


passar

Isso é como dizer: “Faça uma classe chamada SuperFun que herda das classes Child e BadStuff em
o mesmo tempo."

Neste caso, sempre que você tiver ações implícitas em qualquer instância do SuperFun , o Python terá que procurar o
possível função na hierarquia de classes para Child e BadStuff, mas precisa fazer isso em uma ordem consistente. Para fazer
isso, Python usa “ordem de resolução de método” (MRO) e um algoritmo chamado C3 para obter
é direto.

Como o MRO é complexo e um algoritmo bem definido é usado, o Python não pode deixar que você obtenha
o MRO certo. Em vez disso, Python oferece a função super() , que cuida de tudo isso para você no
lugares onde você precisa do tipo de ação de alteração, como fiz em Child.altered. Com super() você não
você precisa se preocupar em fazer isso direito, e o Python encontrará a função certa para você.

44.2.1 Usando super() com __init__

O uso mais comum de super() é, na verdade, em funções __init__ em classes base. Este é geralmente o
único lugar onde você precisa fazer algumas coisas em um filho e, em seguida, concluir a inicialização no pai.
Aqui está um exemplo rápido de como fazer isso na Criança:

classe Filho (pai):

definição _ _e noite _ _ (é o f , coisa ) :


auto . coisas = coisas
Machine Translated by Google

220 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

super (criança , auto ) . _ _iniciar _ _ ( )

É praticamente igual ao exemplo Child.altered acima, exceto que estou definindo algumas variáveis
no __init__ antes de o Parent inicializar com seu Parent.__init__.

Composição
A herança é útil, mas outra maneira de fazer exatamente a mesma coisa é usar outras classes e módulos,
em vez de confiar na herança implícita. Se você observar as três maneiras de explorar a herança, duas das
três envolvem escrever novo código para substituir ou alterar funcionalidade. Isso pode ser facilmente replicado apenas
chamando funções em um módulo. Aqui está um exemplo de como fazer isso:

ex44e.py

1 classe Outro (objeto):


2

3 substituição def (auto):


4 print("OUTRA substituição()")
5

6 def implícito(próprio):
7 print("OUTRO implícito()")
8

9 def alterado (auto):


10 print("OUTRO alterado()")
11

12 classe Criança(objeto):
13

14 def __init__(self):
15 self.other = Outro()
16

17 def implícito(próprio):
18 self.other.implicit()
19

20 substituição def (auto):


21 print("Substituição CRIANÇA()")
22

23 def alterado (auto):


24 print("CRIANÇA, ANTES DE OUTRA alterada()")
25 self.other.altered()
26 print("CRIANÇA, APÓS OUTRO alterado()")
27

28 filho = Filho()
29
Machine Translated by Google

HERANÇA VERSUS COMPOSIÇÃO 221

30 filho.implícito() 31
filho.override() 32
filho.altered()

Neste código não estou usando o nome Parent, pois não existe um relacionamento pai-filho é um . Este é um relacionamento que
tem um , onde a Criança tem um Outro que usa para realizar seu trabalho. Quando executo isso, obtenho a seguinte saída:

Sessão do Exercício 44e

$ python3.6 ex44e.py OUTRO


implícito()
Substituição CRIANÇA()
CRIANÇA, ANTES DE OUTRA alterada()
OUTRO alterado()
CRIANÇA, APÓS OUTRO alterado()

Você pode ver que a maior parte do código em Child e Other é a mesma para realizar a mesma coisa. A única diferença é que tive
que definir uma função Child.implicit para executar aquela ação. Eu poderia então me perguntar se preciso que esse Other seja
uma classe e poderia simplesmente transformá-lo em um módulo chamado other.py?

Quando usar herança ou composição


A questão da “herança versus composição” se resume a uma tentativa de resolver o problema do código reutilizável. Você não quer
ter código duplicado em todo o seu software, pois isso não é limpo e eficiente. A herança resolve esse problema criando um
mecanismo para você ter recursos implícitos nas classes base. A composição resolve isso fornecendo módulos e a capacidade de
chamar funções em outras classes.

Se ambas as soluções resolvem o problema da reutilização, qual delas é apropriada em quais situações? A resposta é incrivelmente
subjetiva, mas darei três diretrizes sobre quando fazer isso:

1. Evite herança múltipla a todo custo, pois é muito complexo para ser confiável. Se você estiver preso a isso, esteja preparado
para conhecer a hierarquia de classes e gastar tempo descobrindo de onde vem tudo.

2. Use composição para empacotar código em módulos que são usados em muitos lugares diferentes e não relacionados
e situações.

3. Use herança somente quando houver trechos de código reutilizáveis claramente relacionados que se encaixem em um único
conceito comum ou se for necessário por causa de algo que você está usando.
Machine Translated by Google

222 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

Não seja escravo dessas regras. O que devemos lembrar sobre a programação orientada a objetos é que ela é
inteiramente uma convenção social que os programadores criaram para empacotar e compartilhar código. Por ser
uma convenção social, mas codificada em Python, você pode ser forçado a evitar essas regras por causa das pessoas
com quem trabalha. Nesse caso, descubra como eles usam as coisas e depois é só se adaptar à situação.

Exercícios de estudo

Há apenas um exercício de estudo para este exercício porque é um exercício grande. Vá e leia http://www. python.org/
dev/peps/pep-0008/ e comece a tentar usá-lo em seu código. Você notará que algumas coisas são diferentes do que
você aprendeu neste livro, mas agora você deve ser capaz de entender suas recomendações e usá-las em seu próprio
código. O restante do código neste livro pode ou não seguir essas diretrizes, dependendo se isso torna o código mais
confuso. Sugiro que você também faça isso, pois a compreensão é mais importante do que impressionar a todos com
seu conhecimento das regras do estilo esotérico.

Perguntas comuns dos alunos

Como posso melhorar na resolução de problemas que nunca vi antes? A única maneira de melhorar a resolução
de problemas é resolver sozinho o maior número possível de problemas. Normalmente as pessoas se deparam
com um problema difícil e depois correm em busca de uma resposta. Isso é bom quando você precisa fazer as
coisas, mas se você tiver tempo para resolver sozinho, reserve esse tempo. Pare e bata a cabeça contra o
problema o maior tempo possível, tentando de tudo até resolvê-lo ou desistir. Depois disso, as respostas que
você encontrar serão mais satisfatórias e, eventualmente, você ficará melhor na resolução de problemas.

Os objetos não são apenas cópias de classes? Em algumas linguagens (como JavaScript) isso é verdade. Elas
são chamadas de linguagens de protótipo e não há muitas diferenças entre objetos e classes além do uso. Em
Python, entretanto, as classes atuam como modelos que “cunham” novos objetos, semelhante a como as
moedas eram cunhadas usando um dado (modelo).
Machine Translated by Google

HERANÇA VERSUS COMPOSIÇÃO 223


Machine Translated by Google

224

EXERCÍCIO 45

Você faz um jogo

Você precisa começar a aprender a se alimentar. Esperamos que, ao ler este livro, você tenha aprendido que todas
as informações de que precisa estão na Internet. Você apenas tem que ir procurá-lo. A única coisa que está faltando
são as palavras certas e o que procurar ao pesquisar. Agora você deve ter uma noção disso, então é hora de você
se esforçar para realizar um grande projeto e tentar fazê-lo funcionar.

Aqui estão seus requisitos:

1. Faça um jogo diferente daquele que fiz.

2. Use mais de um arquivo e use import para usá-los. Certifique-se de saber o que é isso.

3. Use uma classe por sala e dê às classes nomes que atendam ao seu propósito (como GoldRoom, KoiPondRoom).

4. Seu corredor precisará conhecer essas salas, então faça uma aula que as administre e conheça elas. Há
muitas maneiras de fazer isso, mas considere fazer com que cada sala retorne qual sala é a próxima ou
definir uma variável de qual sala é a próxima.

Fora isso, deixo isso para você. Passe uma semana inteira nisso e faça dele o melhor jogo possível. Use classes,
funções, dictos, listas, tudo o que puder para torná-lo legal. O objetivo desta lição é ensinar como estruturar classes
que necessitam de outras classes dentro de outros arquivos.

Lembre-se, não estou lhe dizendo exatamente como fazer isso porque você mesmo terá que fazer isso. Vá descobrir.
Programar é resolver problemas, e isso significa tentar coisas, experimentar, falhar, descartar seu trabalho e tentar
novamente. Quando você tiver dúvidas, peça ajuda e mostre seu código às pessoas. Se eles forem maus com você,
ignore-os e concentre-se nas pessoas que não são maus e ofereça ajuda. Continue trabalhando e limpando até ficar
bom, depois mostre mais um pouco.

Boa sorte e nos vemos em uma semana com seu jogo.

Avaliando seu jogo


Neste exercício você avaliará o jogo que acabou de fazer. Talvez você tenha passado pelo meio e ficou preso.
Talvez você tenha conseguido funcionar, mas por pouco. De qualquer forma, examinaremos um monte de coisas
que você deve saber agora e garantiremos que você as abordou em seu jogo. Estudaremos a formatação adequada
de uma classe, convenções comuns no uso de classes e muito conhecimento de “livro didático”.

Por que eu faria você tentar fazer isso sozinho e depois mostrar como fazer certo? De agora em diante no livro
tentarei torná-lo autossuficiente. Eu estive segurando sua mão quase todo esse tempo,
Machine Translated by Google

VOCÊ FAZ UM JOGO 225

e não posso fazer isso por muito mais tempo. Agora, em vez disso, vou lhe dar coisas para fazer, fazer com que você faça por conta
própria e depois lhe dar maneiras de melhorar o que você fez.

Você terá dificuldades no início e provavelmente ficará muito frustrado, mas persista e, eventualmente, desenvolverá uma mente para
resolver problemas. Você começará a encontrar soluções criativas para os problemas, em vez de apenas copiar soluções dos livros
didáticos.

Estilo de função

Todas as outras regras que ensinei sobre como criar uma função legal se aplicam aqui, mas adicione estas coisas:

• Por diversas razões, os programadores chamam funções que fazem parte de classes de “métodos”. É principalmente marketing,
mas esteja avisado que toda vez que você disser “função”, eles irão corrigi-lo irritantemente e dizer “método”. Se ficarem
muito chatos, basta pedir que demonstrem a base matemática que determina como um “método” é diferente de uma “função”
e eles calarão a boca.

• Quando você trabalha com turmas, passa grande parte do seu tempo conversando sobre como fazer a turma “fazer coisas”.
Em vez de nomear suas funções de acordo com o que a função faz, nomeie-as como se fosse um comando que você está
dando à classe. O mesmo que pop está dizendo “Ei, lista, tire isso”. Não é chamado remove_from_end_of_list porque,
embora seja isso que faz, não é um comando para uma lista.

• Mantenha suas funções pequenas e simples. Por alguma razão, quando as pessoas começam a aprender sobre as aulas
eles se esquecem disso.

Estilo de aula

• Sua classe deve usar “camel case” como SuperGoldFactory em vez de super_gold_factory.

• Tente não fazer muito em suas funções __init__ . Isso os torna mais difíceis de usar.

• Suas outras funções devem usar o “formato sublinhado”, então escreva my_awesome_hair e não myawesomehair
ou MeuAwesomeHair.

• Seja consistente na forma como você organiza os argumentos da sua função. Se sua turma tiver que lidar com usuários, cães
e gatos, mantenha essa ordem o tempo todo, a menos que realmente não faça sentido. Se você tiver uma função que usa
(cachorro, gato, usuário) e a outra leva (usuário, gato, cachorro), será difícil
usar.

• Tente não usar variáveis provenientes do módulo ou globais. Eles devem ser bastante independentes.

• Uma tola consistência é o duende das pequenas mentes. Consistência é boa, mas seguir tolamente
algum mantra idiota porque todo mundo faz é um estilo ruim. Pense por você mesmo.
Machine Translated by Google

226 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

• Sempre, sempre tenha o formato Nome da classe (objeto) ou então você estará em apuros.

Estilo de código

• Dê espaço vertical ao seu código para que as pessoas possam lê-lo. Você encontrará alguns programadores muito
ruins que são capazes de escrever códigos razoáveis, mas que não adicionam espaços . Este é um estilo ruim
em qualquer idioma porque o olho e o cérebro humanos usam o espaço e o alinhamento vertical para escanear
e separar os elementos visuais. Não ter espaço é o mesmo que dar ao seu código uma incrível pintura de
camuflagem.

• Se você não consegue ler em voz alta, provavelmente será difícil de ler. Se você estiver tendo problemas para
tornar algo fácil de usar, tente ler em voz alta. Isso não apenas força você a desacelerar e realmente ler, mas
também o ajuda a encontrar passagens difíceis e coisas que precisam ser alteradas para facilitar a leitura.

• Tente fazer o que outras pessoas estão fazendo em Python até encontrar seu próprio estilo.

• Depois de encontrar seu próprio estilo, não seja idiota. Trabalhar com código de outras pessoas faz parte de ser
programador, e outras pessoas têm muito mau gosto. Acredite em mim, você provavelmente também terá um
gosto muito ruim e nem perceberá.

• Se você encontrar alguém que escreve código em um estilo que você gosta, tente escrever algo que imite esse
estilo.

Bons comentários

• Os programadores lhe dirão que seu código deve ser legível o suficiente para que você não precise de
comentários. Eles então lhe dirão com sua voz mais oficial: “Portanto, nunca se deve escrever comentários ou
documentação. QED.” Esses programadores são consultores que recebem mais se outras pessoas não puderem
usar seu código, ou incompetentes que tendem a nunca trabalhar com outras pessoas. Ignore-os e escreva
comentários.

• Ao escrever comentários, descreva por que você está fazendo o que está fazendo. O código já
diz como, mas por que você fez as coisas do jeito que fez é mais importante.

• Ao escrever comentários de documentos para suas funções, faça a documentação dos comentários para alguém
que terá que usar seu código. Você não precisa enlouquecer, mas uma pequena frase bonita sobre o que alguém
pode fazer com aquela função ajuda muito.

• Embora os comentários sejam bons, muitos são ruins e você precisa mantê-los. Mantenha seus comentários
relativamente curtos e diretos e, se você alterar uma função, revise o comentário para ter certeza de que ainda
está correto.
Machine Translated by Google

VOCÊ FAZ UM JOGO 227

Avalie seu jogo

Eu quero que você agora finja que é eu. Adote uma aparência muito severa, imprima seu código, pegue uma caneta
vermelha e marque todos os erros que encontrar, incluindo qualquer coisa deste exercício e de outras diretrizes que você
leu até agora. Assim que terminar de marcar seu código, quero que você corrija tudo o que criou. Em seguida, repita isso
algumas vezes, procurando algo que possa ser melhor. Use todos os truques que lhe dei para dividir seu código na menor
análise possível.

O objetivo deste exercício é treinar sua atenção aos detalhes das aulas. Depois de terminar esse trecho de código,
encontre o código de outra pessoa e faça a mesma coisa. Leia uma cópia impressa de alguma parte dele e aponte todos
os erros e erros de estilo que encontrar. Em seguida, corrija-o e veja se suas correções podem ser feitas sem quebrar o
programa.

Não quero que você faça nada além de avaliar e corrigir o código da semana — seu próprio código e o de outras pessoas.
Será um trabalho muito difícil, mas quando terminar, seu cérebro estará conectado como as mãos de um boxeador.
Machine Translated by Google

228

EXERCÍCIO 46

Um esqueleto de projeto

Será aqui que você começará a aprender como configurar um bom diretório “esqueleto” de projeto. Este esqueleto
diretório terá todos os fundamentos necessários para colocar um novo projeto em funcionamento. Terá seu projeto
layout, testes automatizados, módulos e scripts de instalação. Quando você for fazer um novo projeto, basta copiar isso
diretório com um novo nome e edite os arquivos para começar.

Configuração do macOS/Linux

Antes de começar este exercício, você precisa instalar algum software para Python usando uma ferramenta chamada
pip3.6 (ou apenas pip) para instalar novos módulos. O comando pip3.6 deve estar incluído em seu
Instalação do python3.6 . Você vai querer verificar isso usando este comando:

$pip3. 6 lista
pip (9.0.1)
ferramentas de configuração ( 2 8 . 8 . 0 )

Você pode ignorar qualquer aviso de descontinuação se o vir. Você também pode ver outras ferramentas instaladas, mas o
base deve ser pip e setuptools. Depois de verificar isso, você poderá instalar o virtualenv:

$ sudo pip3. 6 instale vi r tu al en v


Senha :
Coletando vi r tu al en v
Baixando virtualen v ÿ15.1.0ÿpy2 . py3ÿnenhumÿqualquer . whl (1,8 MB)
100% | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 1,8 MB 1,1 MB/s

Instalando pacotes selecionados: vi r tu al en v


Virtualen v ÿ15.1.0 instalado com sucesso
$

Isto é para sistemas Linux ou macOS. Se você estiver no Linux/macOS, você desejará executar o seguinte comando
para ter certeza de usar o virtualenv correto:

$ onde está vi r tu al em v
/Biblioteca/Frameworks/Python. estrutura / Versão s / 6/bin/virtual ev

Você deverá ver algo parecido com o acima no macOS, mas o Linux será variável. No Linux você pode
tenha um comando virtualenv3.6 real , ou talvez seja melhor instalar um pacote para ele a partir do seu
sistema de gerenciamento de pacotes.
Machine Translated by Google

UM ESQUELETO DE PROJETO 229

Depois de instalar o virtualenv você pode usá-lo para criar uma instalação “falsa” do Python, o que torna
fica mais fácil gerenciar versões de seus pacotes para diferentes projetos. Primeiro, execute este comando e eu irei
explique o que está fazendo:

$ mkdir ~ / . venvs
$ vi r tu al en v ÿÿsystemÿsi t eÿpackages ~ / . venvs/lpthw
$. ~/. venvs / lpthw / bin / ac ti vate
(lpthw) $

Aqui está o que está acontecendo linha por linha:

1. Você cria um diretório chamado .venvs em seu HOME ~/ para armazenar todos os seus ambientes virtuais.

2. Você executa o virtualenv e solicita que ele inclua os pacotes do site do sistema (--system-site-packages),
em seguida, instrua-o a construir o virtualenv em ~/.venvs/lpthw.

3. Você então “fonte” o ambiente virtual lpthw usando o arquivo . operador no bash, seguido por
o script ~/.venvs/lpthw/bin/activate .

4. Finalmente, seu prompt muda para incluir (lpthw), para que você saiba que está usando aquele en-
ambiente.

Agora você pode ver onde as coisas estão instaladas:

(lpthw) $ qual python


/Usuários/zedshaw/ . venvs/lpthw/bin/python
(lpthw) $ python
Python 3. 6. 0 rc2 (v3. 6. 0 rc2: 800 a67f7806d [GCC 4. , 16 de dezembro de 2016 , 1 4: 1 2: 2 1 )
2. 1 (Apple In c. build 5666) (ponto 3)] em darwin
” créditos ” ou " Para maiores informações .
,
Digite ”ajuda” ”direitos ,
autorais” ”license >>> qui t ()

(lpthw) $

Você pode ver que o python executado está instalado em /Users/zedshaw/.venvs/lpthw/bin/python


diretório em vez do local original. Isso também resolve o problema de ter que digitar python3.6 já que
ele instala ambos:

$qual python3. 6
/Usuários/zedshaw/ . venvs/lpthw/bin/python3. 6
(lpthw) $

Você encontrará a mesma coisa para os comandos virtualenv e pip . A etapa final nesta configuração é instalar
nose, uma estrutura de teste que usaremos neste exercício:

$ pip instalar nariz


Coletando nariz
Baixando noseÿ1.3.7ÿpy3ÿnoneÿany . whl (154kB)
Machine Translated by Google

230 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

100% | | 163kB 3,2 MB/s


¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦

Instalando pacotes afetados: nariz


Nariz instalado com sucesso -1.3.7
(lpthw) $

Configuração do Windows 10

A instalação do Windows 10 é um pouco mais simples do que no Linux ou macOS, mas somente se você tiver uma versão do
Python instalado. Se você tiver o Python 3.6 e o Python 2.7 instalados, você estará por conta própria.
muito difícil gerenciar múltiplas instalações. Se você acompanhou o livro até agora e só
Python 3.6, então aqui está o que você faz. Primeiro, mude para o seu diretório inicial e confirme que você está executando
a versão correta do python:
> CD ~
> píton
Python 3.6.0 (v3.6.0:4 1 df79263a11 , 23 de dezembro de 2016 , 0 8: 0 6: 1 2)
[MSC v.1900 64 bits (AMD64)] no win32
” ” ou ”licença” para mais informações.
,
Digite ”ajuda” ”direitos ,
autorais” créditos >>> qui
t()

Então você desejará executar o pip para confirmar que possui uma instalação básica:

> lista de pips


pip (9.0.1)
ferramentas de configuração ( 2 8 . 8 . 0 )

Você pode ignorar com segurança qualquer aviso de descontinuação e está tudo bem se você tiver outros pacotes instalados.
A seguir, você instalará o virtualenv para configurar ambientes virtuais simples no restante do livro:

> pip instalar vi r tu al en v


Coletando vi r tu al en v
Usando virtualen em cache v ÿ15.1.0ÿpy2 . py3ÿnenhumÿqualquer . o que
Instalando pacotes selecionados: vi r tu al en v
Virtualen v ÿ15.1.0 instalado com sucesso

Depois de instalar o virtualenv , você precisará criar um diretório .venvs e preenchê-lo com um virtual
ambiente:

> mkdir. venvs


> we r tu al en v ÿÿsystemÿsi t eÿpackages . venvs/lpthw
Usando pré-fixação base
'
c : \ \ u se rs \ \ zedsh \ \ appdata \ \ local \ \ programas \ \ python \ \ python36 '
Novo executável python em
C:\Usuários\zedshaw\. venvs\lpthw\S cripts\python. exe
Instalando se tuptools , pip , roda . . . feito .
Machine Translated by Google

UM ESQUELETO DE PROJETO 231

Esses dois comandos criam uma pasta .venvs para armazenar diferentes ambientes virtuais e depois criam
seu primeiro chamado lpthw. Um ambiente virtual (virtualenv) é um lugar “falso” para instalar software, então
que você pode ter versões diferentes de pacotes diferentes para cada projeto em que está trabalhando. Uma vez que você
tenha o virtualenv configurado, você precisa ativá-lo:

>. \. venvs \ lpthw \ S cripts \ e ti vate

Isso executará o script de ativação do PowerShell, que configura o lpthw virtualenv para o seu atual
concha. Cada vez que quiser usar o software para o livro, você executará este comando. Você notará em
nosso próximo comando é que agora há um (lpthw) adicionado ao prompt do PowerShell mostrando qual
virtualenv que você está usando. Finalmente, você só precisa instalar o nose para executar testes posteriormente:

(lpthw) > pip instalar nariz


Coletando nariz
Baixando noseÿ1.3.7ÿpy3ÿnoneÿany . whl (154kB)
100% | ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ | 163kB 1,2MB/s

Instalando pacotes afetados: nariz


Nariz instalado com sucesso -1.3.7
(lpthw) >

Você verá que isso instala o nariz, exceto que o pip o instalará em seu ambiente virtual .venvs\lpthw em vez do diretório
principal de pacotes do sistema. Isso permite instalar versões conflitantes de pacotes Python
para cada projeto em que você trabalha sem infectar a configuração principal do sistema.

Criando o diretório do projeto Skeleton


Primeiro, crie a estrutura do seu diretório esqueleto com estes comandos:

$ mkdir projetos
$projetos cd/
$ esqueleto mkdir
$ esqueleto de cd
$ mkdir bin NAME testa documentos

Eu uso um diretório chamado projetos para armazenar todas as coisas em que estou trabalhando. Dentro desse diretório eu
tenho meu diretório esqueleto no qual coloquei a base dos meus projetos. O diretório NAME será renomeado
para o que você está chamando de módulo principal do seu projeto ao usar o esqueleto.

A seguir, precisamos configurar alguns arquivos iniciais. Veja como você faz isso no Linux/macOS:

$ touch NOME/ _ _i nit $ __ . py


testes de toque / _ _i nit __ . py

Aqui está a mesma coisa no Windows PowerShell:


Machine Translated by Google

232 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

$ new-item -type file NOME/ $ new-item -type __ iniciar _ _ . py


filetests / __ iniciar _ _ . py

Isso cria um diretório de módulo Python vazio onde podemos colocar nosso código.
arquivo setup.py que podemos usar para instalar nosso projeto mais tarde, se quisermos:

setup.py

1 tentativa:
2 de setuptools importar configuração
3 exceto ImportError:
4 da configuração de importação distutils.core
5

6 configuração = {
7 'descrição': 'Meu Projeto',
8 'autor': 'Meu nome',
9 'url': 'URL para obtê-lo.',
10 'download_url': 'Onde fazer o download.',
11 'author_email': 'Meu e-mail.',
12 'versão': '0.1',
13 'install_requires': ['nariz'],
14 'pacotes': ['NOME'],
15 'roteiros': [],
16 'nome': 'nome do projeto'
17 }
18

19 configuração(**configuração)

Edite este arquivo para que ele tenha suas informações de contato e esteja pronto para ser usado quando você copiá-lo.

Finalmente, você desejará um arquivo esqueleto simples para testes chamado testes/NAME_tests.py:

NAME_tests.py

*
1 de nose.tools importar 2 importar
NOME
3

4 configuração definida ():


5 print("CONFIGURAÇÃO!")
6

7 desmontagem de definição ():

8 print("DARRUPAR !")
9

10 def test_basic():
11 print("EU CORREI!", end='')
Machine Translated by Google

UM ESQUELETO DE PROJETO 233

46.3.1 Estrutura Final do Diretório

Quando você terminar de configurar tudo isso, seu diretório deverá se parecer com o meu aqui:

esqueleto /
NOME/

_ _iniciar __ . py
caixa /
documentos /

configurar . py
testes /

NAME_testes . py
_ _iniciar __ . py

E de agora em diante, você deve executar seus comandos neste diretório. Se não puder, faça ls -R e se você
não vê essa mesma estrutura, então você está no lugar errado. Por exemplo, as pessoas geralmente entram em
o diretório testes/ para tentar executar arquivos lá, o que não funcionará. Para executar os testes da sua aplicação, você
precisaria estar acima dos testes/ e deste local que tenho acima. Então, se você tentar isso:

$ cd testes / # ERRADO! ERRADO! ERRADO!


$ no s e t e s t s

------------------------------------------- ÿÿÿÿÿÿÿ

Executei 0 testes em 0.000 s

OK

Então isso está errado! Você tem que estar acima dos testes, então, supondo que você cometeu esse erro, você o corrigiria
Fazendo isso:

$cd. . $ls # sair dos testes /


# CORRETO! agora você está no lugar certo
NOME documentos bin configurar . py testes

$ no s e t e s t s
.
------------------------------------------- ÿÿÿÿÿÿÿÿ

Executei 1 teste em 0,004 s

OK

Lembre-se disso porque as pessoas cometem esse erro com bastante frequência.
Machine Translated by Google

234 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

AVISO! No momento da publicação, soube que o projeto do nariz foi abandonado e pode não funcionar
bem. Se você tiver erros de sintaxe estranhos ao executar o nosetests , observe a saída do erro. Se fizer
referência a ”python2.7” na saída, é provável que o nosetests esteja tentando executar a versão 2.7 do
Python em seu computador.
A solução é executar o nariz usando python3.6 -m "nose" no Linux ou OSX. No Windows você pode não
ter esse problema, mas usar python -m "nose" resolverá o problema se tiver.

Testando sua configuração

Depois de instalar tudo isso, você poderá fazer o seguinte:

$ no s e t e s t s
.
------------------------------------------- ÿÿÿÿÿÿÿÿ

Executei 1 teste em 0,007 s

OK

Explicarei o que essa coisa de nosetests está fazendo no próximo exercício, mas por enquanto, se você não vê isso,
provavelmente você entendeu algo errado. Certifique-se de colocar os arquivos __init__.py em seus diretórios NAME e
testes , e certifique-se de que você acertou testes/NAME_tests.py .

Usando o esqueleto

Agora você concluiu a maior parte do barbear do iaque. Sempre que você quiser iniciar um novo projeto, basta fazer o
seguinte:

1. Faça uma cópia do seu diretório esqueleto. Nomeie-o com o nome do seu novo projeto.

2. Renomeie (mova) o diretório NAME para ser o nome do seu projeto ou como você quiser chamar
seu módulo raiz.

3. Edite seu setup.py para ter todas as informações do seu projeto.

4. Renomeie testes/NAME_tests.py para também ter o nome do seu módulo.

5. Verifique se tudo está funcionando usando o nosetests novamente.

6. Comece a codificar.
Machine Translated by Google

UM ESQUELETO DE PROJETO 235

Questionário obrigatório

Este exercício não contém exercícios de estudo, mas um teste que você deve responder:

1. Leia sobre como usar todos os itens que você instalou.

2. Leia sobre o arquivo setup.py e tudo o que ele tem a oferecer. Atenção: não é um software muito bem escrito, por isso será muito
estranho de usar.

3. Faça um projeto e comece a colocar o código no módulo e, em seguida, coloque o módulo em funcionamento.

4. Coloque um script no diretório bin que você possa executar. Leia sobre como você pode criar um script Python
isso pode ser executado em seu sistema.

5. Mencione o script bin que você criou em seu setup.py para que ele seja instalado.

6. Use seu setup.py para instalar seu próprio módulo e certifique-se de que funciona, então use pip para desinstalar
isto.

Perguntas comuns dos alunos

Essas instruções funcionam no Windows? Eles deveriam, mas dependendo da versão do Windows, você pode precisar se esforçar um
pouco com a configuração para que funcione. Continue pesquisando e tentando até conseguir, ou veja se você pode pedir ajuda a
um amigo mais experiente em Python + Windows.

O que coloco no dicionário de configuração no meu setup.py? Certifique-se de ler a documentação para dis-
tutils em http://docs.python.org/distutils/setupscript.html.

Não consigo carregar o módulo NAME e apenas recebo um ImportError. Certifique-se de criar o arquivo NAME/__init__.py . Se você estiver no
Windows, certifique-se de não nomeá-lo acidentalmente como NAME/__init__.py.txt, o que acontece por padrão com alguns editores.

Por que precisamos de uma pasta bin/ ? Este é apenas um local padrão para colocar scripts que são executados no
linha de comando, não um lugar para colocar módulos.

Minha execução de testes de nariz mostra apenas um teste sendo executado. Isso está certo? Sim, é isso que minha saída também mostra.
Machine Translated by Google

236

EXERCÍCIO 47

Teste Automatizado
Ter que digitar comandos repetidamente no jogo para ter certeza de que está funcionando é irritante. Não seria melhor
escrever pequenos trechos de código que testem seu código? Então, quando você faz uma alteração ou adiciona algo novo
ao seu programa, basta “executar seus testes” e os testes garantem que tudo ainda esteja funcionando. Esses testes
automatizados não detectarão todos os seus bugs, mas reduzirão o tempo que você gasta digitando e executando seu
código repetidamente.

Cada exercício após este não terá uma seção O que você deve ver , mas terá uma seção O que você deve testar . Você
escreverá testes automatizados para todo o seu código a partir de agora e esperamos que isso o torne um programador
ainda melhor.

Não tentarei explicar por que você deveria escrever testes automatizados. Direi apenas que você está tentando ser um
programador, e os programadores automatizam tarefas chatas e tediosas. Testar um software é definitivamente chato e
tedioso, então você também pode escrever um pouco de código para fazer isso por você.

Essa deve ser toda a explicação de que você precisa, porque o motivo para escrever testes unitários é fortalecer seu
cérebro. Você leu este livro escrevendo códigos para fazer coisas. Agora você dará o próximo salto e escreverá um código
que conheça outros códigos que você escreveu. Este processo de escrever um teste que executa algum código que você
escreveu força você a entender claramente o que acabou de escrever.
Ele solidifica em seu cérebro exatamente o que faz e por que funciona e oferece um novo nível de atenção aos detalhes.

Escrevendo um caso de teste

Pegaremos um código muito simples e escreveremos um teste simples. Vamos basear este pequeno teste em um novo
projeto do esqueleto do seu projeto.

Primeiro, faça um projeto ex47 a partir do esqueleto do seu projeto. Aqui estão as etapas que você seguiria. Vou dar essas
instruções em inglês, em vez de mostrar como digitá-las, para que você tenha que descobrir
fora.

1. Copie o esqueleto para ex47.

2. Renomeie tudo com NAME para ex47.

3. Altere a palavra NOME em todos os arquivos para ex47.

4. Por fim, remova todos os diretórios __pycache__ para ter certeza de que está limpo.

Volte ao Exercício 46 se você tiver dúvidas e se não conseguir fazer isso facilmente, talvez pratique algumas vezes.
Machine Translated by Google

TESTES AUTOMATIZADOS 237

AVISO! Lembre-se de executar o comando nosetests para executar os testes. Você pode
execute-os com python3.6 ex47_tests.py, mas não funcionará tão facilmente e você terá
fazer isso para cada arquivo de teste.

A seguir, crie um arquivo simples ex47/game.py onde você pode colocar o código para teste. Isso vai ser um pouco bobo
classe que queremos testar com este código:

jogo.py

1 sala de aula (objeto):


2

3 def __init__(self, nome, descrição):


4 self.name = nome
5 self.description = descrição
6 self.paths = {}
7

8 def go(self, direção):


9 retornar self.paths.get (direção, Nenhum)
10

11 def add_paths(self, caminhos):


12 self.paths.update(caminhos)

Depois de ter esse arquivo, altere o esqueleto do teste de unidade para isto:

ex47_tests.py

*
1 da importação de nose.tools 2
da sala de importação ex47.game
3

5 def sala_teste():
6 ouro = Sala("Sala Dourada",
7 """Esta sala tem ouro que você pode pegar. Há um
8 porta para o norte.""")
9 assert_equal(ouro.nome, "GoldRoom")
10 assert_equal(ouro.paths, {})
11

12 def test_room_paths():
13 center = Room("Centro", "Sala de teste no centro.")
14 norte = Room("Norte", "Sala de teste no norte.")
15 sul = Room("Sul", "Sala de teste no sul.")
16

17 center.add_paths({'norte': norte, 'sul': sul})


Machine Translated by Google

238 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

18 assert_equal(center.go('norte'), norte)
19 assert_equal(center.go('sul'), sul)
20

21 def test_map():
22 start = Room("Iniciar", "Você pode ir para oeste e descer um buraco.")
23 oeste = Room("Árvores", "Há árvores aqui, você pode ir para o leste.")
24 down = Room("Dungeon", "Está escuro aqui, você pode subir.")
25

26 start.add_paths({'oeste': oeste, 'para baixo': para baixo})


27 oeste.add_paths({'leste': início})
28 down.add_paths({'up': início})
29

30 assert_equal(start.go('oeste'), oeste)
31 assert_equal(start.go('west').go('east'), start)
32 assert_equal(start.go('down').go('up'), start)

Este arquivo importa a classe Room que você criou no módulo ex47.game para que você possa fazer testes nela. Lá
é então um conjunto de testes que são funções começando com test_. Dentro de cada caso de teste há um pouco de código
que cria uma sala ou um conjunto de salas e, em seguida, garante que as salas funcionem da maneira que você espera que funcionem
trabalhar. Ele testa os recursos básicos da sala, depois os caminhos e, em seguida, testa um mapa completo.

As funções importantes aqui são assert_equal, que garante que as variáveis que você definiu ou os caminhos
que você construiu em uma sala são realmente o que você pensa que são. Se você obtiver o resultado errado, então
nosetests imprimirá uma mensagem de erro para que você possa descobrir.

Diretrizes de teste
Siga este conjunto geral de diretrizes ao fazer seus testes:

1. Os arquivos de teste vão para testes/ e são nomeados BLAH_tests.py, caso contrário, o nosetests não os executará.
Isso também evita que seus testes entrem em conflito com outro código.

2. Escreva um arquivo de teste para cada módulo criado.

3. Mantenha seus casos de teste (funções) curtos, mas não se preocupe se eles estiverem um pouco confusos. Os casos de teste são
geralmente meio bagunçado.

4. Mesmo que os casos de teste sejam confusos, tente mantê-los limpos e remova qualquer código repetitivo que puder.
Crie funções auxiliares que eliminam código duplicado. Você vai me agradecer mais tarde quando fizer uma
mudar e então ter que mudar seus testes. Código duplicado tornará mais fácil alterar seus testes
difícil.

5. Por fim, não se apegue muito aos seus testes. Às vezes, a melhor maneira de redesenhar algo é
apenas excluí-lo e começar de novo.
Machine Translated by Google

TESTES AUTOMATIZADOS 239

O que você deve ver

Exercício 47 Sessão

$ testes de nariz
...
-------------------------------------------------- --------------------

Executei 3 testes em 0,008s

OK

É isso que você deve ver se tudo estiver funcionando bem. Tente causar um erro para ver como fica e corrija-o.

Exercícios de estudo

1. Leia mais sobre testes de nariz e também sobre alternativas.

2. Aprenda sobre os “testes de documentação” do Python e veja se você gosta mais deles.

3. Torne sua sala mais avançada e use-a para reconstruir seu jogo novamente, mas desta vez
teste de unidade conforme você avança.

Perguntas comuns dos alunos

Recebo um erro de sintaxe quando executo o nosetests. Se você entender isso, veja o que o erro diz e corrija essa linha de
código ou as que estão acima dela. Ferramentas como o nosetests estão executando seu código e o código de teste,
portanto, encontrarão erros de sintaxe da mesma forma que a execução do Python.

Não consigo importar ex47.game? Certifique-se de criar o arquivo ex47/__init__.py . Consulte o Exercício 46 novamente para
ver como isso é feito. Se esse não for o problema, faça isso no macOS/Linux:

exportar PYTHONPATH=.

E no Windows:

$env:PYTHONPATH = ”$env:PYTHONPATH; .

Por fim, certifique-se de executar os testes com nosetests, não apenas com Python.

Recebo UserWarning quando executo nosetests. Você provavelmente tem duas versões do Python instaladas ou não está
usando a distribuição. Volte e instale distribui ou pip conforme descrevi no Exercício 46.
Machine Translated by Google

240

EXERCÍCIO 48

Entrada avançada do usuário

Em jogos anteriores, você lidava com a entrada do usuário simplesmente esperando strings definidas. Se o usuário digitasse
“run”, e exatamente “run”, então o jogo funcionava. Se eles digitassem frases semelhantes como “corra rápido”, o processo
falharia. O que precisamos é de um dispositivo que permita aos usuários digitar frases de várias maneiras e depois convertê-las
em algo que o computador entenda. Por exemplo, gostaríamos que todas essas frases funcionassem da mesma forma:

• porta aberta

• abra a porta

• passe pela porta

• soco de urso

• Dê um soco na cara do urso

Deveria ser aceitável para um usuário escrever algo muito parecido com o inglês para o seu jogo e fazer com que ele
descobrisse o que isso significa. Para fazer isso, vamos escrever um módulo que faz exatamente isso. Este módulo terá
algumas classes que funcionam juntas para lidar com a entrada do usuário e convertê-la em algo com o qual seu jogo possa
funcionar de maneira confiável.

Uma versão simplificada da língua inglesa poderia incluir os seguintes elementos:

• Palavras separadas por espaços.

• Frases compostas pelas palavras.

• Gramática que estrutura as frases em termos de significado.

Isso significa que o melhor lugar para começar é descobrir como obter palavras do usuário e que tipo de palavras são.

Nosso Léxico de Jogo

Em nosso jogo, temos que criar uma lista de palavras permitidas chamada “léxico”:

• Palavras de direção: norte, sul, leste, oeste, baixo, cima, esquerda, direita, trás

• Verbos: ir, parar, matar, comer


Machine Translated by Google

ENTRADA AVANÇADA DO USUÁRIO 241

• Palavras irrelevantes: o, em, de, de, em, isso

• Substantivos: porta, urso, princesa, armário

• Números: qualquer sequência de 0 a 9 caracteres

Quando chegamos aos substantivos, temos um pequeno problema, pois cada sala pode ter um conjunto diferente de substantivos,
mas vamos escolher este pequeno conjunto para trabalhar agora e melhorá-lo mais tarde.

48.1.1 Quebrando uma frase

Uma vez que tenhamos o nosso léxico, precisamos de uma forma de quebrar as frases para que possamos descobrir o que elas significam.
são. No nosso caso, definimos uma frase como “palavras separadas por espaços”, então só precisamos fazer
esse:

material = entrada (' > ')


palavras = material. dividir ()

É só com isso que nos preocuparemos por enquanto, mas funcionará muito bem por um bom tempo.

48.1.2 Tuplas de Léxico

Depois de sabermos como dividir uma frase em palavras, só temos que percorrer a lista de palavras e
descobrir que “tipo” eles são. Para fazer isso, usaremos uma pequena estrutura Python chamada
uma “tupla”. Uma tupla nada mais é do que uma lista que você não pode modificar. É criado colocando dados dentro
dois () com vírgula, como uma lista:

primeira_palavra = ('verbo', 'ir')


segunda_palavra = ('direção' 'norte' ) ,
'
terceira_palavra = ('direção' ') , frase
,
oeste = [primeira _palavra segunda_palavra , terceira_palavra]

Isso cria um par (TYPE, WORD) que permite olhar para a palavra e fazer coisas com ela.

Este é apenas um exemplo, mas é basicamente o resultado final. Você deseja obter informações brutas do usuário,
divida-o em palavras com divisão, analise essas palavras para identificar seu tipo e, por fim, faça uma frase
fora deles.

48.1.3 Entrada de digitalização

Agora você está pronto para escrever seu scanner. Este scanner pegará uma string de entrada bruta de um usuário e
retorne uma frase composta por uma lista de tuplas com os pares (TOKEN, WORD). Se uma palavra não for
parte do léxico, ele ainda deverá retornar o WORD, mas definir o TOKEN como um token de erro. Esses
tokens de erro dirão aos usuários que eles erraram.
Machine Translated by Google

242 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

É aqui que fica divertido. Não vou lhe dizer como fazer isso. Em vez disso, escreverei um “teste de unidade” e você
escreverá o scanner para que o teste de unidade funcione.

48.1.4 Exceções e Números

Há uma pequena coisa em que vou ajudá-lo primeiro: a conversão de números. Porém, para fazer isso, vamos trapacear e
usar exceções. Uma exceção é um erro obtido de alguma função que você pode ter executado. O que acontece é que sua
função “gera” uma exceção quando encontra um erro, então você tem que tratar essa exceção. Por exemplo, se você
digitar isso em Python, receberá uma exceção:

Exercício 48 Sessão Python

Python 3.6.5 (v3.6.5:f59c0932b4, 28 de março de 2018, 03:03:55)


[GCC 4.2.1 (Apple Inc. build 5666) (ponto 3)] em darwin Digite "help",
"copyright", "créditos" ou "licença" para obter mais informações. >>> int("inferno")

Traceback (última chamada mais recente):


Arquivo "<stdin>", linha 1, em <module>
ValueError: literal inválido para int() com base 10: 'inferno'

Esse ValueError é uma exceção lançada pela função int() porque o que você entregou a int() não é um número. A função
int()) poderia ter retornado um valor para informar que houve um erro, mas como ela retorna apenas números inteiros, seria
difícil fazer isso. Não pode retornar -1, pois é um número. Em vez de tentar descobrir o que retornar quando há um erro, a
função int() gera a exceção ValueError e você lida com ela.

Você lida com uma exceção usando as palavras-chave try e except :

ex48_convert.py

1 def número(s) de conversão:


2

3 tente: retorne int(s),


4 exceto ValueError:
5 retorne Nenhum

Você coloca o código que deseja “tentar” dentro do bloco try e, em seguida, coloca o código para executar o erro dentro do
exceto. Neste caso, queremos “tentar” chamar int() em algo que possa ser um número. Se houver um erro, nós o
“capturamos” e retornamos None.

No scanner que você escreve, você deve usar esta função para testar se algo é um número. Você também deve fazer isso
como a última coisa a verificar antes de declarar essa palavra como uma palavra de erro.
Machine Translated by Google

ENTRADA DE USUÁRIO AVANÇADA 243

Um primeiro desafio de teste

Testar primeiro é uma tática de programação em que você escreve um teste automatizado que finge que o código funciona e depois
escreve o código para fazer o teste realmente funcionar. Este método funciona quando você não consegue visualizar como o código
é implementado, mas pode imaginar como trabalhar com ele. Por exemplo, se você sabe como usar uma nova classe em outro
módulo, mas ainda não sabe como implementar essa classe, então escreva o teste primeiro.

Você vai fazer um teste que eu lhe dou e usá-lo para escrever o código que o faz funcionar. Para fazer este exercício, você seguirá
este procedimento:

1. Crie uma pequena parte do teste que lhe apresento.

2. Certifique-se de que ele seja executado e falhe para que você saiba que o teste está realmente confirmando que um recurso funciona.

3. Vá para o arquivo fonte lexicon.py e escreva o código que faz esse teste passar.

4. Repita até implementar tudo no teste.

Quando chegar ao 3 também é bom combinar nosso outro método de escrever código:

1. Faça a função ou classe “esqueleto” que você precisa.

2. Escreva comentários descrevendo como essa função funciona.

3. Escreva o código que faz o que os comentários descrevem.

4. Remova quaisquer comentários que apenas repitam o código.

Este método de escrever código é chamado de “código psuedo” e funciona bem se você não sabe como implementar algo, mas pode
descrevê-lo com suas próprias palavras.

Combinando a tática de “testar primeiro” com a tática de “código psuedo”, temos este processo simples de programação:

1. Escreva um teste que falhe.

2. Escreva o esqueleto da função/módulo/classe que o teste precisa.

3. Preencha o esqueleto com comentários com suas próprias palavras explicando como funciona.

4. Substitua os comentários por código até que o teste seja aprovado.

5. Repita.

Neste exercício, você praticará esse método de trabalho fazendo um teste que forneço para você executar no módulo lexicon.py .
Machine Translated by Google

244 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

O que você deve testar

Aqui está o caso de teste testes/lexicon_tests.py que você deve usar, mas não digite ainda:

léxico_tests.py

*
1 do nose.tools importar 2 do
léxico de importação ex48
3

5 def test_directions():
6 assert_equal(lexicon.scan("norte"), [('direção', 'norte')])
7 resultado = lexicon.scan("norte sudeste")
8 assert_equal(resultado, [('direção', 'norte'),
9 ('direção', 'sul'),
10 ('direção', 'leste')])
11

12 def test_verbs():
13 assert_equal(lexicon.scan("go"), [('verbo', 'go')])
14 resultado = lexicon.scan("vá matar, comer")
15 assert_equal(resultado, [('verbo', 'ir'),
16 ('verbo', 'matar'),
17 ('verbo', 'comer')])
18

19

20 def test_stops():
21 assert_equal(lexicon.scan("o"), [('parar', 'o')])
22 resultado = lexicon.scan("a entrada de")
23 assert_equal(resultado, [('parar', 'o'),
24 ('parar', 'dentro'),
25 ('parar', 'de')])
26

27

28 def test_nouns():
29 assert_equal(lexicon.scan("urso"), [('substantivo', 'urso')])
30 resultado = lexicon.scan(" princesa ursa")
31 assert_equal(resultado, [('substantivo', 'urso'),
32 ('substantivo', 'princesa')])
33

34 def números_teste():
35 assert_equal(lexicon.scan("1234"), [('número', 1234)])
36 resultado = lexico.scan("3 91234")
37 assert_equal(resultado, [('número', 3),
38 ('número', 91234)])
Machine Translated by Google

ENTRADA DE USUÁRIO AVANÇADA 245

39

40

41 def test_errors():
42 assert_equal(lexicon.scan("ASDFADFASDF"), [('erro',
43 'ASDFADFASDF')])
44 resultado = lexicon.scan("urso princesa IAS")
45 assert_equal(resultado, [('substantivo', 'urso'), ('erro',
46 'IAS'), ('substantivo',
47 'princesa')])

Você desejará criar um novo projeto usando o esqueleto do projeto, assim como fez no Exercício 47. Em seguida, você precisará criar este
caso de teste e o arquivo lexicon.py que ele usará. Observe a parte superior do caso de teste para ver como ele está sendo importado e
descobrir para onde vai.

A seguir, siga o procedimento que dei a você e escreva um pouco do caso de teste de cada vez. Por exemplo, aqui está como eu faria isso:

1. Escreva a importação no topo. Faça isso funcionar.

2. Crie uma versão vazia do primeiro caso de teste test_directions. Certifique-se de que isso funcione.

3. Escreva a primeira linha do caso de teste test_directions . Faça com que falhe.

4. Vá para o arquivo lexicon.py e crie uma função de varredura vazia .

5. Execute o teste e certifique-se de que a varredura esteja pelo menos em execução, mesmo que falhe.

6. Preencha os comentários do código psuedo sobre como a varredura deve funcionar para que test_directions seja aprovado.

7. Escreva o código que corresponde aos comentários até que test_directions seja aprovado.

8. Volte para test_directions e escreva o restante das linhas.

9. Volte para digitalizar em lexicon.py e trabalhe nele para fazer esse novo código de teste passar.

10. Depois de fazer isso, você terá seu primeiro teste aprovado e passará para o próximo teste.

Contanto que você continue seguindo este procedimento, um pequeno pedaço de cada vez, você poderá transformar com sucesso um
grande problema em problemas menores solucionáveis. É como escalar uma montanha transformando-a num monte de pequenas colinas.

Exercícios de estudo

1. Melhore o teste de unidade para testar mais o léxico.


Machine Translated by Google

246 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

2. Adicione ao léxico e atualize o teste de unidade.

3. Certifique-se de que seu scanner processe a entrada do usuário em qualquer letra maiúscula e minúscula. Atualize o teste para fazer
certeza de que isso realmente funciona.

4. Encontre outra maneira de converter o número.

5. Minha solução tinha 37 linhas. O seu é mais longo? Mais curta?

Perguntas comuns dos alunos

Por que continuo recebendo ImportErrors? Erros de importação geralmente são causados por quatro coisas. 1. Você não criou um
__init__.py em um diretório que contém módulos. 2. você está no diretório errado. 3.
Você está importando o módulo errado porque escreveu errado. 4. Seu PYTHONPATH não está definido
para ., então você não pode carregar módulos do seu diretório atual.

Qual é a diferença entre try-except e if-else? A construção try-except é usada apenas para lidar com exceções que os módulos podem
lançar. Nunca deve ser usado como alternativa ao if-else.

Existe uma maneira de manter o jogo rodando enquanto o usuário espera para digitar? Presumo que você queira que um monstro
ataque os usuários se eles não reagirem com rapidez suficiente. É possível, mas envolve módulos e técnicas que estão fora do
domínio deste livro.
Machine Translated by Google

ENTRADA DE USUÁRIO AVANÇADA 247


Machine Translated by Google

248

EXERCÍCIO 49

Fazendo frases
O que deveríamos ser capazes de obter do nosso pequeno scanner de léxico de jogo é uma lista parecida com esta:

Exercício 49 Sessão Python

Python 3.6.5 (v3.6.5:f59c0932b4, 28 de março de 2018, 03:03:55)


[GCC 4.2.1 (Apple Inc. build 5666) (ponto 3)] em darwin Digite
"help", "copyright", "créditos" ou "licença" para obter mais informações. >>> do ex48
importar léxico >>> lexicon.scan("ir
para o norte") [('verbo', 'ir'),
('direção', 'norte')] >>> lexicon.scan("matar o
princesa") [('verbo', 'matar'), ('parar', 'a'),
('substantivo', 'princesa')] >>> lexicon.scan ("comer o urso") [(' verbo',
'comer'), ('parar', 'o'), ('substantivo',
'urso')]

Isso também funcionará em frases mais longas, como lexicon.scan(”abra a porta e dê um tapa no nariz do urso”).

Agora vamos transformar isso em algo com o qual o jogo possa trabalhar, que seria algum tipo de classe de Sentença . Se você
se lembra da escola primária, uma frase pode ter uma estrutura simples como:

Sujeito-verbo-objeto

Obviamente fica mais complexo do que isso, e você provavelmente passou muitos dias com diagramas de frases irritantes nas
aulas de inglês. O que queremos é transformar as listas anteriores de tuplas em um belo objeto Sentença que tenha sujeito, verbo
e objeto.

Combine e espie

Para fazer isso, precisamos de cinco ferramentas:

1. Uma maneira de percorrer a lista de palavras digitalizadas. Isso é fácil.

2. Uma maneira de “combinar” diferentes tipos de tuplas que esperamos em nossa configuração Sujeito Verbo Objeto.

3. Uma forma de “espiar” uma tupla potencial para que possamos tomar algumas decisões.
Machine Translated by Google

FAZENDO SENTENÇAS 249

4. Uma forma de “pular” coisas com as quais não nos importamos, como palavras irrelevantes.

5. Um objeto Sentença para colocar os resultados.

Colocaremos essas funções em um módulo chamado ex48.parser em um arquivo chamado ex48/parser.py para testá-lo. Usamos a
função peek para dizer “olhe para o próximo elemento em nossa lista de tuplas e, em seguida, combine para retirar um e trabalhar
com ele”.

A gramática da frase

Antes de escrever o código, você precisa entender como funciona a gramática básica de frases em inglês. Em nosso analisador,
queremos produzir um objeto Sentença que possua três atributos:

Sentença.assunto Este é o sujeito de qualquer frase, mas pode ser padronizado como “jogador” na maioria das vezes, já que uma
frase “correr para o norte” implica “jogador correr para o norte”. Este será um substantivo.

Sentença.verbo Esta é a ação da frase. Em “correr para o norte” seria “correr”. Este será um verbo.

Sentença.objeto Este é outro substantivo que se refere ao que o verbo é feito. No nosso jogo separamos direções que também
seriam objetos. Em “run north” a palavra “north” seria o objeto.
Em “hit bear” a palavra “bear” seria o objeto.

Nosso analisador então deve usar as funções que descrevemos e, dada uma frase digitalizada, convertê-la em um objeto List of
Sentence para corresponder à entrada.

Uma palavra sobre exceções

Você aprendeu brevemente sobre exceções, mas não como criá-las. Este código demonstra como fazer isso com ParserError na
parte superior. Observe que ele usa classes para atribuir o tipo de exceção. Observe também o uso da palavra-chave raise para
gerar a exceção.

Nos seus testes, você vai querer trabalhar com essas exceções, o que mostrarei como fazer.

O código do analisador

Se você quiser um desafio extra, pare agora mesmo e tente escrever isso baseado apenas na minha descrição. Se você tiver
dúvidas, pode voltar e ver como fiz isso, mas tentar implementar o analisador sozinho é uma boa prática. Agora examinarei o código
para que você possa inseri-lo em ex48/parser.py. Iniciamos o analisador com a exceção necessária para um erro de análise:
Machine Translated by Google

250 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

analisador.py

1 classe ParserError (Exceção):


2 passar

É assim que você cria sua própria classe de exceção ParserError que pode lançar. Em seguida, precisamos da frase
objeto que criaremos:

analisador.py

Frase de 1 classe (objeto):


2

3 def __init__(self, sujeito, verbo, obj):


4 # lembre-se que pegamos tuplas ('substantivo', 'princesa') e as convertemos
5 self.assunto = assunto[1]
6 self.verbo = verbo[1]
7 self.objeto = obj[1]

Não há nada de especial neste código até agora. Você está apenas fazendo aulas simples.

Na nossa descrição do problema, precisamos de uma função que possa espiar uma lista de palavras e retornar o que
tipo de palavra é:

analisador.py

1 espiada def (lista de palavras):


2 se lista_palavras:
3 palavra = lista_palavras[0]
4 palavra de retorno [0]
5 outro:
6 retornar Nenhum

Precisamos desta função porque teremos que tomar decisões sobre que tipo de frase estamos lidando
com base em qual é a próxima palavra. Então podemos chamar outra função para consumir essa palavra e

continuar.

Para consumir uma palavra usamos a função match , que confirma que a palavra esperada é do tipo certo,
tira-o da lista e retorna a palavra.

analisador.py

1 correspondência def (lista_palavras, esperando):


2 se lista_palavras:
3 palavra = lista_palavras.pop(0)
4

5 if word[0] == esperando:
Machine Translated by Google

FAZENDO FRASES 251

6 palavra de retorno

7 outro:
8 retornar Nenhum
9 outro:
10 retornar Nenhum

Novamente, isso é bastante simples, mas certifique-se de entender este código. Certifique-se também de entender o porquê
Estou fazendo assim. Preciso dar uma olhada nas palavras da lista para decidir que tipo de frase estou lidando
com, e então preciso combinar essas palavras para criar minha frase.

A última coisa que preciso é uma maneira de pular palavras que não são úteis para a frase. Estas são as palavras
rotuladas como “palavras de parada” (tipo 'stop') que são palavras como “o”, “e” e “a”.
analisador.py

1 def pular (lista_palavras, tipo_palavras):


2 while peek(lista_palavras) == tipo_palavra:
3 correspondência (lista_palavras, tipo_palavras)

Lembre-se de que skip não pula uma palavra, ele pula quantas palavras desse tipo encontrar. Isto faz
então, se alguém digitar “gritar com o urso”, você receberá “gritar” e “urso”.

Esse é o nosso conjunto básico de funções de análise, e com isso podemos analisar praticamente qualquer texto que
querer. Nosso analisador é muito simples, portanto as funções restantes são curtas.

Primeiro, podemos analisar um verbo:


analisador.py

1 def parse_verb(lista_palavras):
2 pular(lista_palavras, 'parar')
3

4 if peek(lista_palavras) == 'verbo':
5 retornar correspondência (lista_palavras, 'verbo')
6 outro:
7 raise ParserError("Esperava um verbo a seguir.")

Pulamos quaisquer palavras irrelevantes e, em seguida, olhamos adiante para ter certeza de que a próxima palavra é do tipo “verbo”. Se não for, então

aumente o ParserError para dizer o porquê. Se for um “verbo”, combine-o, o que o tira da lista. Um similar
função lida com objetos de frase:
analisador.py

1 def parse_object(lista_palavras):
2 pular(lista_palavras, 'parar')
3 próxima_palavra = espiar (lista_palavras)
4
Machine Translated by Google

252 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

5 se next_word == 'substantivo':
6 retornar correspondência (lista_palavras, 'substantivo')
7 elif next_word == 'direção':
8 retornar correspondência (lista_palavras, 'direção')
9 outro:
10 raise ParserError("Esperava um substantivo ou direção a seguir.")

Novamente, pule as palavras irrelevantes, olhe adiante e decida se a frase está correta com base no que está lá. Em
a função parse_object , porém, precisamos lidar com as palavras “substantivo” e “direção” tanto quanto possível
objetos. Os assuntos são semelhantes novamente, mas como queremos lidar com o substantivo “jogador” implícito,
tem que usar espiada:

analisador.py

1 def parse_subject(lista_palavras):
2 pular(lista_palavras, 'parar')
3 próxima_palavra = espiar (lista_palavras)
4

5 se next_word == 'substantivo':
6 retornar correspondência (lista_palavras, 'substantivo')
7 elif next_word == 'verbo':
8 return ('substantivo', 'jogador')
9 outro:
10 raise ParserError("Esperava um verbo a seguir.")

Com tudo isso resolvido e pronto, nossa função parse_sentence final é muito simples:

analisador.py

1 def parse_sentence(lista_palavras):
2 sujeito = analisar_assunto(lista_palavras)
3 verbo = analisar_verbo(lista_palavras)
4 obj = analisar_objeto(lista_palavras)
5

6 retornar frase (sujeito, verbo, obj)

Brincando com o analisador

Para ver como isso funciona, você pode brincar assim:


Machine Translated by Google

FAZENDO SENTENÇAS 253

Exercício 49a Sessão Python

Python 3.6.5 (v3.6.5:f59c0932b4, 28 de março de 2018, 03:03:55)


[GCC 4.2.1 (Apple Inc. build 5666) (ponto 3)] em darwin Digite "help",
"copyright", "créditos" ou "licença" para obter mais informações. >>> from ex48.parser
*
import >>> x =
parse_sentence([('verbo', 'correr'), ('direção', 'norte')]) >>> x.subject 'jogador' >>>
x .verbo

'executar' >>>
x.object 'norte'
>>> x = parse_sentence([('substantivo', 'urso'), ('verbo', 'comer'), ('parar', 'o'), ('substantivo',
... 'querido')])
>>> x.subject
'urso'
>>> x.verbo
'comer'

>>> x.object
'querida'

Tente mapear as frases para os pares corretos em uma frase. Por exemplo, como você diria “o urso corre para o sul?”

O que você deve testar

Para o Exercício 49, escreva um teste completo que confirme que tudo neste código está funcionando. Coloque o teste em testes/
parser_tests.py semelhante ao arquivo de teste do último exercício. Isso inclui fazer com que exceções aconteçam, fornecendo
sentenças ruins ao analisador.

Verifique se há uma exceção usando a função assert_raises da documentação do nariz . Aprenda como usar isso para poder
escrever um teste que provavelmente falhará, o que é muito importante nos testes. Aprenda mais sobre esta função (e outras)
lendo a documentação do nariz.

Quando terminar, você deverá saber como esse trecho de código funciona e como escrever um teste para o código de outras
pessoas, mesmo que elas não queiram que você o faça. Acredite em mim, é uma habilidade muito útil de se ter.
Machine Translated by Google

254 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

Exercícios de estudo

1. Altere os métodos parse_ e tente colocá-los em uma classe em vez de usá-los apenas como métodos.
Qual desenho você gosta mais?

2. Torne o analisador mais resistente a erros para evitar incomodar seus usuários se eles digitarem palavras
seu léxico não entende.

3. Melhore a gramática lidando com mais coisas como números.

4. Pense em como você poderia usar esta classe de frase em seu jogo para fazer coisas mais divertidas com um
entrada do usuário.

Perguntas comuns dos alunos

Não consigo fazer assert_raises funcionar direito. Certifique-se de escrever assert_raises(exceção, chamável,
parâmetros) e não escrever assert_raises(exceção, chamarável(parâmetros)).
Observe como o segundo formulário está chamando a função e depois passando o resultado para assert_raises,
o que está errado. Você tem que passar a função a ser chamada e seus argumentos para assert_raises.
Machine Translated by Google

FAZENDO SENTENÇAS 255


Machine Translated by Google

256

EXERCÍCIO 50

Seu primeiro site

Esses três exercícios finais serão muito difíceis e você deve dedicar algum tempo a eles. Neste primeiro você construirá
uma versão web simples de um de seus jogos. Antes de tentar este exercício, você deve ter concluído o Exercício 46
com sucesso e ter um pip funcional instalado para que você possa instalar pacotes e saber como criar um esqueleto de
diretório de projeto. Se você não se lembra de como fazer isso, volte ao Exercício 46 e faça tudo de novo.

Ativando seu ambiente virtual


Você deve ter o hábito de usar um virtualenv , mas se esqueceu, ative-o agora. No Linux ou OSX faça isso:

$ fonte ~ / . venvs / lpthw / bin / e ti vate ( lpthw ) $

Mas, no Microsoft Windows PowerShell, faça o seguinte:

> empurre ~
> . \. venvs \ lpthw \ S cripts \ ac ti vate ( lpthw )
> popd

De agora em diante use sempre este virtualenv para trabalhar no livro. Isso torna as coisas muito mais fáceis. No
restante destas instruções estou fazendo python em vez de python , já que o virtualenv resolve esse problema para nós.
Você também verá (lpthw) antes de cada prompt para lembrá-lo de que está em um ambiente virtual.

Instalando o frasco

Antes de criar sua primeira aplicação web, primeiro você precisará instalar o “framework web” chamado flask.
O termo “estrutura” geralmente significa “algum pacote que torna mais fácil para mim fazer alguma coisa”.
No mundo das aplicações web, as pessoas criam “frameworks web” para compensar os difíceis problemas que
encontraram ao criar seus próprios sites. Eles compartilham essas soluções comuns na forma de um pacote que você
pode baixar para inicializar seus próprios projetos.

No nosso caso, usaremos a estrutura flask , mas existem muitas, muitas, muitas outras que você pode escolher. Por
enquanto, aprenda o flask e, em seguida, passe para outro quando estiver pronto (ou continue usando o flask , pois é
bom o suficiente).

Usando pip, instale o frasco:


Machine Translated by Google

SEU PRIMEIRO SITE 257

(lpthw) $# você está em seu lpthw vi r tu al en v ?


(lpthw) $ sudo pip installflask
[sudo] senha para zedshaw:
Baixando / descompactando o frasco
Executando a configuração. py egg_info para frasco de pacote

Instalando todos os pacotes afetados: flask


Executando a configuração. py instalar para rflask

lask instalado com sucesso


Limpando . . .

Mas no Microsoft Windows PowerShell você faz isso:

( lpthw ) > # você está em seu lpthw vi r tu al en v ?


(lpthw) > pip installflask

Isso funcionará em computadores Linux e macOS, mas no Windows basta descartar a parte sudo do pip
comando de instalação e deve funcionar. Caso contrário, volte ao Exercício 46 e certifique-se de que consegue fazê-lo
de forma confiável.

Faça um projeto simples “Hello World”


Agora você criará uma aplicação web inicial e um diretório de projeto muito simples “Hello World”
usando frasco. Primeiro, crie o diretório do seu projeto:

(lpthw) $ cd projetos
(lpthw) $ mkdir gothonweb
(lpthw)$cd gothonweb
(lpthw) $ mkdir bin gothonweb testa modelos de documentos
(lpthw) $ touch gothonweb / _ _i ni t (lpthw) $ __ . py
testes de toque / _ _i ni t __ . py

No PowerShell você faz isso:

(lpthw) > projetos de cd


(lpthw) > mkdir gothonweb
(lpthw) > cd gothonweb
(lpthw) > mkdir bin
(lpthw) > mkdir gothonweb
(lpthw)> testes mkdir
(lpthw)> documentos mkdir
(lpthw) > modelos mkdir
( lpthw ) > arquivo tipo novo item gothonweb / ( lpthw ) > __ iniciar _ _ . py
arquivo tipo novo item testes / __ iniciar _ _ . py
Machine Translated by Google

258 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

Você pegará o jogo do Exercício 43 e o transformará em uma aplicação web, por isso o chamará de gothonweb. Antes
de fazer isso, precisamos criar o aplicativo de frasco mais básico possível.
Coloque o seguinte código em app.py:

ex50.py

1 da importação do frasco Flask


2 app = Flask(__name__)
3

4 @app.route('/') 5 def
hello_world(): saudação =
6 "Mundo" return f'Olá,
7 {saudação}!'
8

9 se __name__ == "__main__":
10 app.run()

Em seguida, execute o aplicativo assim:

(lpthw) $ aplicativo python. py *


Executando em http://1 2 7 . 0. 0. 1: 5 0 0 0 / (Pressione CTRL+C para sair)

Por fim, use seu navegador e acesse http://localhost:5000/, e você verá duas coisas.
Primeiro, no seu navegador você verá Olá, mundo!. Segundo, você verá seu terminal com uma nova saída como esta:

(lpthw) $ aplicativo python. py *


Executando em http://1 2 7 . 0. 0. 1: 5 0 0 0 / (Pressione CTRL+C para sair)
1 2 7. 0. 0. 1 ÿ ÿ [ 2 2/Fev/2017 1 4: 2 8: 5 0 ] ”GET / HTTP/ 1. 1” 200 ÿ 1 2 7. 0. 0. 1 ÿ ÿ
[ 2 2/Fev/2017 1 4: 2 8: 5 0 ] ”GET / fa vicon . i co HTTP/ 1. 1 ” 404 ÿ 1 2 7. 0. 0. 1 ÿ ÿ [ 2 2/Fev/2017 1 4:
2 8: 5 0 ] ”GET / fa vicon . eu co HTTP/ 1. 1 ” 404 -

Essas são mensagens de log que o flask imprime para que você possa ver se o servidor está funcionando e o que o
navegador está fazendo nos bastidores. As mensagens de log ajudam você a depurar e descobrir quando há problemas.
Por exemplo, está dizendo que seu navegador tentou obter /favicon.ico mas esse arquivo não existia, então ele retornou
o código de status 404 Not Found .

Ainda não expliquei como essas coisas da web funcionam, porque quero deixar você configurado e pronto para começar,
para que eu possa explicar melhor nos próximos dois exercícios. Para conseguir isso, farei com que você quebre seu
aplicativo flask de várias maneiras e, em seguida, reestruture-o para saber como ele está configurado.

O que está acontecendo?

Aqui está o que acontece quando seu navegador acessa seu aplicativo:
Machine Translated by Google

SEU PRIMEIRO SITE 259

1. Seu navegador faz uma conexão de rede com seu próprio computador, que é chamado localhost e
é uma maneira padrão de dizer "qualquer que seja o nome do meu computador na rede". Ele também usa
porta 5000.

2. Depois de se conectar, ele faz uma solicitação HTTP para o aplicativo app.py e solicita o / URL,
que geralmente é o primeiro URL em qualquer site.

3. Dentro de app.py você tem uma lista de URLs e quais funções elas correspondem. O único que temos é o
Mapeamento '/', 'hello_world' . Isso significa que sempre que alguém acessa / com um navegador,
flask encontrará o def hello_world e o executará para lidar com a solicitação.

4. Agora que o flask encontrou def hello_world, ele o chama para realmente lidar com a solicitação. Esta função
tion é executado e simplesmente retorna uma string para qual frasco deve enviar ao navegador.

5. Por fim, o flask atendeu a solicitação e envia essa resposta ao navegador, que é o que você
estão vendo.

Certifique-se de que você realmente entende isso. Elabore um diagrama de como essas informações fluem de seu
navegador, para flask, depois para def hello_world e de volta ao seu navegador.

Correção de erros

Primeiro, exclua a linha 6 onde você atribui a variável de saudação e, em seguida, clique em atualizar no seu navegador. Então use
CTRL-C para matar o frasco e iniciá-lo novamente. Assim que estiver em execução novamente, atualize seu navegador e você deverá ver
um “Erro interno do servidor”. De volta ao seu terminal, você verá isto ([VENV] é o caminho para o seu .venvs/
diretório):

(lpthw) $ aplicativo python. py


*Executando em http://1 2 7 . 0. 0. 1: 5 0 0 0 / (Pressione CTRL+C para sair)
[2017-02-22 14:35:54,256] ERRO no aplicativo: Exceção em / [GET]
Traceback (último calllast mais recente):

Arquivo ”[VENV] /site -packages/flask/app. py li ne 1982 ,
em wsgi_app,
resposta = eu mesmo. full _di sp at ch F _ req é ( )
ile” [VENV ] / si t eÿpackages / flask / app . py na íntegra ” ,
linha ne , _di sp no ch _ r equ é
1614 rv = self . handle_user_exception ( e )

Linha ”[VENV] /site -packages/flask/app. py em ,
de arquivo 1517 , handle_user_exception

rer ai se ( tipo_exc , valor_exc tb ) ,



Arquivo ”[VENV] / site -packages / flask / _compat. py li ne 33 ,
, em rer você tem se
aumentar valor

Arquivo ”[VENV] /site -packages/flask/app. py ,
Machine Translated by Google

260 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

linha 1612 , na íntegra _di sp no ch _ r equ é


rv = eu mesmo. despacho_request()

Arquivo ”[VENV] / site -packages / flask / app. py in di spa tch ,
linha 1598 , _ reque st
retornar a si mesmo. view_functions [ regra e . ponto final] (* * req.view_args)

Arquivo ”aplicativo. , Número 6 , em olá_mundo
py retorno saudação
NameError: nome 'saudação' não está definido
1 2 7. 0. 0. 1 ÿ ÿ [ 2 2/Fev/2017 1 4: 3 5: 5 4 ] ”GET / HTTP/ 1. 1” 500 ÿ

Isso funciona bem, mas você também pode executar o Flask no “modo depurador”. Isto lhe dará uma melhor
página de erro e informações mais úteis. O problema com o modo depurador é que não é seguro executar no
internet, então você deve ativá-lo explicitamente assim:

(lpthw) $ exportar FLASK_DEBUG=1


(lpthw) $ aplicativo python. py
*Executando em http://1 2 7 . 0. 0. 1: 5 0 0 0 / (Pressione CTRL+C para sair)
* Reiniciando com estatísticas
* Depurador isativo!
* Código PIN do depurador: 222ÿ752ÿ342

Depois disso, você clica em atualizar no seu navegador e obtém uma página muito mais detalhada com informações
você pode usar para depurar o aplicativo e um console ativo para trabalhar e saber mais.

AVISO! É o console de depuração ao vivo do Flask e a saída aprimorada que torna


modo de depuração tão perigoso na internet. Com essas informações, um invasor pode controlar
completamente sua máquina remotamente. Se você colocar seu aplicativo da web no
internet não ativa o modo depurador. Na verdade, eu evitaria fazer FLASK_DEBUG
fácil de ativar. É tentador simplesmente hackear esta inicialização para salvar uma etapa durante
desenvolvimento, mas então esse hack chegará ao seu servidor web e se transformará em um verdadeiro
hack, não apenas algo preguiçoso que você fez uma noite quando estava cansado.

Crie modelos básicos


Você pode quebrar seu aplicativo flask , mas você notou que “Hello World” não é um HTML muito bom?
página? Este é um aplicativo da web e, como tal, precisa de uma resposta HTML adequada. Para fazer isso você criará
um modelo simples que diz “Hello World” em uma grande fonte verde.

A primeira etapa é criar um arquivo templates/index.html parecido com este:


Machine Translated by Google

SEU PRIMEIRO SITE 261

index.html

<html>
<cabeça>
<title>Gothons do Planeta Percal #25</title>
</head>
<corpo>

{% se estiver cumprimentando %}

Eu só queria dizer <em


style="color: green; font-size: 2em;">{{ saudação }}</em>. {% else %} <em>Olá</em>,
mundo!

{% fim se %}

</body>
</html>

Se você sabe o que é HTML, isso deve parecer bastante familiar. Caso contrário, pesquise HTML e tente escrever algumas
páginas da web à mão para saber como funciona. Este arquivo HTML, entretanto, é um modelo, o que significa que o flask
preencherá “buracos” no texto dependendo das variáveis que você passar para o modelo. Cada lugar que você vê {{ saudação }}
será uma variável que você passará para o modelo que altera seu conteúdo.

Para fazer seu app.py fazer isso, você precisa adicionar algum código para informar ao flask onde carregar o modelo e
renderizá-lo. Pegue esse arquivo e altere-o assim:

aplicativo.py

1 da importação do frasco Frasco 2


da importação do frasco render_template
3

4 aplicativo = Frasco (__name__)


5

6 @app.route("/") 7 def
index(): saudação =
8 "Olá Mundo" return
9 render_template("index.html", saudação=saudação)
10

11 se __name__ == "__main__":
12 app.run()

Depois de fazer isso, recarregue a página da web em seu navegador e você verá uma mensagem diferente em verde. Você
também deve ser capaz de visualizar o código-fonte na página do seu navegador para ver se é HTML válido.

Isso pode ter passado por você muito rápido, então deixe-me explicar como funciona um modelo:
Machine Translated by Google

262 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

1. Em seu app.py você importou uma nova função chamada render_template na parte superior.

2. Este render_template sabe como carregar arquivos .html fora do diretório templates/ porque
essa é a configuração mágica padrão para um aplicativo Flask.

3. Mais tarde no seu código, quando o navegador atingir o índice def, em vez de apenas retornar a string
saudação, você chama render_template e passa a saudação para ele como uma variável.

4. Este método render_template então carrega o arquivo templates/index.html (mesmo que você
não disse explicitamente modelos) e os processa.

5. Neste arquivo templates/index.html você tem o que parece ser HTML normal, mas há “código” colocado entre dois
tipos de marcadores. Um deles é {% %}, que marca pedaços de “código executável” (instruções if, loops for, etc). A
outra é {{ }} que marca variáveis a serem convertidas em texto e colocadas na saída HTML. O código executável {%
%} não aparece no HTML. Para saber mais sobre esta linguagem de modelo, leia a documentação do Jinja2.

Para se aprofundar nisso, altere a variável de saudação e o HTML para ver o efeito que ela tem. Crie também outro modelo
chamado templates/foo.html e renderize-o como antes.

Exercícios de estudo

1. Leia a documentação em http://flask.pocoo.org/docs/0.12/, que é o mesmo que o projeto do frasco .

2. Experimente tudo o que encontrar lá, incluindo o código de exemplo.

3. Leia sobre HTML5 e CSS3 e crie outros arquivos .html e .css para praticar.

4. Se você tem um amigo que conhece Django e está disposto a ajudá-lo, considere fazer Exercícios
50, 51 e 52 no Django para ver como é.

Perguntas comuns dos alunos

Não consigo me conectar a http://localhost:5000/. Tente acessar http://127.0.0.1:5000/ .

Não consigo encontrar index.html (ou qualquer coisa). Você provavelmente está fazendo cd bin/ primeiro e depois
tentando trabalhar com o projeto. Não faça isso. Todos os comandos e instruções assumem que você está em um
diretório acima de bin/, então se você não consegue digitar python app.py então você está no diretório errado.

Por que atribuímos saudação=saudação quando chamamos o modelo? Você não está atribuindo saudação.
Você está definindo um parâmetro nomeado para fornecer ao modelo. É uma espécie de atribuição, mas afeta apenas
a chamada para a função do modelo.
Machine Translated by Google

SEU PRIMEIRO SITE 263

Não consigo usar a porta 5000 no meu computador. Você provavelmente tem um programa antivírus instalado que está usando
aquele porto. Experimente uma porta diferente.
Machine Translated by Google

264

EXERCÍCIO 51

Obtendo informações de um navegador

Embora seja emocionante ver o navegador exibir “Hello World”, é ainda mais emocionante permitir que o usuário envie texto para
seu aplicativo a partir de um formulário. Neste exercício, melhoraremos nossa aplicação web inicial usando formulários e
armazenando informações sobre os usuários em suas “sessões”.

Como funciona a web


É hora de algumas coisas chatas. Você precisa entender um pouco mais sobre como a web funciona antes de criar um formulário.
Esta descrição não está completa, mas é precisa e ajudará você a descobrir o que pode estar errado com seu aplicativo. Além
disso, criar formulários será mais fácil se você souber o que eles fazem.

Começarei com um diagrama simples que mostra as diferentes partes de uma solicitação web e como as informações fluem:

Rotulei as linhas com letras para poder orientá-lo em um processo de solicitação regular:

1. Você digita o URL http://test.com// em seu navegador e envia a solicitação on- line (A) para
interface de rede do seu computador.

2. Sua solicitação sai pela Internet on- line (B) e depois para o computador remoto on- line (C) onde meu servidor aceita a
solicitação.

3. Assim que meu computador aceitar, meu aplicativo da web o colocará on- line (D) e meu código Python será executado
o manipulador index.GET .
Machine Translated by Google

OBTENDO ENTRADA DE UM NAVEGADOR 265

4. A resposta sai do meu servidor Python quando eu a devolvo e volta para o seu navegador pela linha (D) novamente.

5. O servidor que executa este site coloca a resposta off- line (D) e a envia de volta pela Internet
na linha (C).

6. A resposta do servidor sai da Internet on- line (B) e do seu computador


interface de rede entrega-o ao seu navegador on- line (A).

7. Finalmente, seu navegador exibe a resposta.

Nesta descrição há alguns termos que você deve conhecer para ter um vocabulário comum com o qual trabalhar ao falar
sobre sua aplicação web:

Navegador O software que você provavelmente usa todos os dias. A maioria das pessoas não sabe o que um navegador
realmente faz. Eles apenas chamam os navegadores de “internet”. Seu trabalho é obter endereços (como http://
test.com/) você digita na barra de URL e usa essas informações para fazer solicitações ao servidor nesse endereço.

Endereço Normalmente é um URL (Uniform Resource Locator) como http://test.com// e indica para onde o navegador
deve ir. A primeira parte, http, indica o protocolo que você deseja utilizar, neste caso “Protocolo de Transporte de
Hipertexto”. Você também pode tentar ftp://ibiblio.org/ para ver como funciona o “Protocolo de Transporte de
Arquivos”. O http://test.com/ parte é o “nome do host”, um endereço legível que você pode lembrar e que mapeia
para um número chamado endereço IP, semelhante a um número de telefone de um computador na Internet.
Finalmente, os URLs podem ter um caminho final como a parte /book/ de http://test.com//book/, que indica um
arquivo ou algum recurso no servidor para recuperar com uma solicitação. Existem muitas outras partes, mas
essas são as principais.

Conexão Depois que um navegador souber qual protocolo você deseja usar (http), com qual servidor você deseja se
comunicar (http://test.com/), e qual recurso desse servidor obter, ele deve fazer uma conexão. O navegador
simplesmente pede ao seu sistema operacional (SO) para abrir uma “porta” para o computador, geralmente a
porta 80. Quando funciona, o SO devolve ao seu programa algo que funciona como um arquivo, mas na verdade
está enviando e recebendo bytes. os fios de rede entre o seu computador e o outro computador em http://test.com/.
Isso também é a mesma coisa que acontece com http://localhost:8080/, mas neste caso você está dizendo ao
navegador para se conectar ao seu próprio computador (localhost) e usar a porta 8080 em vez do padrão 80.
Você também pode fazer http://test.com:80/ e obtenha o mesmo resultado, exceto que você está dizendo
explicitamente para usar a porta 80 em vez de deixá-la assim por padrão.

Solicitar Seu navegador está conectado usando o endereço que você forneceu. Agora ele precisa solicitar o recurso que
deseja (ou deseja) no servidor remoto. Se você forneceu /book/ no final da URL, então você deseja o arquivo
(recurso) em /book/, e a maioria dos servidores usará o arquivo real /book/index.html , mas fingirá que ele não
existe. O que o navegador faz para obter esse recurso é enviar uma solicitação ao servidor. Não vou entrar em
detalhes exatamente como isso acontece, mas apenas entendo que é necessário enviar algo para consultar o
servidor sobre a solicitação. O interessante é que esses “recursos” não precisam ser arquivos. Por exemplo,
quando o navegador do seu aplicativo solicita algo, o servidor está retornando algo gerado pelo seu código Python.
Machine Translated by Google

266 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

Servidor O servidor é o computador no final da conexão de um navegador que sabe como responder às solicitações de arquivos/
recursos do seu navegador. A maioria dos servidores web apenas envia arquivos, e isso representa a maior parte do
tráfego. Mas, na verdade, você está construindo um servidor em Python que sabe como receber solicitações de recursos e,
em seguida, retornar strings criadas usando Python. Ao fazer essa elaboração, você está fingindo ser um arquivo para o
navegador, mas na verdade é apenas um código. Como você pode ver no Exercício 50, também não é necessário muito
código para criar uma resposta.

Resposta Este é o HTML (CSS, JavaScript ou imagens) que seu servidor deseja enviar de volta ao navegador como resposta à
solicitação do navegador. No caso de arquivos, ele apenas os lê do disco e os envia para o navegador, mas agrupa o
conteúdo do disco em um “cabeçalho” especial para que o navegador saiba o que está obtendo. No caso do seu aplicativo,
você ainda está enviando a mesma coisa, incluindo o cabeçalho, mas gera esses dados dinamicamente com seu código
Python.

Esse é o curso intensivo mais rápido sobre como um navegador acessa informações em servidores na Internet.

Deve funcionar bem o suficiente para que você entenda este exercício, mas se não, leia sobre ele o máximo que puder até entendê-
lo. Uma boa maneira de fazer isso é pegar o diagrama e quebrar diferentes partes da aplicação web que você fez no Exercício 50.
Se você puder quebrar sua aplicação web de maneira previsível usando o diagrama, você começará a entender como ele funciona.

Como funcionam os formulários

A melhor maneira de brincar com formulários é escrever algum código que aceite dados de formulário e então ver o que você pode
fazer. Pegue seu arquivo app.py e faça com que fique assim:

form_test.py

1 da importação do frasco Frasco


2 da importação do frasco render_template 3
da solicitação de importação do frasco
4

5 aplicativo = Frasco (__name__)


6

7 @app.route("/hello") 8 def
index(): nome =
9 request.args.get('nome', 'Ninguém')
10

11 se nome:
12 saudação = f"Olá, {nome}" else:
13

14 saudação = "Olá mundo"


15

16 return render_template("index.html", saudação=saudação)


17
Machine Translated by Google

OBTENDO ENTRADA DE UM NAVEGADOR 267

18 se __name__ == "__main__":
19 app.run()

Reinicie-o (pressione CTRL-C e execute-o novamente) para garantir que ele carregue novamente e, em seguida,
com seu navegador, acesse http://localhost:5000/hello, que deverá exibir: “Eu só queria dizer Olá, ninguém. ” Em
seguida, altere o URL em seu navegador para http://localhost:5000/hello?name=Frank e você verá a mensagem
“Olá, Frank”. Por fim, altere a parte name=Frank para ser o seu nome. Agora está dizendo olá para você.

Vamos detalhar as alterações que fiz no seu script.

1. Em vez de apenas uma string para saudação, agora estou usando request.args para obter dados do navegador.
Este é um ditado simples que contém os valores do formulário como pares chave=valor.

2. Em seguida, construo a saudação a partir do novo nome, que já deve ser muito familiar para você.

3. Todo o resto do arquivo é igual a antes.

Você também não está restrito a apenas um parâmetro no URL. Altere este exemplo para fornecer duas variáveis
como esta: http://localhost:5000/hello?name=Frank&greet=Hola. Em seguida, altere o código para obter name e
greet assim: greet =
'
request . argumentos. get ('saudação , ' Olá ' )
saudação = f” {saudação}, {nome}”

Você também deve tentar não fornecer os parâmetros greet e name na URL. Você simplesmente enviará seu
navegador para http://localhost:5000/hello para ver que o índice agora tem como padrão “Ninguém” para nome e
“Hello” para saudação.

Criação de formulários HTML

Passar os parâmetros na URL funciona, mas é meio feio e não é fácil de usar para pessoas comuns.
O que você realmente deseja é um “formulário POST”, que é um arquivo HTML especial que contém uma tag
<form> . Este formulário coletará informações do usuário e as enviará para seu aplicativo da web, como você fez acima.

Vamos fazer um rápido para você ver como funciona. Aqui está o novo arquivo HTML que você precisa criar, em
templates/hello_form.html:

olá_formulário.html

<html>
<cabeça>

<title>Exemplo de formulário web</title>


</head>
<corpo>
Machine Translated by Google

268 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

<h1>Preencha este formulário</h1>

<form action="/hello" método="POST">


Uma saudação: <input type="text" name="greet">
<br/>
Seu nome: <input type="text" name="name">
<br/>
<input type="enviar">
</form>

</body>
</html>

Você deve então alterar app.py para ficar assim:

aplicativo.py

1 do frasco de importação Frasco


2 do frasco importar render_template
3 da solicitação de importação do frasco
4

5 aplicativo = Frasco (__name__)


6

7 @app.route("/hello", métodos=['POST', 'GET'])


8 índice de definição ():
9 saudação = "Olá mundo"
10

11 se request.method == "POST":
12 nome = solicitação.form['nome']
13 cumprimentar = solicitação.form['saudação']
14 saudação = f"{saudação}, {nome}"
15 return render_template("index.html", saudação=saudação)
16 outro:
17 retornar render_template("hello_form.html")
18

19

20 se __nome__ == "__main__":
21 app.run()

Depois de escrevê-los, basta reiniciar o aplicativo da web novamente e acessá-lo com seu navegador
como antes.

Desta vez, você receberá um formulário solicitando “Uma saudação” e “Seu nome”. Quando você clica em Enviar
botão no formulário, você receberá a mesma saudação que normalmente recebe, mas desta vez observe o URL
no seu navegador. Veja como é http://localhost:5000/hello mesmo que você tenha enviado parâmetros.
Machine Translated by Google

OBTENDO ENTRADAS DE UM NAVEGADOR 269

A parte do arquivo hello_form.html que faz isso funcionar é a linha com <form action="/hello" method="POST">. Isso diz ao
seu navegador para:

1. Colete dados do usuário usando os campos do formulário.

2. Envie-os para o servidor usando uma solicitação do tipo POST , que é apenas outra solicitação do navegador que
”oculta” os campos do formulário.

3. Envie isso para a URL /hello (conforme mostrado na parte action="/hello" ).

Você poderá então ver como as duas tags <input> correspondem aos nomes das variáveis em seu novo código. Observe
também que em vez de apenas um método GET dentro do índice da classe, tenho outro método, POST. O funcionamento
deste novo aplicativo é o seguinte:

1. Sua solicitação vai para index() normalmente, exceto que agora há uma instrução if que verifica o request.method
para os métodos "POST" ou "GET" . É assim que o navegador informa ao app.py que uma solicitação é um envio
de formulário ou parâmetros de URL.

2. Se request.method for "POST", então você processa o formulário como se tivesse sido preenchido e enviado,
retornando a devida saudação.

3. Se request.method for qualquer outra coisa, basta retornar hello_form.html para o usuário
preencher.

Como exercício, acesse o arquivo templates/index.html e adicione um link apenas para /hello para que você possa continuar
preenchendo o formulário e vendo os resultados. Certifique-se de explicar como esse link funciona e como ele permite
alternar entre templates/index.html e templates/hello_form.html e o que está sendo executado neste código Python mais
recente.

Criando um modelo de layout


Ao trabalhar em seu jogo no próximo exercício, você precisará criar um monte de pequenas páginas HTML.
Escrever uma página da web inteira de cada vez rapidamente se tornará entediante. Felizmente você pode criar um modelo
de “layout”, ou um tipo de shell que envolverá todas as suas outras páginas com cabeçalhos e rodapés comuns. Bons
programadores tentam reduzir a repetição, por isso os layouts são essenciais para ser um bom programador.

Altere templates/index.html para ficar assim:

index_laid_out.html

{% estende "layout.html" %}

{% bloquear conteúdo %}
Machine Translated by Google

270 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

{% se estiver cumprimentando %}

Eu só queria dizer <em


style="color: green; font-size: 2em;">{{ saudação }}</em>. {% else %} <em>Olá</em>,
mundo!

{% fim se %}

{% bloco final %}

Em seguida, altere templates/hello_form.html para ficar assim:

olá_form_laid_out.html

{% estende "layout.html" %}

{% bloquear conteúdo %}

<h1>Preencha este formulário</h1>

<form action="/hello" método="POST">


Uma saudação: <input type="text" name="greet"> <br/>

Seu nome: <input type="text" name="name"> <br/>

<input type="enviar">
</form>

{% bloco final %}

Tudo o que estamos fazendo é retirar o “padrão” na parte superior e inferior, que está sempre em todas as páginas.
Colocaremos isso de volta em um único arquivo templates/layout.html que cuidará disso para nós de agora em diante.

Depois de fazer essas alterações, crie um arquivo templates/layout.html com isto:

layout.html

<html>
<cabeça>
<title>Gothons do Planeta Percal #25</title>
</head>
<corpo>

{% bloquear conteúdo %}

{% bloco final %}
Machine Translated by Google

OBTENDO ENTRADAS DE UM NAVEGADOR 271

</body>
</html>

Este arquivo se parece com um modelo normal, exceto que será passado o conteúdo do outro
modelos e usados para envolvê -los. Qualquer coisa que você colocar aqui não precisa estar nos outros modelos.
Seus outros modelos HTML serão inseridos na seção {% block content %} . Flask sabe usar
este layout.html como o layout porque você colocou {% extends "layout.html" %} no topo do seu
modelos.

Escrevendo testes automatizados para formulários

É fácil testar um aplicativo da web com seu navegador apenas clicando em atualizar, mas vamos lá, somos programadores
aqui. Por que fazer algumas tarefas repetitivas quando podemos escrever algum código para testar nosso aplicativo? O que
o que você fará a seguir é escrever um pequeno teste para seu formulário de inscrição na web com base no que você aprendeu
no Exercício 47. Se você não se lembra do Exercício 47, leia-o novamente.

Crie um novo arquivo chamado testes/app_tests.py com isto:

app_tests.py

*
1 do nose.tools importar 2 do
aplicativo de importação de aplicativo
3

4 app.config['TESTING'] = Verdadeiro
5 web = app.test_client()
6

7 def índice_teste():
8 rv = web.get('/', follow_redirects=True)
9 assert_equal(rv.status_code, 404)
10

11 rv = web.get('/olá', follow_redirects=True)
12 assert_equal(rv.status_code, 200)
13 assert_in(b"Preencha este formulário", rv.data)
14

15 dados = {'nome': 'Zed', 'saudação': 'Olá'}


16 rv = web.post('/olá', follow_redirects=True, dados=dados)
17 assert_in(b"Zed", rv.dados)
18 assert_in(b"Olá", rv.data)

Por fim, use nosetests para executar esta configuração de teste e testar sua aplicação web:

$ no s e t e s t s
.
Machine Translated by Google

272 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

------------------------------------------- ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ

Executei 1 teste em 0,059 s

OK

O que estou fazendo aqui é importar todo o aplicativo do módulo app.py e, em seguida,
executando-o manualmente. A estrutura flask possui uma API muito simples para processar solicitações, que parece
assim:

' '
dados = { 'nome' rv : 'Zed' , : ' Hora ' }
= web. postar ( ' / olá ' , _ resiga
cumprimente direts = Verdadeiro , dados=dados)

Isso significa que você pode enviar uma solicitação POST usando o método post() e, em seguida, fornecer os dados do formulário como um
ditar. Todo o resto funciona da mesma forma que testar solicitações web.get() .

No teste automatizado tests/app_tests.py , primeiro estou certificando-me de que o URL / retorne um "404 Not Found"
resposta, já que na verdade não existe. Então estou verificando se /hello funciona tanto com um GET quanto com um
Formulário POST . Seguir o teste deve ser bastante simples, mesmo que você não saiba totalmente o que está acontecendo
sobre.

Reserve algum tempo estudando este aplicativo mais recente, especialmente como funciona o teste automatizado. Certificar-se
você entendeu como importei o aplicativo do app.py e o executei diretamente para o teste automatizado.
Este é um truque importante que levará a mais aprendizado.

Exercícios de estudo

1. Leia ainda mais sobre HTML e dê um layout melhor ao formulário simples. Ajuda desenhar o que você
deseja fazer no papel e depois implementá-lo com HTML.

2. Este é difícil, mas tente descobrir como você faria um formulário de upload de arquivo para poder enviar um
imagem e salve-a no disco.

3. Isso é ainda mais entorpecente, mas procure o HTTP RFC (que é o documento que descreve
como o HTTP funciona) e leia o máximo que puder. É muito chato, mas é útil uma vez
daqui a pouco.

4. Isso também será muito difícil, mas veja se consegue encontrar alguém para ajudá-lo a configurar um servidor web
como Apache, Nginx ou thttpd. Tente servir alguns de seus arquivos .html e .css apenas para ver
se você puder. Não se preocupe se não puder. Servidores da Web são uma droga.

5. Faça uma pausa depois disso e tente criar o máximo de aplicativos da web diferentes que puder.
Machine Translated by Google

OBTENDO ENTRADAS DE UM NAVEGADOR 273

Quebrando
Este é um ótimo lugar para descobrir como quebrar aplicativos da web. Você deve experimentar o seguinte:

1. Quanto dano você pode causar com a configuração FLASK_DEBUG ativada? Tenha cuidado para não se cansar fazendo
isso.

2. Digamos que você não tenha parâmetros padrão para os formulários. O que poderia dar errado?

3. Você está verificando POST e depois “qualquer outra coisa”. Você pode usar a ferramenta de linha de comando curl para
gerar diferentes tipos de solicitação. O que acontece?
Machine Translated by Google

274

EXERCÍCIO 52

O início do seu jogo na web

Estamos chegando ao final do livro e neste exercício vou realmente desafiar você. Quando terminar, você será um iniciante
em Python razoavelmente competente. Você ainda precisará ler mais alguns livros e escrever mais alguns projetos, mas terá
as habilidades necessárias para concluí-los. A única coisa que atrapalhará será tempo, motivação e recursos.

Neste exercício, não faremos um jogo completo, mas sim um “motor” que pode rodar o jogo do Exercício 47 no navegador.
Isso envolverá a refatoração do Exercício 43, a mistura da estrutura do Exercício 47, a adição de testes automatizados e,
finalmente, a criação de um mecanismo web que possa executar os jogos.

Este exercício será enorme e prevejo que você poderá gastar de uma semana a meses nele antes de prosseguir. É melhor
atacá-lo em pequenos pedaços e fazer um pouco por noite, reservando um tempo para fazer tudo funcionar antes de
prosseguir.

Refatorando o Jogo do Exercício 43


Você alterou o projeto gothonweb em dois exercícios e fará isso mais uma vez neste exercício. A habilidade que você está
aprendendo é chamada de “refatoração” ou, como gosto de chamar, “consertar coisas”. Refatoração é um termo que os
programadores usam para descrever o processo de pegar código antigo e alterá-lo para ter novos recursos ou apenas para
limpá-lo. Você tem feito isso sem nem mesmo saber, pois é uma segunda natureza na construção de software.

O que você fará nesta parte é pegar as ideias do Exercício 47 de um “mapa” testável de Salas e do jogo do Exercício 43 e
combiná-las para criar uma nova estrutura de jogo. Terá o mesmo conteúdo, apenas “refatorado” para ter uma estrutura
melhor.

A primeira etapa é pegar o código de ex47/game.py, copiá-lo para gothonweb/planisphere.py, copiar o arquivo testes/
ex47_tests.py para testes/planisphere_tests.py e executar o nosetests novamente para garantir que continue funcionando. A
palavra “planisfério” é apenas sinônimo de “mapa”, o que evita a função de mapa integrada do Python . O Thesaurus é seu
amigo.

AVISO! De agora em diante, não mostrarei o resultado de um teste. Apenas suponha que você deveria
estar fazendo isso e será semelhante ao anterior, a menos que haja um erro.

Depois de copiar o código do Exercício 47, é hora de refatorá-lo para incluir o mapa do Exercício 43. Vou começar
estabelecendo a estrutura básica e, em seguida, você terá a tarefa de completar o arquivo planisphere.py e o arquivo
planisphere_tests.py .
Machine Translated by Google

O INÍCIO DO SEU JOGO WEB 275

Esboce a estrutura básica do mapa usando a classe Room como está agora:

planisphere.py

1 sala de aula (objeto):


2

3 def __init__(self, nome, descrição):


4 self.name = nome
5 self.description = descrição self.paths =
6 {}
7

8 def go(self, direção): return


9 self.paths.get(direção, Nenhum)
10

11 def add_paths(self, caminhos):


12 self.paths.update(caminhos)
13

14

15 corredor_central = Sala("Corredor Central",


"""
16

17 Os Gothons do Planeta Percal #25 invadiram sua nave e destruíram 18 de toda a sua tripulação.
Você é o último membro sobrevivente e sua última missão é pegar a bomba de destruição de
nêutrons do Arsenal de Armas, colocar 20 na ponte e explodir a nave depois de entrar em uma cápsula
de fuga.
21

22 Você está correndo pelo corredor central em direção ao Arsenal de Armas quando um Gothon
23 salta, pele escamosa vermelha, dentes escuros e sujos e fantasia de palhaço malvado 24
fluindo ao redor de seu corpo cheio de ódio. Ele está bloqueando a porta do Arsenal 25 e prestes a
sacar uma arma para explodir você. 26 """)

27

28

29 laser_weapon_armory = Room("Arsenal de Armas Laser",


"""
30

31 Sorte sua que eles fizeram você aprender os insultos de Gothon na academia. Você 32 conta a
única piada de Gothon que você conhece: Lbhe zbgure vf fb sng, jura fur fvgf 33 nebhaq gur ubhfr, fur
fvgf nebhaq gur ubhfr. O Gothon para, tenta não rir, depois cai na gargalhada e não consegue se
mover. Enquanto ele está rindo , você corre e atira bem na cabeça dele, derrubando-o, 36 e
então salte pela porta do Arsenal de Armas.

37

38 Você faz um mergulho no Arsenal de Armas, agacha-se e examina a sala em busca de mais 39
Gothons que possam estar escondidos. Está muito quieto, muito quieto. Você 40 se levanta e
corre para o outro lado da sala e encontra a bomba de nêutrons 41 em seu recipiente. Há um
bloqueio de teclado na caixa e você precisa do
Machine Translated by Google

276 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

Código 42 para retirar a bomba. Se você errar o código 10 vezes, a fechadura 43 fecha para sempre e você não conseguirá pegar a bomba. O

código tem 3 dígitos. 44 """)

45

46

47 the_bridge = Room("A Ponte",


48 """
49 O recipiente se abre e o lacre se rompe, liberando o gás. Você 50 pega a bomba de nêutrons e corre o mais rápido que puder até a ponte

onde você 51 deve colocá-la no lugar certo.

52

53 Você invade a ponte com a bomba de destruição Netron debaixo do braço 54 e surpreende 5 Gothons que estão tentando assumir o controle

da nave. Cada 55 deles tem uma fantasia de palhaço ainda mais feia que a anterior. Eles ainda não sacaram as armas 56 , pois veem a bomba

activa debaixo do seu braço 57 e não querem detoná-la.

58 """)
59

60

61 escape_pod = Room("Pod de fuga",


62 """

63 Você aponta seu blaster para a bomba que está debaixo do seu braço e os Gothons levantam
as mãos 64 e começam a suar. Você recua lentamente em direção à porta, abre - a e, em seguida,
coloca cuidadosamente a bomba no chão, apontando seu blaster 66 para ela. Você então
pula de volta pela porta, aperta o botão de fechar 67 e explode a fechadura para que os Gothons
não possam sair. Agora que a bomba 68 está colocada, você corre para a cápsula de fuga para
sair desta lata.
69

70 Você corre pela nave tentando desesperadamente chegar à cápsula de fuga 71 antes que toda a nave exploda. Parece que quase nenhum

Gothons 72 está na nave, então sua corrida está livre de interferências. Você chega à câmara 73 com as cápsulas de fuga e agora precisa

escolher uma para levar. Alguns dos 74 deles podem estar danificados, mas você não tem tempo para olhar. São 5 cápsulas, 75 qual você pega?

76 """)

77

78

79 the_end_winner = Room("Fim ",


80 """

81 Você pula no pod 2 e aperta o botão de ejeção. A cápsula desliza facilmente para o espaço em
direção ao planeta abaixo. Enquanto ela voa para o planeta, você 83 olha para trás e vê sua nave
implodir e depois explodir como uma estrela brilhante, 84 destruindo a nave Gothon ao mesmo
tempo. Você ganhou! 85 """)

86
Machine Translated by Google

O INÍCIO DO SEU JOGO WEB 277

87

88 the_end_loser = Room("Fim ",


"""
89

90 Você pula em um pod aleatório e aperta o botão de ejetar. A cápsula escapa

91 no vazio do espaço, então implode quando o casco se rompe, esmagando

Transforme seu corpo em geleia.


"""
93

94 )
95

96 escape_pod.add_paths({
97 '2': the_end_winner,
98 '*': the_end_loser
99 })

100

101 generic_death = Room("morte", "Você morreu.")


102

103 the_bridge.add_paths({
104 'jogar a bomba': generic_death,
105 'coloque lentamente a bomba': escape_pod
106 })

107

108 laser_weapon_armory.add_paths({
109 '0132': a_ponte,
110 '*': morte_genérica
111 })

112

113 central_corredor.add_paths({
114 'atirar!': morte_genérica,
115 'esquivar!': morte_genérica,
116 'conte uma piada': laser_weapon_armory
117 })

118

119 INICIAR = 'corredor_central'


120

121 def load_room(nome):


"""
122

123 Há um problema potencial de segurança aqui.


124 Quem pode definir o nome? Isso pode expor uma variável?
"""
125

126 retornar globals().get(nome)


127

128 def nome_sala(sala):


"""
129

130 O mesmo possível problema de segurança. Você pode confiar no quarto?


Machine Translated by Google

278 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

131 Qual é a melhor solução do que esta pesquisa global?


"""
132

133 para chave, valor em globals().items():


134 se valor == quarto:
135 chave de retorno

Você notará que há alguns problemas com nossa classe Room e este mapa:

1. Temos que colocar o texto que estava nas cláusulas if-else que foram impressas antes de entrar na sala
como parte de cada quarto. Isso significa que você não pode embaralhar o planisfério, o que seria bom.
Você consertará isso neste exercício.

2. Há partes do jogo original em que executamos códigos que determinavam coisas como a bomba
código do teclado ou o pod direito. Neste jogo, apenas escolhemos alguns padrões e seguimos em frente, mas depois
você receberá exercícios de estudo para fazer isso funcionar novamente.

3. Acabei de fazer um final generic_death para todas as decisões erradas, pelas quais você terá que terminar
meu. Você precisará voltar e adicionar todos os finais originais e ter certeza de que funcionam.

4. Eu tenho um novo tipo de transição chamada "*" que será usada para uma ação “pega-tudo” no mecanismo.

Depois de escrever isso basicamente, aqui estão os novos testes de teste automatizados/planisphere_test.py
que você deveria ter para começar:

planisphere_tests.py

*
1 da importação de nose.tools 2
*
da importação de gothonweb.planisphere
3

4 def sala_teste():
5 ouro = Sala("Sala Dourada",
6 """Esta sala tem ouro que você pode pegar. Há um
7 porta para o norte.""")
8 assert_equal(ouro.nome, "GoldRoom")
9 assert_equal(ouro.paths, {})
10

11 def test_room_paths():
12 center = Room("Centro", "Sala de teste no centro.")
13 norte = Room("Norte", "Sala de teste no norte.")
14 sul = Room("Sul", "Sala de teste no sul.")
15

16 center.add_paths({'norte': norte, 'sul': sul})


17 assert_equal(center.go('norte'), norte)
18 assert_equal(center.go('sul'), sul)
19

20 def test_map():
Machine Translated by Google

O INÍCIO DO SEU JOGO WEB 279

21 start = Room("Iniciar", "Você pode ir para oeste e descer um buraco.")


22 oeste = Room("Árvores", "Há árvores aqui, você pode ir para o leste.")
23 down = Room("Dungeon", "Está escuro aqui, você pode subir.")
24

25 start.add_paths({'oeste': oeste, 'para baixo': para baixo})


26 oeste.add_paths({'leste': início})
27 down.add_paths({'up': início})
28

29 assert_equal(start.go('oeste'), oeste)
30 assert_equal(start.go('west').go('east'), start)
31 assert_equal(start.go('down').go('up'), start)
32

33 def test_gothon_game_map():
34 sala_inicial = sala_carregamento(INICIAR)
35 assert_equal(start_room.go('atirar!'), generic_death)
36 assert_equal(start_room.go('esquivar!'), generic_death)
37

38 sala = start_room.go('conte uma piada')


39 assert_equal(sala, laser_weapon_armory)

Sua tarefa nesta parte do exercício é completar o mapa e fazer o teste automatizado completamente
validar todo o mapa. Isso inclui consertar todos os objetos generic_death como finais reais. Fazer
certifique-se de que isso funciona muito bem e que seu teste está o mais completo possível porque iremos mudar isso
mapeie mais tarde e você usará os testes para garantir que ele continue funcionando.

Criando um mecanismo

Você deve ter seu mapa de jogo funcionando e um bom teste de unidade para ele. Agora quero que você faça um simples
pequeno mecanismo de jogo que administrará as salas, coletará informações do jogador e acompanhará onde um
jogador está no jogo. Usaremos as sessões que você acabou de aprender para criar um mecanismo de jogo simples que
fará o seguinte:

1. Inicie um novo jogo para novos usuários.

2. Apresente a sala ao usuário.

3. Receba informações do usuário.

4. Execute a entrada do usuário durante o jogo.

5. Exiba os resultados e continue até que o usuário morra.

Para fazer isso, você pegará o confiável app.py que está hackeando e criará um arquivo totalmente funcional,
mecanismo de jogo baseado em sessão. O problema é que vou fazer um muito simples com arquivos HTML básicos e
caberá a você concluí-lo. Aqui está o motor básico:
Machine Translated by Google

280 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

aplicativo.py

1 da importação do frasco Frasco, sessão, redirecionamento, url_for, escape, solicitação


2 do frasco importar render_template
3 do planisfério de importação gothonweb
4

5 aplicativo = Frasco (__name__)


6

7@app.route ("/")
8 índice de definição ():
9 # isto é usado para "configurar" a sessão com valores iniciais
10 session['room_name'] = planisfério.START
11 retornar redirecionamento(url_for("jogo"))
12

13 @app.route("/game", métodos=['GET', 'POST'])


Jogo com 14 defesas ():
15 nome_sala = session.get('nome_sala')
16

17 se request.method == "GET":
18 se nome_quarto:
19 sala = planisphere.load_room(room_name)
20 return render_template("show_room.html", sala=sala)
21 outro:
22 #por que está aqui? Você precisa disso?'
23 return render_template("você_morreu.html")
24 outro:
25 ação = request.form.get('ação')
26

27 se room_name e ação:
28 sala = planisphere.load_room(room_name)
29 próxima_sala = sala.go(ação)
30

31 se não for next_room:


32 sessão['room_name'] = planisphere.name_room(sala)
33 outro:
34 sessão['room_name'] = planisphere.name_room(next_room)
35

36 retornar redirecionamento(url_for("jogo"))
37

38

39 # VOCÊ DEVE MUDAR ISSO SE COLOCAR NA INTERNET

40 app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'


41

42 se __nome__ == "__main__":
43 app.run()
Machine Translated by Google

O INÍCIO DO SEU JOGO WEB 281

Há ainda mais coisas novas neste script, mas surpreendentemente é um mecanismo de jogo completo baseado na web em um
arquivo pequeno. Antes de executar app.py você precisa alterar sua variável de ambiente PYTHONPATH. Não sabe o que é isso? Eu
sei, é meio idiota, mas você precisa aprender o que é isso para executar até mesmo programas básicos em Python, mas é assim que
as pessoas em Python gostam das coisas.

No seu terminal, digite:

exportar PYTHONPATH=$PYTHONPATH : .

No Windows PowerShell faça:


$env:PYTHONPATH = ”$env:PYTHONPATH; .

Você só deve fazer isso uma vez por sessão do shell, mas se receber um erro de importação, provavelmente precisará fazer isso ou
fez errado.

Em seguida, você deve excluir templates/hello_form.html e templates/index.html e criar os dois modelos mencionados no código
anterior. Aqui está um template/show_room.html muito simples :

show_room.html

{% estende "layout.html" %}

{% bloquear conteúdo %}

<h1> {{ room.name }} </h1>

<pre>
{{ room.description }} </pre>

{% if room.name in ["death", "The End"] %} <p> <a


href="/"> Jogar de novo?</a></p> {% else %}

<p>
<form action="/game" method="POST">
- <input type="text" name="action"> <input type="ENVIAR">
</form>
</p>
{% endif %}

{% bloco final %}

Esse é o modelo para mostrar uma sala conforme você viaja pelo jogo. Em seguida, você precisa contar a alguém que ele morreu
caso tenha chegado ao final do mapa por acidente, que é templates/you_died.html:
Machine Translated by Google

282 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

você_morreu.html

<h1>Você morreu!</h1>

<p>Parece que você morreu.</p> <p> <a


href="/"> Jogar novamente</a></p>

Com eles implementados, agora você deve ser capaz de fazer o seguinte:

1. Faça com que o teste testes/app_tests.py funcione novamente para testar o jogo. Você não conseguirá fazer muito mais do
que alguns cliques no jogo por causa das sessões, mas deverá conseguir fazer algumas coisas básicas.

2. Execute o script python3.6 app.py e teste o jogo.

Você deve ser capaz de atualizar e consertar o jogo normalmente. Você também deve ser capaz de trabalhar com o HTML e o
mecanismo do jogo até que ele faça tudo o que você deseja.

Seu exame final


Você acha que foi uma grande quantidade de informações lançadas sobre você de uma só vez? Ótimo, quero que você tenha algo
em que mexer enquanto desenvolve suas habilidades. Para completar este exercício, darei a você um conjunto final de exercícios
para você fazer sozinho. Você notará que o que escreveu até agora não está muito bem construído; é apenas uma primeira versão
do código. Sua tarefa agora é tornar o jogo mais completo fazendo o seguinte:

1. Corrija todos os bugs mencionados no código e aqueles que não mencionei. Se você encontrar novos bugs, deixe-me
saber.

2. Melhore todos os testes automatizados para testar mais o aplicativo e chegar a um ponto em que você usa um teste em vez
do navegador para verificar o aplicativo enquanto trabalha.

3. Faça o HTML parecer melhor.

4. Pesquise logins e crie um sistema de inscrição para o aplicativo para que as pessoas possam ter logins e alta
pontuações.

5. Complete o mapa do jogo, tornando-o o maior e mais completo possível.

6. Dê às pessoas um sistema de “ajuda” que lhes permita perguntar o que podem fazer em cada sala do jogo.

7. Adicione quaisquer outros recursos que você possa imaginar ao jogo.


Machine Translated by Google

O INÍCIO DO SEU JOGO WEB 283

8. Crie vários “mapas” e deixe as pessoas escolherem o jogo que desejam jogar. Seu mecanismo app.py deve ser
capaz de executar qualquer mapa de salas fornecido, para que você possa oferecer suporte a vários jogos.

9. Finalmente, use o que você aprendeu nos Exercícios 48 e 49 para criar um processador de entrada melhor. Você
tem a maior parte do código necessário; você só precisa melhorar a gramática e conectá-la ao seu formulário de
entrada e ao GameEngine.

Boa sorte!

Perguntas comuns dos alunos

Estou usando sessões no meu jogo e não consigo testá-lo com testes de nariz. Leia a documentação de teste de
frasco sobre “Outros truques de teste” para obter informações sobre como criar sessões falsas dentro de seus testes.

Eu recebo um ImportError. Pode ser um ou mais destes: diretório errado, versão errada do Python, PYTHONPATH não
definido, nenhum arquivo __init__.py e/ou erro ortográfico na importação.
Machine Translated by Google

284

Próximos passos

Você ainda não é um programador. Gosto de pensar que este livro oferece a você sua “faixa preta em programação”. Você sabe o
suficiente para começar outro livro sobre programação e lidar com isso perfeitamente. Este livro deveria ter fornecido as ferramentas
mentais e a atitude necessárias para ler a maioria dos livros sobre Python e realmente aprender alguma coisa. Pode até facilitar.

Recomendo que você dê uma olhada em alguns desses projetos e tente construir algo com eles:

• Aprenda Ruby da maneira mais difícil Você aprenderá ainda mais sobre programação à medida que aprender mais
linguagens de programação, então tente aprender Ruby também.

• O Tutorial Django e tente construir uma aplicação web com o Django Web Framework.

• SciPy se você gosta de ciências, matemática e engenharia.

• PyGame e veja se você consegue fazer um jogo com gráficos e som.

• Pandas para fazer manipulação e análise de dados.

• Kit de ferramentas de linguagem natural para analisar texto escrito e escrever coisas como filtros de spam e bate-papo
robôs. TensorFlow para aprendizado de máquina e visualização.

• Solicitações de para aprender o lado do cliente do HTTP e da web.

• Scrapy e tente copiar alguns sites para obter informações deles.

• Kiev para fazer interfaces de usuário em desktops e plataformas móveis.

• Aprenda C da maneira mais difícil depois de estar familiarizado com Python e tentar aprender C e algoritmos com
meu outro livro. Vá devagar; C é diferente, mas uma coisa muito boa de aprender.

Escolha um dos recursos anteriores e consulte todos os tutoriais e documentação que eles possuem. À medida que você analisa
a documentação com código, digite todo o código e faça-o funcionar. É assim que eu faço. É assim que todo programador faz. Ler
a documentação de programação não é suficiente para aprendê-la; você tem que fazer. Depois de ler o tutorial e qualquer outra
documentação que eles tenham, faça algo. Qualquer coisa serve, mesmo algo que alguém já tenha escrito. Basta fazer alguma
coisa.

Apenas entenda que qualquer coisa que você escrever provavelmente será uma droga. Tudo bem, embora eu seja péssimo em
todas as linguagens de programação que começo a usar. Ninguém escreve ouro puro e perfeito quando é iniciante, e qualquer um
que diga que sim é um grande mentiroso.
Machine Translated by Google

PRÓXIMOS PASSOS 285

Como aprender qualquer linguagem de programação

Vou ensiná-lo a aprender a maioria das linguagens de programação que você pode querer aprender no futuro. A organização deste livro
é baseada em como eu e muitos outros programadores aprendemos novas linguagens. O processo que costumo seguir é:

1. Compre um livro ou algum texto introdutório sobre o idioma.

2. Leia o livro e digite todo o código para executá-lo.

3. Leia o livro enquanto trabalha no código, fazendo anotações.

4. Use a linguagem para implementar um pequeno conjunto de programas com os quais você está familiarizado em outra linguagem.

5. Leia o código de outras pessoas na linguagem e tente copiar seus padrões.

Neste livro, forcei você a passar por esse processo muito lentamente e em pequenos pedaços. Outros livros não são organizados da
mesma maneira, e isso significa que você precisa extrapolar o modo como o fiz fazer isso para a forma como o conteúdo deles é
organizado. A melhor maneira de fazer isso é ler o livro com leveza e fazer uma lista de todas as principais seções do código. Transforme
esta lista em um conjunto de exercícios baseados nos capítulos e simplesmente pratique-os na ordem, um de cada vez.

O processo anterior também funciona para novas tecnologias, desde que haja livros que você possa ler. Para qualquer coisa sem livros,
você segue o processo acima, mas usa documentação online ou código-fonte como introdução inicial.

Cada nova linguagem que você aprende torna você um programador melhor e, à medida que você aprende mais, elas se tornam mais
fáceis de aprender. No seu terceiro ou quarto idioma, você deverá ser capaz de aprender idiomas semelhantes em uma semana,
enquanto idiomas estranhos demoram mais. Agora que você conhece Python, você poderia aprender Ruby e JavaScript com bastante
rapidez em comparação. Isso ocorre simplesmente porque muitos idiomas compartilham conceitos semelhantes e, uma vez que você
aprende os conceitos em um idioma, eles funcionam em outros.

A última coisa a lembrar sobre aprender um novo idioma é esta: não seja um turista estúpido. Turista estúpido é alguém que vai para
outro país e depois reclama que a comida não é igual à de casa. “Por que não consigo comer um bom hambúrguer neste país estúpido!?”
Quando você estiver aprendendo um novo idioma, presuma que o que ele faz não é estúpido, é apenas diferente, e aceite-o para que
possa aprendê-lo.

Depois de aprender um idioma, não seja escravo da maneira como esse idioma faz as coisas. Às vezes, as pessoas que usam uma
língua na verdade fazem coisas muito idiotas sem outra razão a não ser “é assim que sempre fizemos”. Se você gosta mais do seu estilo
e sabe como todo mundo faz isso, sinta-se à vontade para quebrar as regras se isso melhorar as coisas.

Eu realmente gosto de aprender novas linguagens de programação. Eu me considero um “antropólogo programador” e penso neles
como pequenos insights sobre o grupo de programadores que os utilizam. Estou aprendendo uma linguagem que todos usam para
conversar através de computadores, e acho isso fascinante. Então, novamente, sou um cara meio estranho, então aprenda linguagens
de programação porque você quer.

Aproveitar! Isso é realmente divertido.


Machine Translated by Google

286

Conselhos de um antigo programador


Você terminou este livro e decidiu continuar com a programação. Talvez seja uma carreira para você, ou talvez seja um
hobby. Você precisará de alguns conselhos para garantir que continuará no caminho certo e aproveitará ao máximo a
atividade recém-escolhida.

Estou programando há muito tempo. Tanto tempo que é incrivelmente chato para mim. Na época em que escrevi este livro,
eu conhecia cerca de 20 linguagens de programação e poderia aprender novas em cerca de um dia a uma semana,
dependendo de quão estranhas elas fossem. Eventualmente, porém, isso se tornou chato e não conseguiu mais manter meu
interesse. Isso não significa que eu acho que programar é chato, ou que você vai pensar que é chato, apenas que acho isso
desinteressante neste ponto da minha jornada.

O que descobri depois dessa jornada de aprendizado é que não são os idiomas que importam, mas o que você faz com eles.
Na verdade, eu sempre soube disso, mas me distraía com os idiomas e esquecia de vez em quando. Agora eu nunca
esqueço disso, e você também não deveria.

Qual linguagem de programação você aprende e usa não importa. Não se deixe levar pela religião que cerca as linguagens
de programação, pois isso apenas o cegará para o verdadeiro propósito de ser sua ferramenta para fazer coisas interessantes.

A programação como atividade intelectual é a única forma de arte que permite criar arte interativa.
Você pode criar projetos com os quais outras pessoas possam brincar e conversar com elas indiretamente. Nenhuma outra
forma de arte é tão interativa. Os filmes fluem para o público em uma direção. As pinturas não se movem.
O código funciona nos dois sentidos.

A programação como profissão é apenas moderadamente interessante. Pode ser um bom trabalho, mas você pode ganhar
quase o mesmo dinheiro e ser mais feliz administrando uma lanchonete. É muito melhor usar o código como arma secreta
em outra profissão.

As pessoas que sabem codificar no mundo das empresas de tecnologia custam um centavo a dúzia e não são respeitadas.
Pessoas que sabem codificar em biologia, medicina, governo, sociologia, física, história e matemática são respeitadas e
podem fazer coisas incríveis para o avanço dessas disciplinas.

Claro, todos esses conselhos são inúteis. Se você gostou de aprender a escrever software com este livro, tente usá-lo para
melhorar sua vida de todas as maneiras que puder. Saia e explore essa nova e estranha busca intelectual que quase
ninguém nos últimos 50 anos foi capaz de explorar. É melhor aproveitar enquanto pode.

Por fim, direi que aprender a criar software muda você e o torna diferente. Não é melhor ou pior, apenas diferente. Você pode
descobrir que as pessoas o tratam com severidade porque você pode criar software, talvez usando palavras como “nerd”.
Talvez você descubra isso porque pode dissecar a lógica deles de que eles odeiam discutir com você. Você pode até
descobrir que simplesmente saber como um computador funciona o torna irritante e estranho para eles.

Para isso só tenho um conselho: eles podem ir para o inferno. O mundo precisa de mais pessoas estranhas que
Machine Translated by Google

CONSELHOS DE UM ANTIGO PROGRAMADOR 287

sabem como as coisas funcionam e adoram descobrir tudo. Quando eles te tratarem assim, lembre-se de que esta
é a sua jornada, não a deles. Ser diferente não é crime, e as pessoas que dizem isso ficam com inveja porque você
adquiriu uma habilidade que elas nunca, em seus sonhos mais loucos, poderiam adquirir.

Você pode codificar. Eles não podem. Isso é muito legal.


Machine Translated by Google

288

APÊNDICE

Apêndice A: Curso intensivo de linha de comando

Este apêndice é um curso rápido e super rápido sobre como usar a linha de comando. O objetivo é ser feito rapidamente
em cerca de um ou dois dias, e não para ensinar o uso avançado do shell.

Introdução: Cale a boca e Shell


Este apêndice é um curso intensivo sobre como usar a linha de comando para fazer seu computador executar tarefas. Por
ser um curso intensivo, não é tão detalhado ou extenso quanto meus outros livros. Ele foi projetado simplesmente para que
você seja capaz o suficiente para começar a usar seu computador como um programador de verdade faz. Quando terminar
este apêndice, você será capaz de fornecer a maioria dos comandos básicos que todo usuário do shell toca todos os dias.
Você entenderá o básico sobre diretórios e alguns outros conceitos.

O único conselho que vou dar é este:

Cale a boca e digite tudo isso.

Desculpe ser mau, mas é isso que você tem que fazer. Se você tem um medo irracional da linha de comando, a única
maneira de vencer um medo irracional é simplesmente calar a boca e lutar contra ele.

Você não vai destruir seu computador. Você não será jogado em alguma prisão no fundo do campus da Microsoft em
Redmond. Seus amigos não vão rir de você por ser um nerd. Simplesmente ignore quaisquer motivos estúpidos e estranhos
que você tenha para temer a linha de comando.

Por que? Porque se você quer aprender a programar, então você deve aprender isso. Linguagens de programação são
formas avançadas de controlar seu computador com linguagem. A linha de comando é o irmão mais novo das linguagens
de programação. Aprender a linha de comando ensina você a controlar o computador usando a linguagem. Depois de
superar isso, você poderá começar a escrever o código e sentir que realmente possui o pedaço de metal que acabou de
comprar.

55.1.1 Como usar este apêndice

A melhor maneira de usar este apêndice é fazer o seguinte:

• Arranje um pequeno caderno de papel e uma caneta.


Machine Translated by Google

APÊNDICE A: CURSO DE ACIDENTE DE LINHA DE COMANDO 289

• Comece no início do apêndice e faça cada exercício exatamente como lhe foi dito.

• Quando você ler algo que não faz sentido ou que você não entende, anote
no seu caderno. Deixe um pouco de espaço para que você possa escrever uma resposta.

• Depois de terminar um exercício, volte ao seu caderno e reveja as perguntas que tiver.
Tente respondê-las pesquisando on-line e perguntando a amigos que possam saber a resposta. Envie-me um e-mail para
help@learncodethehardway.org e eu vou te ajudar também.

Continue nesse processo de fazer um exercício, anotando as perguntas que você tem, depois voltando e respondendo às perguntas
que puder. Quando terminar, você saberá muito mais do que pensa sobre como usar a linha de comando.

55.1.2 Você estará memorizando coisas

Estou avisando com antecedência que vou fazer você memorizar as coisas imediatamente. Esta é a maneira mais rápida de torná-lo
capaz em alguma coisa, mas para algumas pessoas a memorização é dolorosa. Apenas lute contra isso e faça de qualquer maneira.
A memorização é uma habilidade importante para aprender coisas, então você deve superar o medo dela.

Veja como você memoriza as coisas:

• Diga a si mesmo que você conseguirá . Não tente encontrar truques ou maneiras fáceis de escapar, apenas sente-se e faça.

• Escreva o que deseja memorizar em algumas fichas. Coloque metade do que você precisa aprender
de um lado e outra metade do outro lado.

• Todos os dias, durante cerca de 15 a 30 minutos, estude as fichas, tentando lembrar cada uma delas. Coloque todas as cartas
que você não acertar em uma pilha diferente, apenas perfure essas cartas até ficar entediado, depois experimente o baralho
inteiro e veja se você melhora.

• Antes de ir para a cama, perfure apenas as cartas que errou por cerca de 5 minutos e depois vá dormir.

Existem outras técnicas, como você pode escrever o que precisa aprender em uma folha de papel, plastificá-la e colá-la na parede
do chuveiro. Enquanto estiver tomando banho, pratique o conhecimento sem olhar e, quando ficar preso, dê uma olhada nele para
refrescar a memória.

Se você fizer isso todos os dias, deverá ser capaz de memorizar a maioria das coisas que eu lhe digo para memorizar em cerca de
uma semana a um mês. Depois de fazer isso, quase todo o resto se torna mais fácil e intuitivo, que é o propósito da memorização.
Não se trata de ensinar conceitos abstratos, mas sim de enraizar o básico para que sejam intuitivos e você não precise pensar sobre
eles. Depois de memorizar esses princípios básicos, eles deixam de ser obstáculos que impedem você de aprender conceitos
abstratos mais avançados.
Machine Translated by Google

290 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

A configuração

Neste apêndice você será instruído a fazer três coisas:

• Faça algumas coisas no seu shell (linha de comando, Terminal, PowerShell).

• Aprenda sobre o que você acabou de fazer.

• Faça mais por conta própria.

Para este primeiro exercício você deverá ter seu terminal aberto e funcionando para que você possa fazer o resto do apêndice.

55.2.1 Faça isto

Faça seu Terminal, shell ou PowerShell funcionar para que você possa acessá-lo rapidamente e saber que funciona.

Mac OS

Para macOS, você precisará fazer o seguinte:

• Mantenha pressionada a tecla de comando e aperte a barra de espaço.

• Uma “barra de pesquisa” aparecerá.

• Tipo: terminal

• Clique no aplicativo Terminal que se parece com uma caixa preta.

• Isso abrirá o Terminal.

• Agora você pode ir para o seu dock e clicar com a tecla CTRL pressionada para abrir o menu e selecionar Opções->Manter em
doca.

Agora você tem seu Terminal aberto e ele está no seu dock para que você possa acessá-lo.

Linux

Presumo que se você possui Linux, já sabe como chegar ao seu terminal. Procure no menu do seu gerenciador de janelas qualquer coisa
chamada “Shell” ou “Terminal”.
Machine Translated by Google

APÊNDICE A: CURSO DE CRASH DE LINHA DE COMANDO 291

janelas

No Windows vamos usar o PowerShell. As pessoas costumavam trabalhar com um programa chamado cmd.exe, mas ele não é
tão utilizável quanto o PowerShell. Se você tiver o Windows 7 ou posterior, faça o seguinte:

• Clique em Iniciar.

• Em “Pesquisar programas e arquivos” digite: powershell

• Pressione Enter.

Se você não possui o Windows 7, considere seriamente a atualização. Se você ainda insiste em não atualizar, tente instalar o
Powershell no centro de download da Microsoft. Pesquise online para encontrar “downloads do PowerShell” para a sua versão
do Windows. Você está por conta própria, já que não tenho o Windows XP, mas espero que a experiência do PowerShell seja a
mesma.

55.2.2 Você aprendeu isso

Você aprendeu como abrir seu terminal para poder fazer o restante deste apêndice.

AVISO! Se você tem aquele amigo realmente inteligente que já conhece Linux, ignore-o quando ele lhe disser
para usar algo diferente do Bash. Estou te ensinando Bash. É isso.
Ele afirmará que o zsh lhe dará mais 30 pontos de QI e ganhará milhões no mercado de ações. Ignore-o. Seu
objetivo é ser capaz o suficiente e, nesse nível, não importa qual shell você usa. O próximo aviso é ficar
longe do IRC ou de outros lugares onde “hackers” se encontram. Eles acham engraçado entregar comandos
que podem destruir seu computador.
O comando rm -rf / é um clássico que você nunca deve digitar. Apenas evite-os. Se precisar de ajuda, peça
ajuda a alguém em quem você confia e não a idiotas aleatórios na Internet.

55.2.3 Faça mais

Este exercício tem uma grande parte “faça mais”. Os outros exercícios não são tão complexos quanto este, mas peço que você
prepare seu cérebro para o resto do apêndice fazendo algumas memorizações. Apenas confie em mim: isso tornará as coisas
suaves como a seda mais tarde.

Linux/macOS

Pegue esta lista de comandos e crie fichas com os nomes à esquerda de um lado e as definições do outro lado. Pratique-os todos
os dias enquanto continua com as lições deste apêndice.
Machine Translated by Google

292 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

diretório de trabalho de impressão pwd

hostname o nome da rede do meu computador

mkdir criar diretório

diretório de mudança de cd

ls lista diretório

rmdir remover diretório

diretório pushd push

diretório popdpop

cp copiar um arquivo ou diretório

mv mover um arquivo ou diretório

menos página através de um arquivo

gato imprime o arquivo inteiro

xargs executa argumentos

encontrar encontrar arquivos

grep encontra coisas dentro de arquivos

homem leu uma página de manual

a propósito , descubra qual página de manual é apropriada

env olhe para o seu ambiente

echo imprime alguns argumentos

exportar exportar/definir uma nova variável de ambiente

sair sair do shell

sudo PERIGO! torne-se superusuário root PERIGO!


Machine Translated by Google

APÊNDICE A: CURSO DE ACIDENTE DE LINHA DE COMANDO 293

janelas

Se você estiver usando o Windows, aqui está sua lista de comandos:

diretório de trabalho de impressão pwd

hostname o nome da rede do meu computador

mkdir criar diretório

diretório de mudança de cd

ls lista diretório

rmdir remover diretório

diretório pushd push

diretório popdpop

cp copiar um arquivo ou diretório

cópia robusta do robocopy

mv mover um arquivo ou diretório

mais páginas através de um arquivo

digite imprimir o arquivo inteiro

forfiles executa um comando em muitos arquivos

dir -r encontrar arquivos

select-string encontra coisas dentro de arquivos

ajude a ler uma página de manual

helpctr encontre qual página de manual é apropriada

echo imprima alguns argumentos

definir exportação/definir uma nova variável de ambiente

sair sair do shell

runas PERIGO! torne-se superusuário root PERIGO!

Perfure, perfure, perfure! Faça exercícios até conseguir dizer essas frases imediatamente ao ver essa palavra. Em seguida, faça o inverso, para
que você leia a frase e saiba qual comando fará isso. Você está construindo seu vocabulário fazendo isso, mas não perca tanto tempo a ponto
de enlouquecer e ficar entediado.
Machine Translated by Google

294 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

Caminhos, pastas, diretórios (pwd)

Neste exercício você aprende como imprimir seu diretório de trabalho com o comando pwd .

55.3.1 Faça isto

Vou te ensinar a ler essas “sessões” que te mostro. Você não precisa digitar tudo que listo aqui, apenas algumas partes:

• Você não digita $ (Unix) ou > (Windows). Sou apenas eu mostrando minha sessão para que você possa
veja o que eu consegui.

• Você digita o que está depois de $ ou > e pressiona Enter. Então, se eu tiver $ pwd, você digita apenas pwd e clica
Digitar.

• Você pode então ver o que tenho como saída seguido por outro prompt $ ou > . Esse conteúdo é a saída e você deverá
ver a mesma saída.

Vamos fazer um primeiro comando simples para que você possa pegar o jeito:

Linux/macOS

Exercício 2 Sessão

$ pwd
/Usuários/zedshaw
$

janelas

Exercício 2 Sessão do Windows

PS C:\Usuários\zed> pwd

Caminho

----

C:\Usuários\zed

PS C:\Usuários\zed>
Machine Translated by Google

APÊNDICE A: CURSO DE ACIDENTE DE LINHA DE COMANDO 295

AVISO! Neste apêndice preciso economizar espaço para que você possa se concentrar nos detalhes
importantes dos comandos. Para fazer isso, vou retirar a primeira parte do prompt (o PS C:\Users\zed acima)
e deixar apenas a pequena parte > . Isso significa que seu prompt não será exatamente igual, mas não se
preocupe com isso.
Lembre-se que de agora em diante terei apenas o > para informar que esse é o prompt.
Estou fazendo a mesma coisa com os prompts do Unix, mas os prompts do Unix são tão variados que a maioria
das pessoas se acostuma com o significado de $ “apenas o prompt”.

55.3.2 Você aprendeu isso

Seu prompt será diferente do meu. Você pode ter seu nome de usuário antes do $ e do nome do seu computador. No Windows
provavelmente também será diferente. A chave é que você veja o padrão de:

• Há um aviso.

• Você digita um comando lá. Neste caso, é pwd.

• Imprimiu alguma coisa.

• Repita.

Você acabou de aprender o que o pwd faz, o que significa “imprimir diretório de trabalho”. O que é um diretório? É uma pasta.
Pasta e diretório são a mesma coisa e são usados de forma intercambiável. Ao abrir o navegador de arquivos no computador
para localizar arquivos graficamente, você está percorrendo pastas. Essas pastas são exatamente as mesmas coisas que esses
“diretórios” com os quais vamos trabalhar.

55.3.3 Faça mais

• Digite pwd 20 vezes e sempre diga “imprimir diretório de trabalho”.

• Anote o caminho que este comando fornece. Encontre-o com seu navegador de arquivos gráfico de
escolha.

• Não, sério, digite 20 vezes e diga em voz alta. Sssh. Apenas faça.

Se você se perder

Ao seguir essas instruções, você pode se perder. Você pode não saber onde está ou onde está um arquivo e não ter ideia de
como continuar. Para resolver esse problema vou te ensinar os comandos para digitar para não se perder.
Machine Translated by Google

296 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

Sempre que você se perde, é provavelmente porque estava digitando comandos e não tem ideia de onde foi parar. O que
você deve fazer é digitar pwd para imprimir seu diretório atual. Isso diz onde você está.

A próxima coisa é que você precisa encontrar uma maneira de voltar para onde está seguro, sua casa. Para fazer isso, digite
cd ~ e você estará de volta em sua casa.

Isso significa que se você se perder a qualquer momento digite:

cd
pwd ~

O primeiro comando pwd informa onde você está. O segundo comando cd ~ leva você para casa para que você possa tentar
novamente.

55.4.1 Faça isto

Agora descubra onde você está e depois vá para casa usando pwd e cd ~. Isso garantirá que você esteja sempre no lugar
certo.

55.4.2 Você aprendeu isso

Como voltar para sua casa se você se perder.

Crie um diretório (mkdir)


Neste exercício você aprende como criar um novo diretório (pasta) usando o comando mkdir .

55.5.1 Faça isto

Lembrar! Você precisa ir para casa primeiro! Faça seu pwd e depois cd ~ antes de fazer este exercício. Antes de fazer todos
os exercícios deste apêndice, sempre vá para casa primeiro!

Linux/macOS

Exercício 4 Sessão

$ pwd
$ cd ~
Machine Translated by Google

APÊNDICE A: CURSO DE ACIDENTE DE LINHA DE COMANDO 297

$ temperatura mkdir
$ mkdir temp/coisas
$ mkdir temp/coisas/coisas
$ mkdir -p temp/coisas/laranja/maçã/pêra/uva
$

janelas

Exercício 4 Sessão do Windows

> senha
> CD ~
> temperatura mkdir

Diretório: C:\Usuários\zed

Modo LastWriteTime Nome do comprimento


---- ------------- ------ ----

d---- 17/12/2011 9h02 temperatura

> mkdir temp/coisas

Diretório: C:\Usuários\zed\temp

Modo LastWriteTime Nome do comprimento


---- ------------- ------ ----

d---- 17/12/2011 9h02 coisa

> mkdir temp/coisas/coisas

Diretório: C:\Users\zed\temp\stuff

Modo LastWriteTime Nome do comprimento


---- ------------- ------ ----

d---- 17/12/2011 9h03 coisas


Machine Translated by Google

298 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

> mkdir temp/coisas/coisas/laranja/maçã/pêra/uva

Diretório: C:\Users\zed\temp\stuff\things\orange\apple\pear

Modo LastWriteTime Nome do comprimento


---- ------------- ------ ----

d---- 17/12/2011 9h03 uva

>

Esta é a única vez que listarei os comandos pwd e cd ~ . Eles são esperados nos exercícios sempre.
Faça-os o tempo todo.

55.5.2 Você aprendeu isso

Agora vamos digitar mais de um comando. Estas são todas as diferentes maneiras de executar o mkdir.
O que o mkdir faz? Ele cria diretórios. Porque esta perguntando isso? Você deveria estar fazendo suas fichas e memorizando seus
comandos. Se você não sabe que “mkdir cria diretórios”, continue trabalhando nas fichas.

O que significa criar um diretório? Você pode chamar os diretórios de “pastas”. Eles são a mesma coisa.
Tudo o que você fez acima foi criar diretórios dentro de diretórios dentro de mais diretórios. Isso é chamado de “caminho” e é uma
forma de dizer “primeiro tempo, depois coisas, depois coisas e é aí que eu quero”. É um conjunto de instruções para o computador
onde você deseja colocar algo na árvore de pastas (diretórios) que compõem o disco rígido do seu computador.

AVISO! Neste apêndice estou usando o caractere / (barra) para todos os caminhos, já que agora eles funcionam
da mesma forma em todos os computadores. No entanto, os usuários do Windows precisarão saber que você
também pode usar o caractere \ (barra invertida) e outros usuários do Windows normalmente esperam isso às
vezes.

55.5.3 Faça mais

• O conceito de “caminho” pode confundi-lo neste momento. Não se preocupe. Faremos muito mais com
eles, e então você vai conseguir.

• Crie outros 20 diretórios dentro do diretório temporário em vários níveis. Dê uma olhada neles com um navegador de arquivos
gráfico.
Machine Translated by Google

APÊNDICE A: CURSO DE ACIDENTE DE LINHA DE COMANDO 299

• Crie um diretório com um espaço no nome, colocando-o entre aspas: mkdir "I Have Fun"

• Se o diretório temporário já existir, você receberá um erro. Use cd para mudar para um diretório de trabalho
que você pode controlar e experimentar lá. Na área de trabalho do Windows é um bom lugar.

Alterar diretório (cd)


Neste exercício você aprende como mudar de um diretório para outro usando o comando cd .

55.6.1 Faça isto

Vou lhe dar as instruções para essas sessões mais uma vez:

• Você não digita $ (Unix) ou > (Windows).

• Você digita o texto depois disso e pressiona Enter. Se eu tiver $ cd temp, basta digitar cd temp e clicar
Digitar.

• A saída vem depois que você pressiona Enter, seguido por outro prompt $ ou > .

• Sempre vá para casa primeiro! Faça pwd e depois cd ~, para voltar ao ponto de partida.

Linux/macOS

Exercício 5 Sessão

$ cd temp
$ pwd
~/temp
$ cd coisas
$ pwd
~/temp/stuff $
cd coisas $
pwd ~/
temp/stuff/things $ cd
orange/ $ pwd
~/
temp/stuff/things/orange $ cd
apple/ $ pwd
~/
temp/stuff/things/orange/ maçã $ cd pêra/
Machine Translated by Google

300 APRENDA PYTHON 3 DA MANEIRA MAIS DIFÍCIL

$ pwd
~/temp/stuff/things/orange/apple/pear $ cd grape/ $
pwd ~/temp/
stuff/
things/orange/apple/pear/grape $ cd $ cd
..
..
$ pwd
~/temp/coisas/coisas/laranja/apple $ cd
..
$ cd ..
$ pwd
~/temp/coisas/coisas $
cd ../../..
$ pwd
~/
$ cd temp/stuff/things/orange/apple/pear/grape $ pwd ~/temp/
stuff/
things/orange/apple/pear/grape $ cd ../../../../../. ./../ $ pwd ~/

janelas

Exercício 5 Sessão do Windows

> temperatura do

cd > senha

Caminho

----

C:\Usuários\zed\temp

> coisas de CD
> senha

Caminho

----

C:\Usuários\zed\temp\coisas

Você também pode gostar