O que é e como utilizar @property no Python

Cansado de programar?

Cansado(a) de quebrar a cabeça para aprender a programar Python de verdade?

Conheça a melhor e mais completa formação de Python e Django e sinta-se um programador verdadeiramente competente. Além de Python e Django, você também vai aprender Banco de Dados, SQL, HTML, CSS, Javascript, Bootstrap e muito mais!

Quero aprender Python e Django de Verdade! Quero aprender!
Suporte

Tire suas dúvidas diretamente com o professor

Suporte

Projetos práticos voltados para o mercado de trabalho

Suporte

Formação moderna com foco na prática profissional

Download do Artigo

Atualizado para Python 3.13 (Dezembro 2025)
Conteúdo enriquecido com atributos computados, validação e casos práticos.

Salve salve Pythonista!

@property transforma métodos em atributos, permitindo validação, cálculos e encapsulamento sem mudar a interface pública da classe!

Neste guia, você vai aprender:

  • Getters/Setters Pythônicos - Sem .get_x() / .set_x()
  • Validação automática - Dados sempre válidos
  • Atributos computados - Cálculos sob demanda
  • Casos práticos - Temperatura, idade, preços

O Python é uma linguagem de programação flexível e poderosa que oferece uma série de recursos avançados para os desenvolvedores.

Um desses recursos é o decorador @property, que permite transformar métodos de uma classe em propriedades, tornando o código mais elegante e fácil de entender.

Nesse artigo você vai aprender o que é e como utilizar o @property no Python.

Sem mais delongas, vamos nessa!

Vá Direto ao Assunto…

Ao criar classes em Python, é comum definir métodos que retornam ou modificam valores de atributos.

Se ainda não sabe sobre Classes em Python, leia nosso outro artigo sobre Classes no Python

No entanto, esses métodos muitas vezes têm nomes diferentes dos atributos e são acessados como funções.

Para melhorar a legibilidade do código e fornecer uma sintaxe mais intuitiva, podemos usar o decorador @property.

Neste artigo, vamos explorar o que é o @property no Python e como utilizá-lo em nossas classes para criar propriedades que podem ser acessadas de uma forma mais intuitiva.

Propriedades em Python

Antes de mergulharmos no @property, é importante entender o conceito de propriedades em Python.

Uma propriedade é um atributo de classe que é calculado dinamicamente, em vez de ser armazenado em memória.

Quando um atributo é uma propriedade, ele é acessado e modificado como qualquer outro atributo, mas na verdade, por trás dos panos, um método customizado é chamado.

Ao utilizar propriedades, podemos ter controle sobre o acesso e modificação de atributos de uma classe, permitindo realizar validações, conversões de dados ou cálculos adicionais antes de retornar ou definir o valor.

O decorador @property

Em Python, o decorador @property é usado para transformar um método em uma propriedade de uma classe.

Ele permite que um método seja acessado como atributo, sem a necessidade de chamá-lo como uma função.

Vamos começar com um exemplo simples para ilustrar como o @property funciona.

Suponha que temos a classe Retangulo que representa um retângulo e possui os atributos largura e altura.

Para calcular a área do retângulo, poderíamos ter um método chamado calcular_area, como mostrado abaixo:

1
2
3
4
5
6
7
class Retangulo:
    def __init__(self, largura, altura):
        self.largura = largura
        self.altura = altura
    
    def calcular_area(self):
        return self.largura * self.altura

Neste caso, para calcular a área do retângulo, precisamos chamar o método calcular_area() explicitamente:

1
2
3
retangulo = Retangulo(5, 3)
area = retangulo.calcular_area()
print(area)

E a saída seria:

1
15

Agora, vamos utilizar o @property para transformar o método calcular_area() em uma propriedade da classe Retangulo:

1
2
3
4
5
6
7
8
class Retangulo:
    def __init__(self, largura, altura):
        self.largura = largura
        self.altura = altura
    
    @property
    def area(self):
        return self.largura * self.altura

Note o uso do decorador @property antes do método area(). Agora, podemos acessar a área do retângulo como se fosse um atributo:

1
2
retangulo = Retangulo(5, 3)
print(retangulo.area)  # Saída: 15

Agora, a chamada retangulo.area retorna o valor da área sem a necessidade de chamarmos explicitamente o método.

:bulb: Estou construindo o DevBook, uma plataforma que usa IA para criar ebooks técnicos — com código formatado e exportação em PDF. Te convido a conhecer!

Getters e Setters

Em muitos casos, queremos não apenas obter o valor calculado de uma propriedade, mas também definir seu valor.

Para isso, utilizamos os métodos getter e setter.

O método getter é responsável por retornar o valor da propriedade quando ela é acessada.

Utilizamos o decorador @property para definir o getter, como já vimos anteriormente.

O método setter, por sua vez, é usado para definir o valor da propriedade quando ela é modificada.

Para definir o setter, utilizamos o mesmo nome da propriedade seguido pelo decorador @nomedapropriedade.setter.

Vamos expandir nosso exemplo anterior para incluir um setter para modificar a largura do retângulo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Retangulo:
    def __init__(self, largura, altura):
        self._largura = largura
        self.altura = altura
    
    @property
    def largura(self):
        return self._largura
    
    @largura.setter
    def largura(self, nova_largura):
        if nova_largura > 0:
            self._largura = nova_largura
        else:
            raise ValueError("A largura deve ser maior que 0.")
    
    @property
    def area(self):
        return self.largura * self.altura

Neste exemplo, criamos um método largura para funcionar como o getter da propriedade largura e um método largura.setter para funcionar como o setter.

O método setter verifica se o novo valor da largura é maior que zero e, em caso positivo, atualiza o atributo _largura.

Caso contrário, lança uma exceção ValueError informando que a largura deve ser maior que zero.

Agora, podemos usar a propriedade largura para obter e modificar o valor da largura do retângulo:

1
2
3
4
5
6
7
retangulo = Retangulo(5, 3)
print(retangulo.largura)  # Saída: 5

retangulo.largura = 7
print(retangulo.largura)  # Saída: 7

retangulo.largura = -1  # Lança uma exceção ValueError

Podemos ver que, ao acessar a propriedade largura, o método largura() é chamado e retorna o valor atual da largura.

Da mesma forma, ao atribuir um novo valor à propriedade largura, o método largura.setter é executado e valida o novo valor antes de atualizar _largura.

Está curtindo esse conteúdo? :thumbsup:

Que tal receber 30 dias de conteúdo direto na sua Caixa de Entrada?

Sua assinatura não pôde ser validada.
Você fez sua assinatura com sucesso.

Assine as PyDicas e receba 30 dias do melhor conteúdo Python na sua Caixa de Entrada: direto e sem enrolação!

Deletar propriedades

Além de obter e definir o valor de uma propriedade, também podemos excluí-la utilizando o método deleter.

Para definir o deleter de uma propriedade, utilizamos o decorador @nomedapropriedade.deleter.

Vamos adicionar um método deleter à classe Retangulo para excluir a propriedade largura:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Retangulo:
    def __init__(self, largura, altura):
        self._largura = largura
        self.altura = altura
    
    @property
    def largura(self):
        return self._largura
    
    @largura.setter
    def largura(self, nova_largura):
        if nova_largura > 0:
            self._largura = nova_largura
        else:
            raise ValueError("A largura deve ser maior que 0.")
    
    @largura.deleter
    def largura(self):
        del self._largura
    
    @property
    def area(self):
        return self.largura * self.altura

Agora podemos excluir a propriedade largura utilizando o comando del:

1
2
3
4
5
6
retangulo = Retangulo(5, 3)
print(retangulo.largura)  # Saída: 5

del retangulo.largura

print(retangulo.largura)

Ao tentar acessar a propriedade na linha print(retangulo.largura) o seguinte erro será lançado:

1
AttributeError: 'Retangulo' object has no attribute '_largura'

Casos de uso do @property

O decorador @property é muito útil em situações em que precisamos controlar o acesso aos atributos de uma classe.

Aqui estão alguns exemplos de casos de uso comuns:

  • Conversão de tipos: podemos usar @property para converter automaticamente tipos de dados. Por exemplo, podemos ter um atributo data que é armazenado como uma string e uma propriedade data que devolve o valor convertido em um objeto datetime.
  • Verificação de validade: podemos adicionar validações em um setter para garantir que os atributos estão dentro dos limites aceitáveis. Por exemplo, podemos ter um atributo idade que precisa ser um número positivo e, caso contrário, levanta um erro.
  • Uso de cache: podemos utilizar uma propriedade para fazer cache de um valor calculado, evitando recalcular a cada vez que a propriedade é acessada.
  • Acesso a dados externos: podemos usar propriedades para acessar e atualizar dados em bancos de dados externos ou sistemas remotos. Dessa forma, podemos manter a interface do objeto consistente, independentemente de onde os dados são armazenados.

Casos Práticos Adicionais

1. Conversor de Temperatura

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Temperatura:
    def __init__(self, celsius):
        self._celsius = celsius
    
    @property
    def celsius(self):
        return self._celsius
    
    @celsius.setter
    def celsius(self, valor):
        if valor < -273.15:
            raise ValueError("Temperatura abaixo do zero absoluto!")
        self._celsius = valor
    
    @property
    def fahrenheit(self):  # Somente leitura
        return self._celsius * 9/5 + 32
    
    @property
    def kelvin(self):  # Somente leitura
        return self._celsius + 273.15

temp = Temperatura(25)
print(f"{temp.celsius}°C = {temp.fahrenheit}°F = {temp.kelvin}K")
# 25°C = 77.0°F = 298.15K

2. Produto com Preço Calculado

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Produto:
    def __init__(self, nome, preco_base, imposto=0.1):
        self.nome = nome
        self._preco_base = preco_base
        self.imposto = imposto
    
    @property
    def preco_base(self):
        return self._preco_base
    
    @preco_base.setter
    def preco_base(self, valor):
        if valor <= 0:
            raise ValueError("Preço deve ser positivo")
        self._preco_base = valor
    
    @property
    def preco_final(self):  # Calculado automaticamente
        return self._preco_base * (1 + self.imposto)

produto = Produto("Mouse", 100)
print(produto.preco_final)  # 110.0
produto.preco_base = 150
print(produto.preco_final)  # 165.0

3. Pessoa com Idade Calculada

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from datetime import datetime, date

class Pessoa:
    def __init__(self, nome, data_nascimento):
        self.nome = nome
        self._data_nascimento = data_nascimento
    
    @property
    def data_nascimento(self):
        return self._data_nascimento
    
    @data_nascimento.setter
    def data_nascimento(self, valor):
        if valor > date.today():
            raise ValueError("Data de nascimento no futuro!")
        self._data_nascimento = valor
    
    @property
    def idade(self):  # Sempre atualizado!
        hoje = date.today()
        return hoje.year - self._data_nascimento.year - (
            (hoje.month, hoje.day) < (self._data_nascimento.month, self._data_nascimento.day)
        )

pessoa = Pessoa("Alice", date(1990, 5, 15))
print(pessoa.idade)  # Calcula idade atual automaticamente

@property vs Atributos Públicos

Quando Usar @property?

Use @property quando:

  • Precisa validar valores
  • Atributo é calculado (não armazenado)
  • Precisa controlar acesso (read-only)
  • Pode precisar mudar lógica no futuro
  • Lazy loading (calcular só quando necessário)

Quando NÃO usar @property?

Use atributo simples quando:

  • Atributo é apenas armazenamento (sem lógica)
  • Performance crítica (property tem overhead mínimo)
  • Não precisa validação
  • Classe é simples (dataclass)
1
2
3
4
5
6
7
8
9
10
11
12
13
# ❌ Property desnecessária
class Usuario:
    def __init__(self, nome):
        self._nome = nome
    
    @property
    def nome(self):
        return self._nome  # Só retorna, sem lógica

# ✅ Atributo público direto
class Usuario:
    def __init__(self, nome):
        self.nome = nome  # Mais simples!

Conclusão

Neste guia de @property, você aprendeu:

Getters/Setters - Interface Pythônica sem .get_x()
Validação - Dados sempre válidos automaticamente
Atributos computados - Cálculos sob demanda (idade, temperatura)
Read-only - Propriedades somente leitura
@property vs públicos - Quando usar cada um

Principais lições:

  • @property torna métodos acessíveis como atributos
  • Use para validação e cálculos
  • Setter controla modificações
  • Deleter permite del objeto.atributo
  • Property tem overhead mínimo (99% dos casos, use!)

Próximos passos:

  • Pratique Classes e Objetos
  • Explore Dataclasses (reduz boilerplate)
  • Aprenda __getattr__ e __setattr__
  • Estude descriptors (property avançado)

O decorador @property é uma ferramenta poderosa que nos permite transformar métodos em propriedades de uma classe, oferecendo um acesso mais intuitivo e controlado a essas propriedades.

Além de fornecer uma sintaxe mais elegante, as propriedades também nos permitem adicionar validações, conversões de dados e realizar cálculos adicionais antes de retornar ou definir o valor de um atributo.

Com esse conhecimento em mãos, você está pronto para utilizar o @property em suas classes Python e tornar seus códigos mais legíveis e eficientes.

Experimente utilizar propriedades em seus projetos e descubra como elas podem simplificar o acesso e a manipulação de atributos em suas classes.

É isso por hoje! Nos vemos no próximo artigo :wink:

Começe agora sua Jornada na Programação!

Não deixe para amanhã o sucesso que você pode começar a construir hoje!

#newsletter Olá :wave: Curtiu o artigo? Então faça parte da nossa Newsletter! Privacidade Não se preocupe, respeitamos sua privacidade. Você pode se descadastrar a qualquer momento.