
Passo 1 de 6
Calcular valores na leitura de um atributo
Use @property para expor um valor calculado com a mesma sintaxe de um atributo.
Trilha de aprendizado · Nível 11 · Tutorial 6
Ao concluir, você poderá manter uma interface de atributo enquanto calcula valores ou valida atribuições, sem expor diretamente a organização interna do objeto.
Calcular valores na leitura de um atributo
Use @property para expor um valor calculado com a mesma sintaxe de um atributo. 3 min
Separar o acesso público do armazenamento
Crie um getter e um setter para controlar a leitura e a atribuição de lado sem mudar a sintaxe usada por quem acessa o objeto. 3 min
Validar antes de alterar o estado
Use o setter para aceitar apenas medidas positivas e manter o último estado válido quando uma atribuição falhar. 3 min
Validar também na criação do objeto
Reutilize o setter no inicializador para aplicar uma única regra tanto na criação quanto nas alterações posteriores. 2 min
Entender os limites de somente leitura
Uma propriedade sem setter bloqueia uma atribuição direta, mas não torna automaticamente a instância nem os objetos retornados por ela imutáveis. 3 min
Aplicar e verificar o contrato das propriedades
Integre cálculo, validação e armazenamento interno em uma classe Quadrado e confira o contrato pela interface pública. 4 min

Passo 1 de 6
Use @property para expor um valor calculado com a mesma sintaxe de um atributo.
Uma property permite manter a leitura com ponto — quadrado.area — enquanto Python executa um método para produzir o valor.
Ao colocar @property acima de um método, você transforma esse método em uma interface de atributo. O método recebe self e retorna o valor que será lido.
A área não precisa existir como um segundo valor salvo no objeto: ela é obtida a partir do lado atual sempre que for consultada.

Ler area aciona o cálculo usando o valor atual de lado.
O método area é escrito como um método comum, mas @property faz com que ele seja acessado sem parênteses.
class Quadrado:
def __init__(self, lado):
self.lado = lado
@property
def area(self):
return self.lado * self.lado
quadrado = Quadrado(4)
print(quadrado.area) # 16Exemplo
Use quadrado.area, e não quadrado.area(). Embora area execute código internamente, para quem usa o objeto ela se comporta como uma leitura de atributo.
Assim, código que apenas consulta a área não precisa saber se ela está armazenada ou calculada.
O getter de area é executado a cada leitura. Ele não guarda automaticamente o resultado: consulta self.lado e calcula de novo.
Isso evita manter uma área separada que poderia ficar desatualizada depois de uma mudança no lado.
Execute este código no seu computador e compare as duas saídas.
quadrado = Quadrado(4)
print(quadrado.area) # 16
quadrado.lado = 7
print(quadrado.area) # 49Com a classe Quadrado mostrada, o que print(quadrado.area) exibe depois de quadrado.lado = 7?

Passo 2 de 6
Crie um getter e um setter para controlar a leitura e a atribuição de lado sem mudar a sintaxe usada por quem acessa o objeto.
A propriedade lado é a interface pública: o código continua lendo quadrado.lado e atribuindo quadrado.lado = 8.
O valor fica guardado em _lado. O getter lê _lado; o setter grava em _lado. Esse nome diferente evita que a propriedade chame a si mesma.

Use lado para acessar a interface e _lado para armazenar o valor da instância.
O decorador @lado.setter se aplica à propriedade já criada com @property. Os dois métodos usam o nome lado.
class Quadrado:
def __init__(self, lado):
self._lado = lado
@property
def lado(self):
return self._lado
@lado.setter
def lado(self, novo_lado):
self._lado = novo_lado
quadrado = Quadrado(4)
print(quadrado.lado) # 4
quadrado.lado = 8
print(quadrado.lado) # 8Dentro do getter, self.lado tenta ler a propriedade novamente, que executa o getter outra vez. Dentro do setter, self.lado = novo_lado tenta atribuir à mesma propriedade novamente, que executa o setter outra vez.
Nenhum dos dois chega a guardar ou retornar um valor: as chamadas se repetem até Python interromper com RecursionError. Use self._lado no corpo dos dois métodos.
Estes acessos parecem naturais, mas chamam a propriedade de novo.
class Quadrado:
@property
def lado(self):
return self.lado # chama o getter repetidamente
@lado.setter
def lado(self, novo_lado):
self.lado = novo_lado # chama o setter repetidamentePara armazenar o novo valor sem chamar o setter outra vez, complete: self._____ = novo_lado
Explique por que return self.lado no getter ou self.lado = novo_lado no setter causa recursão. Indique qual atributo deve ser usado no lugar.
Escreva pelo menos 80 caracteres (0/80).

Passo 3 de 6
Use o setter para aceitar apenas medidas positivas e manter o último estado válido quando uma atribuição falhar.
A interface pública continua sendo quadrado.lado = valor. No setter, teste o novo valor antes de alterar _lado.
Neste exemplo, uma medida de lado só é válida quando é maior que zero. Zero e números negativos devem gerar ValueError.
A ordem das operações determina se o objeto preserva seu último estado válido.

Valor válido: valida e grava. Valor inválido: lança uma exceção antes de qualquer gravação.
O raise interrompe o setter. Portanto, a linha que grava em _lado não é executada para valores inválidos.
class Quadrado:
def __init__(self, lado):
self._lado = lado
@property
def lado(self):
return self._lado
@lado.setter
def lado(self, novo_lado):
if novo_lado <= 0:
raise ValueError("lado deve ser maior que zero")
self._lado = novo_lado
@property
def area(self):
return self._lado ** 2Exemplo
Com um quadrado já existente:
quadrado = Quadrado(4)quadrado.lado = 6 → quadrado.lado é 6 e quadrado.area é 36.
Depois, quadrado.lado = -2 lança ValueError. Como a validação ocorreu antes de self._lado = novo_lado, o objeto continua com lado 6 e área 36.
Ordene o que acontece quando o código executa quadrado.lado = 0.
Considere quadrado = Quadrado(5). Ao executar quadrado.lado = 0, o que acontece com a exceção, com quadrado.lado e com quadrado.area?
Escreva pelo menos 30 caracteres (0/30).
Dica
Em setters que protegem um estado válido, valide primeiro e grave depois. Assim, uma rejeição não deixa o objeto parcialmente alterado.

Passo 4 de 6
Reutilize o setter no inicializador para aplicar uma única regra tanto na criação quanto nas alterações posteriores.
Se lado já possui um setter que valida valores, use self.lado = lado em __init__. Assim, a mesma regra vale ao criar o objeto e ao alterá-lo depois, sem copiá-la para dois lugares.
O valor inicial passa pelo setter antes de chegar ao armazenamento interno.

Ao usar self.lado no inicializador, o setter controla a criação da instância.
O inicializador delega a validação ao setter.
class Quadrado:
def __init__(self, lado):
self.lado = lado
@property
def lado(self):
return self._lado
@lado.setter
def lado(self, valor):
if valor <= 0:
raise ValueError("lado deve ser maior que zero")
self._lado = valor
@property
def area(self):
return self._lado ** 2Exemplo
quadrado = Quadrado(4) cria a instância com quadrado.lado == 4 e quadrado.area == 16.
Já Quadrado(0) executa o setter, recebe um ValueError e não devolve uma instância válida.
Dica
Evite self._lado = lado em __init__ quando o valor inicial precisar obedecer à mesma regra. Essa atribuição grava diretamente no armazenamento e contorna a validação.
Qual implementação de __init__ reutiliza o setter de lado?

Passo 5 de 6
Uma propriedade sem setter bloqueia uma atribuição direta, mas não torna automaticamente a instância nem os objetos retornados por ela imutáveis.
Quando uma propriedade tem apenas getter, você pode lê-la, mas não atribuir diretamente a ela. A tentativa de quadrado.area = 100 gera AttributeError.
Isso proíbe substituir o valor pela interface area. Não significa que o resultado calculado nunca mudará.
A área continua sendo calculada a partir de lado. Ao alterar lado por sua interface permitida, a próxima leitura de area mostra outro resultado.

area não recebe atribuições, mas seu resultado acompanha mudanças em lado.
Execute este exemplo:
class Quadrado:
def __init__(self, lado):
self.lado = lado
@property
def area(self):
return self.lado ** 2
quadrado = Quadrado(4)
print(quadrado.area) # 16
quadrado.lado = 5
print(quadrado.area) # 25
# quadrado.area = 100 # AttributeError: property 'area' ... has no setterUma property também pode devolver uma lista. Sem setter, objeto.itens = outra_lista é proibido. Porém, se o getter devolve a própria lista interna, objeto.itens.append(...) modifica essa lista.
Há uma diferença importante: atribuir troca o valor associado ao atributo; chamar append modifica o objeto lista já acessado.
Exemplo
class ListaDeCompras:
def __init__(self):
self._itens = ["arroz"]
@property
def itens(self):
return self._itens
lista = ListaDeCompras()
lista.itens.append("feijão") # permitido: modifica a lista retornada
print(lista.itens) # ['arroz', 'feijão']
# lista.itens = [] # AttributeError: não há setterA property controla a atribuição a itens; ela não impede, por si só, as operações disponíveis na lista retornada.
Se area possui apenas getter e é calculada a partir de lado, então area pode mudar após uma atribuição válida a lado.
Uma property sem setter que devolve uma lista impede automaticamente objeto.itens.append(valor).
O prefixo _ comunica que _lado é um detalhe interno da implementação e que o uso normal deve ocorrer por lado. É uma convenção para pessoas que leem e usam a classe, não uma barreira de segurança imposta pelo Python.
Assim, quadrado._lado ainda pode ser acessado e alterado diretamente. Fazer isso pode contornar a validação do setter e deixar o objeto em um estado que a interface pública evitaria.
Atenção
Se a classe oferece lado para validar alterações, use quadrado.lado = novo_valor. Alterar quadrado._lado diretamente ignora a regra definida pela própria classe; o _ sinaliza exatamente esse risco.

Passo 6 de 6
Integre cálculo, validação e armazenamento interno em uma classe Quadrado e confira o contrato pela interface pública.
Agora reúna o que você praticou: lado é a interface pública validada; _lado guarda o valor aceito; e area é calculada a cada leitura. Quem usa o objeto continua escrevendo quadrado.lado e quadrado.area, sem precisar conhecer essa organização interna.
A leitura de area calcula um resultado; a escrita em lado passa pela validação antes de alcançar _lado.

lado controla leitura e escrita; area é somente leitura e deriva do estado interno.
Crie um arquivo chamado quadrado.py, copie o código completo abaixo e execute python quadrado.py no terminal. O bloco try permite observar a rejeição sem interromper as demais verificações.
Classe completa e roteiro de verificações.
class Quadrado:
def __init__(self, lado):
self.lado = lado
@property
def lado(self):
return self._lado
@lado.setter
def lado(self, valor):
if valor <= 0:
raise ValueError("lado deve ser maior que zero")
self._lado = valor
@property
def area(self):
return self._lado ** 2
quadrado = Quadrado(4)
print(quadrado.lado) # 4
print(quadrado.area) # 16
quadrado.lado = 5
print(quadrado.lado) # 5
print(quadrado.area) # 25
try:
quadrado.lado = 0
except ValueError as erro:
print(erro) # lado deve ser maior que zero
print(quadrado.lado) # 5: estado preservado
print(quadrado.area) # 25
try:
Quadrado(-2)
except ValueError as erro:
print(erro) # lado deve ser maior que zero
try:
quadrado.area = 100
except AttributeError as erro:
print(type(erro).__name__) # AttributeError
Dica
Quando quadrado.lado = 0 falha, a exceção ocorre antes de self._lado = valor. Por isso o objeto mantém o último lado válido: 5.
Execute o roteiro. Relate o que ocorreu em pelo menos quatro situações: criação com 4, mudança para 5, tentativa de usar 0, criação com -2 e atribuição a area. Explique por que o lado permanece 5 após a tentativa inválida.
Escreva pelo menos 120 caracteres (0/120).
Resumo
Uma property preserva a sintaxe de atributo enquanto define o que acontece na leitura ou na atribuição.
area, para evitar armazenar valores derivados que podem ficar desatualizados.self.lado = lado quando a regra do setter também deve valer na criação.AttributeError; isso não torna toda a instância imutável._ comunica uso interno por convenção, não é uma barreira de segurança.Parabéns! Você concluiu: Controlar atributos com property
Milhares de cursos online em vídeo, ebooks e áudiobooks.
Para testar seus conhecimentos no decorrer dos cursos online
Gerado diretamente na galeria de fotos do seu celular e enviado ao seu e-mail
Baixe nosso aplicativo pelo QR Code ou pelos links abaixo:.
+ de 10 milhões
de alunos
Certificado grátis e
válido em todo o Brasil
60 mil exercícios
gratuitos
4,8/5 classificação
nas lojas de apps
Cursos gratuitos em
vídeo, ebooks e audiobooks