Guia de estudo

Aula 17 · Qua, 17/06

Manipulação de Arquivos

Fazendo o programa lembrar das coisas.

Até agora, tudo o que criamos morria quando o programa fechava. Hoje aprendemos a gravar e ler dados no disco — e a dar às nossas classes o poder de salvar e carregar seus objetos.

open() e with ler / escrever (r · w · a) encoding utf-8 salvar objetos · JSON

roteiro da aula

O que vamos aprender hoje

01

O problema

Nossos objetos somem quando o programa fecha. Precisamos de uma memória que sobreviva.

02

Abrir e fechar

open(), os modos r/w/a, e o with — o jeito seguro de mexer em arquivos.

03

Ler e escrever

read() e write(), encoding utf-8 pros acentos, e o tratamento de arquivo que não existe.

04

Salvar objetos

Dar à classe um salvar() e um carregar() — e serializar em JSON.

ponte com a aula passada

De onde paramos — exceções (aula 14)

  • 🧹 O bloco finally rodava SEMPRE — era ele que garantia liberar recursos no fim, com erro ou sem erro.
  • 🗂️ O FileNotFoundError já apareceu lá, na tabela de erros nativos do Python.
  • 🌉 Hoje o finally vira o with (que fecha o arquivo sozinho), e os erros de arquivo viram try/except.

o problema

A memória do programa é volátil

Tudo o que criamos até agora vive só na memória RAM. Fechou o programa, perdeu.

volatil.py
class Pedido:
    def __init__(self, cliente, sabor, valor):
        self.cliente = cliente
        self.sabor = sabor
        self.valor = valor

pedido = Pedido("Ana", "Calabresa", 39.90)
print(pedido.cliente, pedido.sabor, pedido.valor)   # Ana Calabresa 39.9

# Fim do programa... e o objeto some.
# Amanhã, ao rodar de novo, o pedido da Ana não existe mais.
# Ele viveu só na memória RAM — nada foi gravado em lugar nenhum.
Numa pizzaria de verdade, o caixa não pode esquecer os pedidos toda vez que o computador desliga. Precisamos gravar no disco.

a ideia

A solução: gravar em arquivo

  • 🗄️ Arquivo = memória que sobrevive ao programa. Fica salvo no disco, não na RAM.
  • 💾 Gravar (escrever) = guardar os dados. Ler = recuperar os dados de volta.
  • 🔑 Todo arquivo segue o mesmo ritual: abrir → usar → fechar.

abrir e fechar

open() — abrir é o primeiro passo

open() recebe o caminho, o modo e o encoding, e devolve um objeto de arquivo pra você usar.

abrir.py
# open(caminho, modo, encoding) — abre o arquivo e devolve um objeto de arquivo
arquivo = open("pedidos.txt", "w", encoding="utf-8")
arquivo.write("Pedido da Ana: Calabresa - R$ 39,90")
arquivo.close()          # fechar é OBRIGATÓRIO pra garantir que gravou

# O ritual de todo arquivo: abrir -> usar -> fechar.
# Esquecer o close() pode deixar o conteúdo "preso" sem ser gravado no disco.
Esse open/close manual funciona, mas depende de você nunca esquecer o close(). Daqui a pouco a gente troca isso pelo with, que fecha sozinho. Comece entendendo o ritual completo.

abrir e fechar

Os modos do open()

item detalhe
"r" (read) Lê o arquivo. É o padrão. Levanta FileNotFoundError se o arquivo não existir.
"w" (write) Escreve do zero. CUIDADO: apaga todo o conteúdo que já existia no arquivo!
"a" (append) Anexa no final, preservando o que já estava lá. Cria o arquivo se não existir.
"x" (exclusive) Cria um arquivo novo. Levanta erro se o arquivo já existir.
"+" Combinado com os outros (ex.: "r+"), permite ler e escrever no mesmo arquivo.
"b" (binary) Modo binário (ex.: "rb", "wb"), pra imagens e PDFs. Hoje ficamos só no texto.

a pegadinha nº 1

"w" apaga · "a" anexa

O erro mais destrutivo de quem está começando: abrir em "w" achando que vai acrescentar — e apagar tudo.

"w" — reescreve do zero

modo_w.py
# "w" apaga o que já estava no arquivo
with open("pedidos.txt", "w", encoding="utf-8") as f:
    f.write("Ana: Calabresa\n")
with open("pedidos.txt", "w", encoding="utf-8") as f:
    f.write("Bruno: Mussarela\n")

# conteúdo final do arquivo: APENAS
# Bruno: Mussarela
# o pedido da Ana foi apagado pelo segundo "w".

"a" — anexa no final

modo_a.py
# "a" preserva o que já estava e acrescenta no fim
with open("pedidos.txt", "a", encoding="utf-8") as f:
    f.write("Ana: Calabresa\n")
with open("pedidos.txt", "a", encoding="utf-8") as f:
    f.write("Bruno: Mussarela\n")

# conteúdo final do arquivo: as DUAS linhas
# Ana: Calabresa
# Bruno: Mussarela

ler e escrever

write() — escrevendo no arquivo

write() grava exatamente o que você passar — nem uma quebra de linha a mais.

escrever.py
with open("pedidos.txt", "w", encoding="utf-8") as f:
    f.write("Ana: Calabresa")      # write NÃO adiciona quebra de linha
    f.write("Bruno: Mussarela")    # gruda na linha anterior!

# conteúdo gravado:  Ana: CalabresaBruno: Mussarela   <- tudo numa linha só

# A correção: você mesmo coloca o \n no fim de cada linha
with open("pedidos.txt", "w", encoding="utf-8") as f:
    f.write("Ana: Calabresa\n")
    f.write("Bruno: Mussarela\n")

# writelines grava uma lista de strings (também SEM \n automático)
linhas = ["Carla: Portuguesa\n", "Diego: Quatro Queijos\n"]
with open("pedidos.txt", "a", encoding="utf-8") as f:
    f.writelines(linhas)
Diferente do print(), o write() não pula linha sozinho. Quebra de linha é responsabilidade sua: \n.

ler e escrever

As formas de ler um arquivo

Quatro jeitos de ler. O último — iterar linha a linha — é o mais pythônico.

ler.py
# read() — o arquivo inteiro como uma única string
with open("pedidos.txt", "r", encoding="utf-8") as f:
    conteudo = f.read()
print(conteudo)
# Ana: Calabresa
# Bruno: Mussarela

# readline() — só a primeira linha (vem com o \n no fim)
with open("pedidos.txt", "r", encoding="utf-8") as f:
    print(repr(f.readline()))    # 'Ana: Calabresa\n'

# readlines() — uma lista com todas as linhas
with open("pedidos.txt", "r", encoding="utf-8") as f:
    print(f.readlines())         # ['Ana: Calabresa\n', 'Bruno: Mussarela\n']

# o jeito pythônico — iterar linha a linha (.strip() tira o \n)
with open("pedidos.txt", "r", encoding="utf-8") as f:
    for linha in f:
        print(linha.strip())     # Ana: Calabresa  /  Bruno: Mussarela
Iterar o arquivo (for linha in f) lê uma linha de cada vez sem carregar tudo na memória — ideal pra arquivos grandes.

ler e escrever

encoding="utf-8" — acentos não são opcionais

Em português, sem encoding="utf-8" os acentos e o ç viram lixo — ou estouram um erro.

encoding.py
# Sem encoding, máquinas com configuração diferente podem gravar/ler errado.
# Com utf-8, acentos e ç são garantidos em qualquer computador.
with open("pedidos.txt", "w", encoding="utf-8") as f:
    f.write("João pediu Calabresa\n")
    f.write("Pizza de Coração de galinha\n")

with open("pedidos.txt", "r", encoding="utf-8") as f:
    print(f.read())
# João pediu Calabresa
# Pizza de Coração de galinha

# Abrir sem o encoding certo pode estourar:
# UnicodeDecodeError: 'charmap' codec can't decode byte ...
Regra de bolso pra este curso: TODO open() leva encoding="utf-8". Nosso conteúdo é em português — acento é regra, não exceção.

o with

Fechar na mão é frágil

Lembra do finally da aula 14? Dá pra garantir o close() com ele — mas é trabalhoso.

fechar_manual.py
# O padrão da aula 14: garantir o close() no finally
f = open("pedidos.txt", "w", encoding="utf-8")
try:
    f.write("Ana: Calabresa\n")
finally:
    f.close()          # roda SEMPRE — mesmo se der erro no write

# Funciona, mas é verboso: você precisa lembrar do try, do finally e do close.
# E se esquecer o close()? O arquivo pode ficar aberto e o dado não gravar.
📍 try / finally foi a aula 14. O finally rodava sempre, justamente pra liberar recursos. Guarde essa ideia — o próximo slide a automatiza.

o with

with — o finally automático

O with abre o arquivo, te entrega no as f, e fecha sozinho ao sair do bloco.

com_with.py
# with cuida do close() sozinho — é o finally automático
with open("pedidos.txt", "w", encoding="utf-8") as f:
    f.write("Ana: Calabresa\n")
# ao sair do bloco, o arquivo já está fechado. Mesmo se houvesse um erro.

# O que o finally fazia na unha (aula 14), o with faz de graça.
O with é a forma recomendada de mexer em arquivos. A partir daqui, todos os exemplos usam with.

o with

Sem with vs com with

Mesmo resultado. À esquerda, você precisa lembrar de tudo. À direita, o with garante o fechamento.

Sem with — manual

sem_with.py
f = open("pedidos.txt", "w", encoding="utf-8")
try:
    f.write("Ana: Calabresa\n")
finally:
    f.close()
# 5 linhas, e fácil de esquecer o close().

Com with — automático

com_with.py
with open("pedidos.txt", "w", encoding="utf-8") as f:
    f.write("Ana: Calabresa\n")
# 2 linhas. O arquivo fecha sozinho,
# sem risco de esquecer.

tratando erros

Arquivo que não existe → FileNotFoundError

Ler um arquivo que não existe levanta FileNotFoundError. Esse é o caso de uso natural do try/except (aula 14).

arquivo_faltando.py
# Ler um arquivo que não existe levanta FileNotFoundError (aula 14!)
try:
    with open("caixa_de_ontem.txt", "r", encoding="utf-8") as f:
        print(f.read())
except FileNotFoundError:
    print("Arquivo não encontrado — começando um caixa novo.")
# Arquivo não encontrado — começando um caixa novo.

# Outro erro comum: PermissionError (sem permissão pra abrir/gravar o arquivo).
📍 Aqui a exceção faz sentido de verdade: o arquivo PODE não existir (1ª vez que o programa roda). Diferente de usar exceção pra fluxo normal, que a aula 14 alertou ser anti-padrão.

tratando erros

pathlib — lidando com caminhos

"O arquivo foi salvo ONDE?" — caminho relativo parte de onde o programa roda; absoluto é o endereço completo.

caminhos.py
from pathlib import Path

caminho = Path("dados") / "pedidos.txt"   # monta o caminho sem se preocupar com / ou \
print(caminho)             # dados/pedidos.txt
print(caminho.exists())    # False  <- dá pra checar ANTES de tentar abrir

# Caminho relativo: parte da pasta onde o programa roda (ex.: dados/pedidos.txt).
# Caminho absoluto: o endereço completo no disco (ex.: /Users/leo/pizzaria/dados/pedidos.txt).
# Path("pedidos.txt").absolute() devolve esse caminho absoluto.
Erro clássico: "rodei e não achei o arquivo". Quase sempre é caminho relativo — o arquivo foi salvo na pasta onde você executou o programa, não onde está o .py.

a ponte com POO

E os nossos objetos?

  • 💾 Até agora o arquivo guardou texto solto. Mas o curso inteiro é sobre objetos.
  • 🎯 O que queremos é salvar o ESTADO de um objeto: os atributos de um Pedido, de uma Conta, de um Personagem.
  • 🧬 A classe ganha dois superpoderes: salvar() grava os próprios dados, e carregar() reconstrói o objeto a partir do arquivo.

salvar objetos

Um objeto que sabe se salvar

Damos à classe Pedido um método salvar(): ele grava os próprios atributos como uma linha de texto.

pedido_salvar.py
class Pedido:
    def __init__(self, cliente, sabor, valor):
        self.cliente = cliente
        self.sabor = sabor
        self.valor = valor

    def salvar(self, caminho="pedidos.txt"):
        # grava o estado do objeto como uma linha de texto (anexando)
        with open(caminho, "a", encoding="utf-8") as f:
            f.write(f"{self.cliente};{self.sabor};{self.valor}\n")

pedido = Pedido("Ana", "Calabresa", 39.90)
pedido.salvar()
# o arquivo pedidos.txt agora tem a linha:  Ana;Calabresa;39.9
Usamos ";" pra separar os campos numa linha só. É um formato simples; daqui a pouco o JSON faz isso de forma mais robusta.

salvar objetos

@classmethod carregar() — reconstruindo o objeto

carregar() lê a linha e devolve um Pedido novo — é o factory method (@classmethod) da aula 03.

pedido_carregar.py
class Pedido:
    def __init__(self, cliente, sabor, valor):
        self.cliente = cliente
        self.sabor = sabor
        self.valor = valor

    @classmethod
    def carregar(cls, caminho="pedidos.txt"):
        # lê a primeira linha e reconstrói um Pedido (factory method, aula 03)
        with open(caminho, "r", encoding="utf-8") as f:
            linha = f.readline().strip()
        cliente, sabor, valor = linha.split(";")
        return cls(cliente, sabor, float(valor))

pedido = Pedido.carregar()
print(pedido.cliente, pedido.sabor, pedido.valor)   # Ana Calabresa 39.9
# o objeto voltou à vida — direto do arquivo.
Repare: o que está no arquivo é TEXTO. O valor vem como "39.9" (string) e precisa virar float(valor). Reconstruir o objeto é passar os dados pelo construtor.

salvar objetos

JSON — o formato que entende objetos

JSON guarda dicionários e listas. Convertemos o objeto num dict (to_dict) pra gravar, e remontamos (from_dict) pra ler.

pedido_json.py
import json

class Pedido:
    def __init__(self, cliente, sabor, valor):
        self.cliente = cliente
        self.sabor = sabor
        self.valor = valor

    def to_dict(self):
        return {"cliente": self.cliente, "sabor": self.sabor, "valor": self.valor}

    @classmethod
    def from_dict(cls, dados):
        return cls(dados["cliente"], dados["sabor"], dados["valor"])

# salvar em JSON
pedido = Pedido("João", "Coração de Frango", 39.90)
with open("pedido.json", "w", encoding="utf-8") as f:
    json.dump(pedido.to_dict(), f, ensure_ascii=False, indent=2)

# ler de volta
with open("pedido.json", "r", encoding="utf-8") as f:
    dados = json.load(f)
pedido = Pedido.from_dict(dados)
print(pedido.cliente, pedido.sabor, pedido.valor)   # João Coração de Frango 39.9
ensure_ascii=False mantém os acentos legíveis no arquivo (José, não Jos\u00e9). indent=2 deixa o JSON formatado. json.dump grava em arquivo; json.load lê de arquivo.

ao vivo · vamos construir juntos

Exercício ao Vivo: Caixa da Pizzaria

Vou construir esse na frente de vocês, do zero. Objetivo: um Pedido que sabe se salvar() no arquivo, e um carregar_todos() que traz a lista de volta — mesmo que o arquivo ainda não exista. Acompanhem o raciocínio passo a passo.

1

Monte a classe Pedido

Com cliente, sabor e valor, e um __str__ que mostre o pedido formatado (ex.: Ana — Calabresa — R$ 39,90).

2

salvar() que anexa

Método salvar(self, caminho="pedidos.txt") que abre no modo "a" com encoding="utf-8" e grava os campos numa linha separada por ;.

3

carregar_todos() que reconstrói

@classmethod carregar_todos(cls, caminho="pedidos.txt") que lê o arquivo iterando linha a linha e devolve uma lista de objetos Pedido.

4

Trate o arquivo que falta

Se o arquivo ainda não existir, o carregar_todos() deve devolver uma lista vazia em vez de quebrar — use try/except FileNotFoundError (aula 14).

resolução · passo 1

A classe Pedido e o __str__

Começamos pela classe: três atributos e um __str__ que devolve o pedido já formatado, pronto pra exibir.

📌
:.2f formata o número com 2 casas (39.90); o .replace troca o ponto pela vírgula do real.
O __str__ (aula 03) deixa o objeto pronto pro print() — a string de exibição mora dentro da classe.
caixa_pizzaria.py
class Pedido:
    def __init__(self, cliente, sabor, valor):
        self.cliente = cliente
        self.sabor = sabor
        self.valor = valor

    def __str__(self):
        preco = f"R$ {self.valor:.2f}".replace(".", ",")
        return f"{self.cliente}{self.sabor}{preco}"

print(Pedido("João", "Coração de Frango", 39.90))   # João — Coração de Frango — R$ 39,90

resolução · passo 2

salvar() que anexa no arquivo

Cada Pedido sabe se gravar. O modo "a" anexa no fim — não apaga o que já estava lá.

📌
"a" (append) escreve no fim do arquivo. Com "w", cada chamada apagaria o pedido anterior.
📌
Os campos vão separados por ; e a linha fecha com \n — um pedido por linha, pra reler depois.
O with fecha o arquivo sozinho; o encoding="utf-8" preserva o ç e os acentos.
caixa_pizzaria.py
    # (dentro da classe Pedido, logo abaixo do __str__)
    def salvar(self, caminho="pedidos.txt"):
        with open(caminho, "a", encoding="utf-8") as f:
            f.write(f"{self.cliente};{self.sabor};{self.valor}\n")

# cada pedido grava uma linha sua
Pedido("João", "Coração de Frango", 39.90).salvar()
Pedido("Ana", "Calabresa", 49.90).salvar()

resolução · passos 3 e 4

carregar_todos() à prova de arquivo que falta

Um @classmethod (aula 03) que lê o arquivo linha a linha, reconstrói a lista de objetos — e não quebra se o arquivo ainda não existir.

📌
split(";") desmonta a linha nos três campos; float(valor) volta a ser número (no arquivo tudo é texto).
📌
cls(...) cria um Pedido — o factory method da aula 03, aqui devolvendo a lista inteira.
O try/except FileNotFoundError (aula 14) cobre a 1ª execução: sem arquivo, devolve [] em vez de explodir.
caixa_pizzaria.py
    @classmethod
    def carregar_todos(cls, caminho="pedidos.txt"):
        pedidos = []
        try:
            with open(caminho, "r", encoding="utf-8") as f:
                for linha in f:
                    cliente, sabor, valor = linha.strip().split(";")
                    pedidos.append(cls(cliente, sabor, float(valor)))
        except FileNotFoundError:
            pass  # arquivo ainda não existe → começamos do zero
        return pedidos

resolução · saída esperada

Juntando tudo — e o que o terminal mostra

Na 1ª execução não há arquivo: carregamos (vazio), gravamos dois pedidos e listamos de volta.

📌
No pedidos.txt o valor fica como 39.9 (texto), mas o __str__ exibe R$ 39,90 — quem formata é a classe, não o arquivo.
É a ponte arquivo + POO: o objeto se grava sozinho e se reconstrói sozinho.
caixa_pizzaria.py
# 1ª execução: ainda não há arquivo → carregar_todos() devolve []
anteriores = Pedido.carregar_todos()
print(f"Pedidos já salvos: {len(anteriores)}")   # Pedidos já salvos: 0

Pedido("João", "Coração de Frango", 39.90).salvar()
Pedido("Ana", "Calabresa", 49.90).salvar()

print("--- Pedidos no caixa ---")
for pedido in Pedido.carregar_todos():
    print(pedido)
# --- Pedidos no caixa ---
# João — Coração de Frango — R$ 39,90
# Ana — Calabresa — R$ 49,90
Rode de novo: agora o arquivo existe, 'Pedidos já salvos' vira 2 — e sobe a cada execução, porque salvar() anexa. A persistência sobreviveu ao fim do programa.

resolução · arquivo completo

O arquivo final: caixa_pizzaria.py

Os quatro passos montados num arquivo só — a classe com seus três métodos e o programa que usa.

caixa_pizzaria.py
class Pedido:
    def __init__(self, cliente, sabor, valor):
        self.cliente = cliente
        self.sabor = sabor
        self.valor = valor

    def __str__(self):
        preco = f"R$ {self.valor:.2f}".replace(".", ",")
        return f"{self.cliente}{self.sabor}{preco}"

    def salvar(self, caminho="pedidos.txt"):
        with open(caminho, "a", encoding="utf-8") as f:
            f.write(f"{self.cliente};{self.sabor};{self.valor}\n")

    @classmethod
    def carregar_todos(cls, caminho="pedidos.txt"):
        pedidos = []
        try:
            with open(caminho, "r", encoding="utf-8") as f:
                for linha in f:
                    cliente, sabor, valor = linha.strip().split(";")
                    pedidos.append(cls(cliente, sabor, float(valor)))
        except FileNotFoundError:
            pass  # arquivo ainda não existe → começamos do zero
        return pedidos


# ── Programa ───────────────────────────────────────────
anteriores = Pedido.carregar_todos()
print(f"Pedidos já salvos: {len(anteriores)}")

Pedido("João", "Coração de Frango", 39.90).salvar()
Pedido("Ana", "Calabresa", 49.90).salvar()

print("--- Pedidos no caixa ---")
for pedido in Pedido.carregar_todos():
    print(pedido)
Uma classe que sabe se salvar e se carregar, e um programa de 8 linhas que a usa. Esse é o esqueleto que os exercícios de casa pedem pra você esticar.

recapitulando

Glossário rápido de hoje

item detalhe
open(caminho, modo, encoding) Abre um arquivo e devolve um objeto de arquivo.
modo r / w / a Ler / escrever do zero (apaga!) / anexar no fim.
with open(...) as f: Abre e fecha o arquivo automaticamente. O jeito recomendado.
encoding="utf-8" Garante acentos e ç. Obrigatório no nosso conteúdo em português.
write() / read() Escreve uma string / lê o conteúdo. write não pula linha sozinho.
FileNotFoundError Erro ao abrir em "r" um arquivo que não existe. Trate com try/except.
json.dump / json.load Grava um dict/list em arquivo / lê de volta. Serialização.

O que dominamos hoje

  • Entendi por que precisamos de arquivos: a memória RAM é volátil; o disco persiste.
  • Sei abrir um arquivo com open() e os modos r, w (apaga!) e a (anexa).
  • Uso with open(...) as f: e entendo que ele fecha o arquivo sozinho, como o finally da aula 14.
  • Coloco sempre encoding="utf-8" pra não corromper acentos.
  • Trato arquivo que não existe com try/except FileNotFoundError.
  • Dou à minha classe um salvar() e um carregar()/from_dict() e gravo objetos em JSON.

exercícios · visão geral

Mãos à obra: os exercícios

Cinco exercícios em três níveis. Começamos juntos agora, em sala — quem não fechar todos, termina em casa. Mire pelo menos um de cada nível antes da próxima aula.

01

Fáceis

2 exercícios — Diário de bordo e Contador de linhas. Foco: open/with, modos a/r e leitura linha a linha.

02

Médios

2 exercícios — Leitura segura e Coleção de jogos. Foco: try/except FileNotFoundError e a ponte arquivo + POO.

03

Difícil

1 exercício — Cardápio em JSON. Foco: serializar uma lista inteira de objetos com json.dump/json.load.

exercícios · nível fácil

Para fixar open() e with

01

Diário de bordo

Crie um diario.py que anexa (modo "a") uma linha nova a um log.txt a cada execução — por exemplo, a data e hora atual com datetime.now() —, sempre com encoding="utf-8". Depois leia tudo iterando for linha in f. Foco: o modo a não apaga, e o \n é por sua conta.
Dica: agora = datetime.now().strftime("%d/%m/%Y %H:%M:%S")

02

Contador de linhas

Leia o log.txt gerado no exercício anterior (ou crie um arquivo com algumas linhas de texto) e conte quantas linhas e quantas palavras ele tem, usando readlines() e .split(). Foco: as formas de ler e iterar o conteúdo.

exercícios · nível médio

Tratar erros e persistir objetos

03

Leitura segura

Função ler_config(caminho) que tenta abrir o arquivo em "r" e devolve o conteúdo lido; se ele não existir, captura FileNotFoundError, cria o arquivo com um conteúdo padrão (ex.: tema=escuro) e tenta de novo. Foco: o try/except FileNotFoundError da aula 14 aplicado a arquivos.

04

Coleção de jogos

Classe Jogo com nome, categoria e num_jogadores, um __str__ formatado e um salvar(self, caminho="jogos.txt") que anexa (modo "a", encoding="utf-8") os campos separados por ;. Um @classmethod carregar_todos() lê o arquivo linha a linha e devolve uma lista de objetos Jogo, tratando com try/except FileNotFoundError o arquivo que ainda não existe. Foco: reproduzir de memória o padrão do exercício ao vivo, num domínio novo. Atenção: num_jogadores é inteiro — na hora de carregar é int(...), não float(...).

exercícios · nível difícil

O desafio que junta tudo

05

Cardápio em JSON

Classe Pizza com sabor, tamanho e preco, mais to_dict()/from_dict(). Uma classe Cardapio guarda uma lista de pizzas, com um adicionar(pizza) pra incluir cada uma, um salvar(caminho) que grava a lista inteira com json.dump e um @classmethod carregar(caminho) que lê com json.load, reconstrói cada Pizza e devolve um Cardapio — tratando com try/except FileNotFoundError o arquivo que ainda não existe. Foco: serializar uma coleção de objetos — exatamente a ponte pra aula 18. Atenção: json.dump grava dicionários, não objetos.

próxima aula

Aula 18 · 22/06

Coleções e POO

Hoje salvamos um objeto por vez. Na próxima, vamos guardar VÁRIOS com elegância: list, dict, set e tuple — e como as suas classes conversam com for, in e sorted.

list, dict, set, tuple comprehensions objetos em coleções