Da trilha de Python Este conceito ainda não saiu como card do dia. ir para o card de hoje

Python POO Intermediário

Properties

Em Python, properties permitem que você acesse métodos como se fossem atributos, mantendo a sintaxe simples de obj.x mas executando código personalizado. A decoradora @property transforma um método em um getter; para permitir atribuição, define-se um setter com @nome.setter. Isso é útil para criar atributos calculados (derivados de outros) e para validação de dados, garantindo que o objeto permaneça em estado válido.

Com properties, você pode começar com atributos públicos simples e, se precisar adicionar lógica depois, não quebra a interface existente. O acesso continua sendo obj.atributo, mas internamente o Python chama o método decorado. Além disso, properties são a maneira idiomática de implementar getters e setters em Python, evitando métodos explícitos como get_x() e set_x().

Neste card, veremos como criar uma property somente leitura (apenas getter), como adicionar validação no setter e como calcular valores dinamicamente a partir de outros atributos. Também abordaremos erros comuns, como esquecer de usar o mesmo nome no setter ou tentar modificar uma property sem setter.

Pontos-chave

  • @property transforma um método em um getter acessível como atributo.
  • O setter é definido com @nome.setter e permite validar ou transformar o valor antes de armazenar.
  • Atributos calculados são properties que derivam seu valor de outros atributos, sem armazenar estado redundante.
  • Properties mantêm a sintaxe de acesso direto, mas executam código personalizado.
  • Sem setter, a property é somente leitura e tentar atribuir gera AttributeError.
properties_exemplo.py
class Circulo:
    def __init__(self, raio):
        self.raio = raio  # usa o setter para validar

    @property
    def raio(self):
        return self._raio

    @raio.setter
    def raio(self, valor):
        if valor <= 0:
            raise ValueError("O raio deve ser positivo")
        self._raio = valor

    @property
    def area(self):
        # atributo calculado: não armazena, calcula na hora
        return 3.14159 * self._raio ** 2


c = Circulo(2)
print(c.raio)   # 2
print(c.area)   # 12.56636
c.raio = 3
print(c.area)   # 28.27431
try:
    c.raio = -1
except ValueError as e:
    print(e)    # O raio deve ser positivo

Exercícios

  1. 1
    Fácil

    Temperatura com property

    Crie uma classe Temperatura que armazena graus Celsius em um atributo privado _celsius. Use @property para expor celsius (getter) e um setter que não permita valores abaixo de -273.15 (zero absoluto). Se o valor for inválido, lance ValueError com a mensagem 'Temperatura abaixo do zero absoluto'.

    Resolver
  2. 2
    Médio

    Retângulo com área calculada

    Crie uma classe Retangulo que armazena largura e altura como properties com validação (devem ser maiores que zero). Adicione uma property somente leitura area que calcula a área. Adicione também uma property perimetro que calcula o perímetro. Não armazene area nem perimetro como atributos; calcule-os dinamicamente.

    Resolver
  3. 3
    Desafio

    Conta bancária com saldo e histórico

    Implemente uma classe ContaBancaria com as properties saldo (somente leitura, calculado a partir do histórico de transações) e historico (somente leitura, retorna uma cópia da lista de transações). A classe deve ter métodos depositar(valor) e sacar(valor). Depósitos e saques devem ser registrados no histórico como tuplas (tipo, valor), onde tipo é 'deposito' ou 'saque'. Saques não podem exceder o saldo; caso contrário, lance ValueError('Saldo insuficiente'). Depósitos e saques devem ser maiores que zero; caso contrário, lance ValueError('Valor deve ser positivo').

    Resolver

Continue estudando