Médio Python
Retângulo com área calculada
Enunciado
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.
Requisitos
- As properties
larguraealturadevem ter getter e setter com validação (valor > 0). - A property
areadeve ser somente leitura e retornarlargura * altura. - A property
perimetrodeve ser somente leitura e retornar2 * (largura + altura).
Código inicial
class Retangulo:
def __init__(self, largura, altura):
pass
@property
def largura(self):
pass
@largura.setter
def largura(self, valor):
pass
@property
def altura(self):
pass
@altura.setter
def altura(self, valor):
pass
@property
def area(self):
pass
@property
def perimetro(self):
pass
Saída esperada
Area: 6
Perimetro: 10
Nova area: 12
Erro: Largura deve ser positiva
Ver dica
Para a área e perímetro, apenas retorne o cálculo usando self.largura e self.altura. Lembre-se de que não precisa de setter para elas.
Mostrar solução
class Retangulo:
def __init__(self, largura, altura):
self.largura = largura # usa setter
self.altura = altura # usa setter
@property
def largura(self):
return self._largura
@largura.setter
def largura(self, valor):
if valor <= 0:
raise ValueError('Largura deve ser positiva')
self._largura = valor
@property
def altura(self):
return self._altura
@altura.setter
def altura(self, valor):
if valor <= 0:
raise ValueError('Altura deve ser positiva')
self._altura = valor
@property
def area(self):
return self._largura * self._altura
@property
def perimetro(self):
return 2 * (self._largura + self._altura)
# Testes
r = Retangulo(2, 3)
print(f'Area: {r.area}')
print(f'Perimetro: {r.perimetro}')
r.largura = 4
print(f'Nova area: {r.area}')
try:
r.largura = -1
except ValueError as e:
print(f'Erro: {e}')
Passo a passo
- No
__init__, atribuímoslarguraealturausandoself.largura = ...eself.altura = ..., acionando os setters para validar. - O getter de
larguraretornaself._largura; o setter verifica se o valor é maior que zero e, caso contrário, lançaValueError. - O mesmo padrão é aplicado para
altura. - A property
areaé somente leitura (sem setter) e calculaself._largura * self._alturatoda vez que é acessada. - A property
perimetrotambém é somente leitura e calcula2 * (self._largura + self._altura). - Nos testes, criamos um retângulo 2x3, imprimimos área e perímetro. Depois alteramos a largura para 4 e a área é recalculada automaticamente.
- Tentamos atribuir largura negativa, o que dispara o setter e lança a exceção, capturada e impressa.
Por que funciona
As properties largura e altura controlam o acesso aos atributos internos, garantindo que nunca sejam inválidos. As properties area e perimetro são calculadas sob demanda, refletindo sempre os valores atuais. Isso evita inconsistências e mantém o código limpo.
Erros comuns
- Armazenar área como atributo: se fizer
self.area = ...no__init__, a área não será atualizada quando largura ou altura mudarem. Prefira calcular na property. - Esquecer de validar no setter: sem validação, valores negativos ou zero podem causar resultados incorretos.
- Tentar atribuir a
area: como não há setter,r.area = 10geraAttributeError. Isso é esperado para atributos calculados somente leitura.
Outra forma de resolver
Poderia-se usar métodos get_area() e get_perimetro(), mas properties permitem acesso como atributo, mais natural.
Saída esperada
Area: 6
Perimetro: 10
Nova area: 12
Erro: Largura deve ser positiva