Solucionado (ver solução)
Solucionado
(ver solução)
1
resposta

Python property

Quais são as diferença entre os metodos com @property e os sem?

1 resposta
solução!

Olá, Caio.

O uso do decorator @property são a maneira "pythonica" de se trabalhar com atributos, pois:

  • A sintaxe usada para definir propriedades é muito concisa e legível.
  • Você pode acessar os atributos da instância exatamente como se fossem atributos públicos enquanto usa a "mágica" de intermediários (getters e setters) para validar novos valores e evitar acessar ou modificar os dados diretamente.
  • Usando @property, você pode "reutilizar" o nome de uma propriedade para evitar a criação de novos nomes para os getters, setters e deleters.

O utilizador da classe não vai perceber se o criador usa ou não @property em seus atributos.

Problema real

Imagine que você queira criar a seguinte classe:

class House:
    def __init__(self, price):
        self.price = price

O atributo price pode facilmente ser acessado ou modificado usando:

# Acessar
obj.price

# Modificar
obj.price = 40000

Agora imagine que você usa essa classe em produção, mas agora deseje adicionar getters e setters ao atributo price. Você teria que mudar todas as linhas de acesso e modificação para:

# Acessar
obj.get_price()

# Modificar
obj.set_price(40000)

Caso contrário, o código pararia.

Se você decidir usar @property, sua classe será semelhante ao exemplo abaixo:

class House:
    def __init__(self, price):
        self._price = price

    @property
    def price(self):
        return self._price

    @price.setter
    def price(self, new_price):
        if new_price > 0 and isinstance(new_price, float):
            self._price = new_price
        else:
            print("Please enter a valid price")

Observe que o atributo price agora é considerado "protegido" porque adicionamos um sublinhado à esquerda ao nome em self._price. No Python, por escolha, quando você adiciona um sublinhado inicial a um nome, está dizendo a outros desenvolvedores que ele não deve ser acessado ou modificado diretamente fora da classe. Só deve ser acessado através de intermediários (getters e setters) se estiverem disponíveis.

Com a utilização de @property, o acesso e modificação permanacem os mesmos:

# Acessar
obj.price

# Modificar
obj.price = 40000

Além disso, como adicionamos uma nova regra de negócio ao atributo. Se tentarmos atribuir um valor inválido, vemos a mensagem descritiva. O código a seguir:

house = House(50000.0)
house.price = -50

Apresentaria o seguinte erro: Please enter a valid price. Além disso, seu valor não seria atualizado.

Dicas

Você não precisa necessariamente definir os três métodos para cada atributo. Você pode definir propriedades somente leitura incluindo apenas um método getter. Você também pode optar por definir um getter e um setter sem um deleter.

Se você acha que um atributo deve ser definido apenas quando a instância é criada ou que somente deve ser modificado internamente na classe, você pode omitir o configurador.

Você pode escolher quais métodos incluir, dependendo do contexto em que estiver trabalhando.

Em suma:

  • Você pode definir propriedades com a sintaxe @property, que é mais compacta e legível.
  • O uso de @property pode ser considerada a maneira "pytônica" de definir getters, setters e deleters.
  • Ao definir propriedades, você pode alterar a implementação interna de uma classe sem afetar o programa, para adicionar getters, setters e deleters que atuam como intermediários "nos bastidores" para evitar acessar ou modificar os dados diretamente.

Espero ter ajudado.