Este documento apresenta um exemplo de código Python para randomizar uma frase usando consoantes aleatórias. Ele define uma lista de consoantes e uma string com marcadores de posição, e usa funções para embaralhar as consoantes e substituí-las na string, gerando variações da frase.
4. Eu sou famoso (ou era) por entrar eu reuniões, fazer uma pergunta e a reunião explodir em discussões (úteis, diga-se
de passagem). Mas eu não fazia isso de propósito.
6. O PROBLEMAO PROBLEMA
"Hello world" não é muito didático
Escrever "Fujam para as colinas"
... com randomização de alguns elementos.
Ex: "Cujam para as folinas", "Lujam para as cofinas"
e "Nujam para as folicas"
7. SOLUÇÃOSOLUÇÃO
"""Randomize a "Run to the hills" phrase."""
from __future__ import print_function
import random
from argparse import ArgumentParser
CONSONANTS = ['f', 'j', 'c', 'l', 'n']
PASSPHRASE = '{}u{}am para as {}o{}i{}as'
def print_phrase(consonants):
"""Print the phrase with the randomized consonants."""
print(PASSPHRASE.format(*consonants).capitalize())
8. DOCSTRINGSDOCSTRINGS
"""Randomize a "Run to the hills" phrase."""
Docstrings são utilizadas para documentar coisas em Python: módulos, funções, classes. Essas docstrings depois são
utilizadas para o `help` e para extração de documentação, com aplicativos tipo o Sphinx. Outra coisa: Strings.
Docstrings são strings normais, só que ficam logo abaixo do módulo/classe/função. E como strings normais, elas podem
ser geradas com aspas simples ou duplas; as três aspas significam que a string pode ter quebra de linhas.
9. MÓDULOS E IMPORTSMÓDULOS E IMPORTS
import random
from argparse import ArgumentParser
Para importar módulos no Python, se usa `import` ou `from X import Y`.
10. MÓDULOS E IMPORTSMÓDULOS E IMPORTS
Imagine dois módulos: `mod1` e `mod2`. `mod1` tem uma função `func1` e `mod2` tem uma funcão `func2`. Como
ambos estão em espaços separados, de `mod1` eu não consigo chamar `func2` (e nem o contrário).
11. MÓDULOS E IMPORTSMÓDULOS E IMPORTS
Se eu fizer `import mod2`, tudo que tiver dentro de `mod2` vai vir para o "namespace" atual (assim como quando tu cria
um objeto a partir de uma classe ele vira uma "instância", ao importar um módulo, ele vira um namespace). Agora,
usando o nome do módulo/namespace, eu consigo chamar `func2`, por exemplo. Como fazer a chamada usando o
namespace é visto a seguir.
12. MÓDULOS E IMPORTSMÓDULOS E IMPORTS
Se eu fizer `from mod2 import func2`, a única coisa que eu vou trazer para o namespace atual é `func2`; se houvessem
outras funções ou outros módulos ou classes, essas não estariam disponíveis para uso.
13. VARIÁVEIS E TIPOSVARIÁVEIS E TIPOS
CONSONANTS = ['f', 'j', 'c', 'l', 'n']
PASSPHRASE = '{}u{}am para as {}o{}i{}as'
Primeiro, como vimos, strings são marcadas com aspas simples ou duplas. Segundo, temos uma lista: `[]` indicam listas
e, nesse caso, nos temos uma lista de strings (não existe o conceito de "um caractere" como em C, por exemplo --
simplesmente, strings com um caractere só). Terceiro: Existe uma string com uns colchetes no meio. Por si só, esses
colchetes não fazem nada e se alguém tentar imprimir essa string, os colchetes ainda vão estar lá. Quarto: como pode
ser visto, o nome dessas variávels está em maiúsculo. Isso é apenas por notação para indicar constantes, embora o
Python não tenha esse conceito de constantes; isso é apenas convenção (e, mais pra frente, nós vamos estragar essa
convenção.)
14. FUNÇÕESFUNÇÕES
def print_phrase(consonants):
"""Print the phrase with the randomized consonants."""
Nossa primeira função, sem nada de especial: Primeiro, elas começam com `def`. Segundo, elas tem nomes e, por
padrão, tem que ser em minúsculas e separadas por underscore; não existe nada na linguagem barrando criar funções
com nomes todos em maiúsculas ou com camelCase, mas, de novo, é a convenção da comunidade. Terceiro, funções
tem parâmetros, que seguem a mesma convenção de nomes que já vimos. Quarto, funcões são seguidas de dois
pontos. Quinto: Python não usa colchetes para blocos; blocos são definidos por identação (como pode ser visto pela
docstring).
16. FUNCÕESFUNCÕES
def soma(primeiro, segundo):
total = primeiro + segundo
return total
Se uma função tem algum retorno, basta adicionar `return`; funções sem `return` retornam um valor vazio, chamado
`None` (que é o mesmo que `nil`, `null` e tantos outros nomes). Não existe diferença na hora de criar uma "função" e
uma "procedure", como existe no Pascal: Simplesmente funções que não retornam valor não retornam valor (e ficam
como None).
19. FUNÇÕESFUNÇÕES
soma(segundo=3, primeiro=2)
... e por isso dá pra misturar a ordem dos parâmetros, se ficar mais fácil de ler. Também ajuda se a função tiver vários
parâmetros, sem contar que ajuda quem tiver lendo o código pra não precisar voltar e ver quais são os parâmetros.
21. PAUSA: VARARGSPAUSA: VARARGS
def soma(primeiro, segundo):
total = primeiro + segundo
return total
soma(1)
soma(1, 2, 3)
O que acontece quando não se passa a quantidade correta de parâmetros para uma função?
22. PAUSA: VARARGSPAUSA: VARARGS
TypeError: soma() takes exactly 2 arguments (3 given)
Simplesmente, o Python se recusa a executar porque não foi passado o número correto de parâmetros.
23. PAUSA: VARARGSPAUSA: VARARGS
def soma(*valores):
Entram os varargs: Quando um parâmetro tem um asterísco na frente do nome, ele significa "colete tudo que foi
passado que não conseguiu associar a um parâmetro e retorne como lista"
27. PAUSA: VARARGSPAUSA: VARARGS
def soma(**valores):
print(valores)
soma(primeiro=1, segundo=2)
{'primeiro': 1, 'segundo': 2}
Para capturar parâmetros com nomes, usam-se dois asteríscos na frente do nome. Assim como um asterísco significa
"capture tudo que não for capturado por parâmetros normais", dois asteríscos significam "capture tudo que tiver nome e
não for capturado por parâmetros normais". E agora também vimos como funcionam dicionários em Python (que são
chamadas de "objetos", "arrays associativos", "mapas" e outros nomes em outras linguagens).
28. PAUSA: VARARGSPAUSA: VARARGS
O legal de varargs (e o asterísco) é que ele funciona
pros dois lados: Não só ele transforma parâmetros em
lista, mas ele também pode funcionar para converter
uma lista em parâmetros.
30. PAUSA: OBJETOSPAUSA: OBJETOS
Sem entrar em detalhes sobre como criar objetos:
Objetos tem métodos (funções associadas a um
objeto)
Para chamar um método, usa-se '.' e o nome do
método
Strings são objetos
32. PAUSA: OBJETOSPAUSA: OBJETOS
help("isso é uma string")
Pedindo help num objeto vai mostrar o help da classe do objeto; no caso, serão mostrados todos os métodos presentes
no objeto "str", de string. E é por isso que é interessante colocar docstrings: help() vai mostrar tudo que aquele objeto
faz, desde que documentado.
34. WELCOME TO HELLWELCOME TO HELL
print(PASSPHRASE.format(*consonants).capitalize())
Holy cow!
35. WELCOME TOWELCOME TO HELLHELL
O que sabemos:
PASSPHRASE é uma string.
.format deve ser um método de strings.
consonants é uma lista
*consonants tá transformando a lista em
parâmetros
capitalize também deve ser um método de
strings
36. WELCOMEWELCOME TO HELLTO HELL
Lembram que PASSPHRASE tinha um monte de
colchetes no meio?
.format() converte cada um deles para um dos
parâmetros passados.
37. WELCOMEWELCOME TO HELLTO HELL
'Bem vindo {}!'.format('Júlio')
Bem vindo Júlio!
Format funciona da seguinte format: Tudo que tiver `{}` no meio, ele troca pelo que vier de parâmetro.
38. WELCOME TO HELLWELCOME TO HELL
PASSPHRASE = '{}u{}am para as {}o{}i{}as'
PASSPHRASE.format('f', 'j', 'c', 'l', 'n')
'fujam para as colinas'
... se eu passar cada uma das consoantes no format com a nossa string original, ele vai trocar cada um dos `{}` pelas
consoantes passadas como parâmetros, uma a uma.
39. WELCOME TO... HELLWELCOME TO... HELL
CONSONANTS = ['f', 'j', 'c', 'l', 'n']
PASSPHRASE = '{}u{}am para as {}o{}i{}as'
PASSPHRASE.format(*CONSONANTS)
'fujam para as colinas'
... e como a gente viu que dá pra converter listas para parâmetros, usando o `*` a gente passa a lista, que é convertida
para chamada de parâmetros exatamente como anteriormente e ainda temos o mesmo resultado.
40. WELCOME TO... HELL?WELCOME TO... HELL?
'fujam para as colinas'.capitalize()
Fujam para as colinas
E `capitalize()` simplesmente converte o primeiro caractere para maiúscula.
41. RANDOMIZAÇÕESRANDOMIZAÇÕES
def totally_random():
"""Run a totally random way."""
random.shuffle(CONSONANTS)
print_phrase(CONSONANTS)
Nada complicado: A gente chama o `random.shuffle`, que é um método do módulo `random` que a gente fez import lá
no começo. O único problema aqui é que `shuffle` faz *in-place*, ou seja, a lista vai ter o conteúdo alterado.
42. RANDOMIZAÇÕESRANDOMIZAÇÕES
def switch_two():
"""Run by changing two steps at a time."""
first = random.randint(0, 1)
second = random.randint(2, 4)
Essa função simplesmente escolhe dois números randomicamente. O primeiro vai de 0 a 1. E o segundo de 2 a 4. ...
que, se a gente contar, são exatamente as posições das consoantes de "fujam" e de "colinas", respecticamente,
começando por 0.
43. WELCOME TO HELL, MAYBE?WELCOME TO HELL, MAYBE?
CONSONANTS[second], CONSONANTS[first] =
CONSONANTS[first], CONSONANTS[second]
44. WELCOME TO LISTAS!WELCOME TO LISTAS!
# CONSONANTS = ['f', 'j', 'c', 'l', 'n']
# second = random.randint(2, 4)
CONSONANTS[second]
Para acessar um elemento específico de uma lista é só usar colchetes e um índice; ou seja, iremos pegar a consoante
indicada pelo número randômico seleciado (entre 2 e 4, inclusive).
45. WELCOME TO TUPLES!WELCOME TO TUPLES!
Tuplas são como listas, só que não podem ser
alteradas.
E pra criar uma tupla:
Ou mais bonitinho: (valor, valor)
valor, valor
46. WELCOME TO DESTRUCTURINGWELCOME TO DESTRUCTURING
primeiro, segundo = [1, 2]
print(primeiro)
print(segundo)
1
2
Destructuring (e não destroying) serve para "desmontar" tuplas e listas. Por exemplo, a lista tem dois elementos; se eu
apontar os dois valores para ela, o primeiro vai ter o primeiro valor e o segundo, o segundo; se forem três, eu preciso de
três variáveis. E se o número de váriaveis estiver errado, dá erro.
47. TUDO JUNTO, AGORA!TUDO JUNTO, AGORA!
CONSONANTS[second], CONSONANTS[first] =
CONSONANTS[first], CONSONANTS[second]
tmp = CONSONANTS[first]
CONSONANTS[first] = CONSONANTS[second]
CONSONANTS[second] = tmp
Ou seja, estamos pegando a consonante escolhida randomicamente entre 0 e 1 (f e j) e a consoante escolhida
randomicante entre 2 e 4 (c, l, n) e criando uma tupla com esses dois valores; a seguir a gente desmonta (destructura)
esses dois na ordem inversa.
48. O PAI DE TODOS MÓDULOSO PAI DE TODOS MÓDULOS
if __name__ == "__main__":
Falamos antes que um módulo, quando importado, vira um namespace. Pois bem, namespaces tem nomes que podem
ser acessados com `__name__`. E o que acontece quando um script é executado diretamente pela linha de comando?
O módulo é "importado" pelo interpretador, mas qual é o nome do namespace? `__main__`. Essa construção permite
que scripts sejam tanto executados diretamente quando importados. No caso, todo o conteúdo desse if só vai ser
executado se for executado pela linha de comando. Se for importado por um outro script, o script vai ter acesso às
funções, mas não vai ser afetado pela leitura da linha de comando.
49. A LINHA DE COMANDOA LINHA DE COMANDO
args = ArgumentParser()
args.add_argument('-t', '--totally',
dest='totally',
default=False,
action='store_true',
help='Like, toootaly random')
args.add_argument('-s', '--short',
dest='short',
default=False,
action='store_true',
help='Not so random')
result = args.parse_args()
Nada de muito mágico aqui, exceto que o ArgumentParser faz um monte de coisas pra nós: nós só definimos os
parametros, onde eles vão ficar no final, qual ação a ser tomada e um help. E o ArgumentParser faz todo o resto.
50. E OS FINALMENTES...E OS FINALMENTES...
if result.totally:
totally_random()
elif result.short:
switch_two()
else:
print('Dude, option!')
E a gente simplesmente acessa as propriedades do objeto de resultado do `parse_args` e, se for verdadeiro (True),
executamos uma função ou a outra.