Unidade 7 · a prateleira
A prateleira
Na prateleira tem o que outra pessoa (ou você, noutro arquivo) já escreveu. import, random, statistics, sys.argv, fatias, pip, JSON — e o módulo da casa.
input a cada vez. Pacote de fora se instala com pip.
Não copie o mesmo arquivo de novo
Biblioteca é código que outra pessoa (ou você, noutro dia) já escreveu. Módulo, nesta linguagem, é isso em um arquivo: uma ou mais funções (e outros recursos) com nome. O ponto é reúso. Copiar-colar o mesmo bloco em três projetos vira três cópias para consertar. Fatore: um arquivo, vários programas carregam.
print e input já estão na memória. Outras funções ficam num arquivo no disco — depois que o interpretador foi instalado, existe um random.py em algum lugar. Para usar, você importa de propósito.
A documentação oficial descreve cada módulo: o que existe, o que cada função espera. Não invente a matemática do sorteio se alguém já resolveu.
Cara ou coroa
Arquivo sorteio.py. Primeira linha (ou quase): import random. Isso libera as funções daquele módulo. A docs descreve random.choice(seq): seq é sequência — lista, ou coisa de lista. Devolve um item, probabilidade igual para cada um. Dois itens = 50/50; três = cerca de um terço cada.
import random
moeda = random.choice(["cara", "coroa"])
print(moeda)
Lista: colchetes, vírgulas, strings entre aspas. Os parênteses de fora são da função. O ponto: random.choice — de qual módulo vem esta choice.
Rode três vezes. Cara, cara, coroa não é bug: é pouca amostra. No infinito, aproxima 50/50.
Uma linha que importe um módulo (ou um nome com from).
import randomO nome sozinho, ou com o módulo
import random traz o módulo inteiro. Aí você escreve random.choice sempre. Alternativa: from random import choice — o nome choice entra no vocabulário deste arquivo. Dá para chamar choice(["cara", "coroa"]) sem o prefixo.
Quando o prefixo ajuda: você já tem uma variável ou função chamada choice. O módulo guarda os nomes no próprio escopo; não colidem. Quando o prefixo cansa: a mesma chamada dezenas de vezes. Não há um único certo. Programa curto, os dois valem; em projeto maior, o prefixo deixa claro de onde veio.
Inteiro entre A e B, inclusive
random.randint(1, 10) devolve um inteiro de 1 a 10 incluindo os dois — cerca de 10% cada. Dado, senha da fila, personagem de jogo que não é previsível.
import random
n = random.randint(1, 10)
print(n)
Embaralhar no lugar
random.shuffle(lista) mexe na lista que você passou — como baralho. Não devolve um baralho novo: devolve None. Por isso cartas = random.shuffle(cartas) esvazia a gaveta.
import random
cartas = ["valete", "dama", "rei"]
random.shuffle(cartas)
for c in cartas:
print(c)
Três cartas, poucas ordens: repetir a mesma sequência umas vezes é chance, não prova de que está quebrado. choice devolve um item e deixa a lista intacta. shuffle altera.
Por que não fazer cartas = random.shuffle(cartas)?
Média sem reinventar
Outro arquivo da instalação: statistics. mean é média. Conta da mesa, duas notas — você não precisa somar e dividir na mão se o módulo já faz.
import statistics
precos = [8.5, 5.0]
print(statistics.mean(precos))
Há mediana, moda, e o resto na docs. Mesma ideia: import, depois modulo.funcao.
Argumentos no comando
Até agora o dado entra com input, depois que o programa já rodou. Dá para passar na hora do comando: python cracha.py Ana. Isso é argumento de linha de comando — não só desta linguagem.
Módulo sys (sistema). Variável sys.argv: argument vector, lista das palavras digitadas no prompt. Índice 0 é o nome do arquivo. 1 em diante são o que veio depois. Tudo string.
import sys
print("Crachá:", sys.argv[1])
python cracha.py Ana imprime o nome. sys.argv[0] é cracha.py — pouco interessante, mas é o contrato. O interpretador python em si não entra nessa lista.
Em python cracha.py Ana, o nome Ana está em que índice de sys.argv?
Quando [1] não existe
python cracha.py sem nome: a lista tem um item só. Pedir [1] levanta IndexError — list index out of range. Erro clássico de lista em qualquer linguagem: foi longe demais para a direita (ou para a esquerda).
Trocar para [0] imprime o nome do arquivo no crachá. Não é o que você quer. Unidade 6: try / except IndexError e um recado “faltou o nome”. Ou, mais fino, conferir o tamanho antes e dizer se foi pouco ou demais.
import sys
if len(sys.argv) < 2:
print("faltou o nome")
elif len(sys.argv) > 2:
print("nome demais")
else:
print("Crachá:", sys.argv[1])
Dois argumentos no total: arquivo + um nome. Nome composto no comando: aspas em volta — python cracha.py "Ana Silva" — senão cada palavra vira um índice. else só um; vários elif no meio.
Aspas esquecida no print continua sendo SyntaxError: o programa nem arranca. Condicional não pega isso. Fecha a aspas e rode de novo (unidade 6).
python cracha.py sem nome, e o código faz print(sys.argv[1]). O que acontece?
Checar erro em cima, trabalho embaixo
O crachá no else funciona, mas esconde o que o programa é. Melhor: tratar o caso ruim no topo e, se não dá para seguir, sair. sys.exit("faltou o nome") imprime o recado e encerra. Aí a linha do print do crachá fica alinhada à esquerda, depois de todos os testes — você já pode confiar que [1] existe.
import sys
if len(sys.argv) < 2:
sys.exit("faltou o nome")
if len(sys.argv) > 2:
sys.exit("nome demais")
print("Crachá:", sys.argv[1])
Sem o exit, o print de baixo roda mesmo depois de “faltou o nome” e cai no IndexError. O arquivo já ia acabar sozinho no fim; exit é para sair antes. break sai de loop, não do programa (unidade 3).
Quem importa este arquivo como biblioteca não quer que o programa inteiro morra no meio: aí é raise (unidade 6), não sys.exit.
Um trecho que leia sys.argv ou chame sys.exit.
import syssys.exit("faltou o nome")Vários nomes, sem o nome do arquivo
Vários crachás: python cracha.py Ana Bia Leo. Não há “nome demais”. Percorra a lista. Bug: for arg in sys.argv inclui o .py — um crachá a mais, para o programa.
Fatia: pedaço da lista. sys.argv[1:] começa no 1 e vai até o fim (o segundo número omitido). O : aqui não é o da f-string :.2f — mesmo símbolo, outro contexto, poucas teclas no teclado.
import sys
if len(sys.argv) < 2:
sys.exit("faltou o nome")
for nome in sys.argv[1:]:
print("Crachá:", nome)
Número negativo conta do fim: [1:-1] larga o último. "Bia"[1:] é ia — a mesma ideia em string.
O que "Bia"[1:] devolve? (sem aspas)
O que não veio na caixa
Pacote, na prática: biblioteca de terceiros. Às vezes é um módulo numa pasta, não só um arquivo. O índice público se chama PyPI. Instalador: pip, que costuma vir com o Python. pip install nome baixa e deixa o import funcionar.
random e sys já estavam lá. Pedido HTTP, gráfico, planilha — outra história. Leia o nome do pacote: um quase igual pode ser outra coisa. ModuleNotFoundError: não instalou neste interpretador, ou o nome do import não é o do pip.
Argumento no comando é menos amigável para quem não programa. Para quem programa, é mais rápido: uma linha só, histórico da seta para cima, automação. Por isso python arquivo.py em vez de o interpretador perguntar o nome do arquivo toda vez.
Quando você precisa do pip install?
Dados de outro computador
API (interface de programação) não é só desta linguagem: serviço — muitas vezes na internet — que o seu código consulta como se fosse um navegador. Pacote comum para isso: requests (pip install requests). requests.get(url) devolve a resposta.
O texto que chega costuma ser JSON: chaves e valores, chaves { }, listas [ ], aspas. Parece dicionário desta linguagem de propósito. As chaves o servidor escolhe; você não as renomeia na origem — só guarda o valor numa variável sua.
# o servidor mandou algo neste formato:
o = {
"quantidade": 1,
"itens": [
{"nome": "café", "preco": 8.5}
],
}
for item in o["itens"]:
print(item["nome"])
No programa de verdade: resposta = requests.get(url), depois o = resposta.json(), o mesmo for. Módulo json da biblioteca padrão formata o blob para leitura (json.dumps(..., indent=2)) enquanto você descobre as chaves. Sem rede, o dicionário acima já treina o acesso.
O arquivo que os outros importam
Você também fatura função repetida. recados.py:
def ola(nome):
print(f"olá, {nome}")
def tchau(nome):
print(f"tchau, {nome}")
def main():
ola("fila")
tchau("fila")
if __name__ == "__main__":
main()
Noutro arquivo, na mesma pasta: from recados import ola. O Python lê recados.py de cima a baixo. Se o main() estiver solto no fim, o teste “olá, fila” roda no import — misturado com o programa que só queria ola.
__name__ vale "__main__" quando você roda python recados.py. Quando outro arquivo importa, o nome é o do módulo, não __main__, e o if não chama main. Por isso o disparo condicional da unidade 4: não é enfeite.
Por que o main de teste em recados.py precisa do if __name__ == "__main__"?
Oficina · sorteio
random e imprima. Arquivo: sorteio.py. Opcional: ler o nome no comando com sys.argv em vez de input.
Cole um programa com random e print.
import random
print(random.choice(["Ana", "Bia", "Leo"]))