Propriedade Python

Resumo : neste tutorial, você aprenderá sobre a propertyclasse Python e como usá-la para definir propriedades para uma classe.

Introdução às propriedades da classe

O seguinte define uma Person classe que possui dois atributos name e agee cria uma nova instância da Personclasse:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age


john = Person('John', 18)Linguagem de código:  Python  ( python )

Como ageé o atributo de instância da Personclasse, você pode atribuir a ele um novo valor como este:

john.age = 19Linguagem de código:  Python  ( python )

A seguinte atribuição também é tecnicamente válida:

john.age = -1Linguagem de código:  Python  ( python )

No entanto, a idade está semanticamente incorreta.

Para garantir que a idade não seja zero ou negativa, você usa a ifinstrução para adicionar um cheque da seguinte forma:

age = -1
if age <= 0:
    raise ValueError('The age must be positive')
else:
    john.age = ageLinguagem de código:  Python  ( python )

E você precisa fazer isso toda vez que quiser atribuir um valor ao ageatributo. Isso é repetitivo e difícil de manter.

Para evitar essa repetição, você pode definir um par de métodos chamados getter e setter.

Getter e setter

Os métodos getter e setter fornecem uma interface para acessar um atributo de instância:

  • O getter retorna o valor de um atributo
  • O setter define um novo valor para um atributo

Em nosso exemplo, você pode tornar o ageatributo privado (por convenção) e definir um getter e um setter para manipular o ageatributo.

O seguinte mostra a nova Personclasse com um getter e um setter para o ageatributo:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.set_age(age)

    def set_age(self, age):
        if age <= 0:
            raise ValueError('The age must be positive')
        self._age = age

    def get_age(self):
        return self._ageLinguagem de código:  Python  ( python )

Como funciona.

Na Personclasse, the set_age()é o setter e o get_age()é o getter. Por convenção, o getter e o setter têm os seguintes nomes: get_<attribute>()e set_<attribute>().

No set_age()método, elevamos a ValueErrorse the agefor menor ou igual a zero. Caso contrário, atribuímos o ageargumento ao _ageatributo:

def set_age(self, age):
    if age <= 0:
        raise ValueError('The age must be positive')
    self._age = ageLinguagem de código:  Python  ( python )

O get_age()método retorna o valor do _ageatributo:

def get_age(self):
    return self._ageLinguagem de código:  Python  ( python )

No __init__()método, chamamos o set_age()método setter para inicializar o _ageatributo:

def __init__(self, name, age):
    self.name = name
    self.set_age(age)Linguagem de código:  Python  ( python )

As seguintes tentativas de atribuir um valor inválido ao ageatributo:

john = Person('John', 18)
john.set_age(-19)Linguagem de código:  Python  ( python )

E o Python emitiu um ValueErrorcomo esperado.

ValueError: The age must be positiveLinguagem de código:  Python  ( python )

Este código funciona muito bem. Mas tem um problema de compatibilidade com versões anteriores.

Suponha que você tenha lançado a Personclasse há algum tempo e outros desenvolvedores já a estejam usando. E agora que você adiciona o getter e o setter, todo o código que usa Person não funcionará mais.

Para definir um método getter e setter e ao mesmo tempo obter compatibilidade com versões anteriores, você pode usar a property()classe.

A classe de propriedade Python

A classe de propriedade retorna um propertyobjeto. A property()classe possui a seguinte sintaxe:

property(fget=None, fset=None, fdel=None, doc=None)Linguagem de código:  Python  ( python )

O property()possui os seguintes parâmetros:

  • fgeté uma função para obter o valor do atributo ou o método getter.
  • fseté uma função para definir o valor do atributo ou o método setter.
  • fdelé uma função para excluir o atributo.
  • docé uma doutrina, ou seja, um comentário.

O seguinte usa a property()função para definir a agepropriedade da Personclasse.

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def set_age(self, age):
        if age <= 0:
            raise ValueError('The age must be positive')
        self._age = age

    def get_age(self):
        return self._age

    age = property(fget=get_age, fset=set_age)Linguagem de código:  Python  ( python )

Na Personclasse, criamos um novo objeto de propriedade chamando property()e atribuindo o objeto de propriedade ao atributo age. Observe que ageé um atributo de classe , não um atributo de instância .

O seguinte mostra que the Person.ageé um propertyobjeto:

print(Person.age)Linguagem de código:  Python  ( python )

Saída:

<property object at 0x000001F5F5149180>Linguagem de código:  Python  ( python )

O seguinte cria uma nova instância da Personclasse e acessa o ageatributo:

john = Person('John', 18)Linguagem de código:  Python  ( python )

Armazena john.__dict__os atributos de instância do objeto john. A seguir mostra-se o conteúdo do john.__dict__:

print(john.__dict__)Linguagem de código:  Python  ( python )

Saída:

{'_age': 18, 'name': 'John'}Linguagem de código:  Python  ( python )

Como você pode ver claramente na saída, john.__dict__não possui o ageatributo.

O seguinte atribui um valor ao ageatributo do objeto john:

john.age = 19Linguagem de código:  Python  ( python )

Nesse caso, o Python procura o ageatributo primeiro john.__dict__. Como o Python não encontra o ageatributo no arquivo john.__dict__, ele o encontrará ageno arquivo Person.__dict__.

O Person.__dict__armazena os atributos de classe da classe Person. A seguir mostra-se o conteúdo do Person.__dict__:

pprint(Person.__dict__)Linguagem de código:  Python  ( python )

Saída:

mappingproxy({'__dict__': <attribute '__dict__' of 'Person' objects>,
              '__doc__': None,
              '__init__': <function Person.__init__ at 0x000002242F5B2670>,
              '__module__': '__main__',
              '__weakref__': <attribute '__weakref__' of 'Person' objects>,
              'age': <property object at 0x000002242EE39180>,
              'get_age': <function Person.get_age at 0x000002242F5B2790>,
              'set_age': <function Person.set_age at 0x000002242F5B2700>})Linguagem de código:  Python  ( python )

Como o Python encontra o ageatributo no Person.__dict__, ele chamará o ageobjeto de propriedade.

Ao atribuir um valor ao ageobjeto:

john.age = 19Linguagem de código:  Python  ( python )

Python chamará a função atribuída ao fsetargumento, que é o set_age().

Da mesma forma, quando você lê o ageobjeto de propriedade, o Python executará a função atribuída ao fgetargumento, que é o get_age()método.

Ao usar a property()classe, podemos adicionar uma propriedade a uma classe enquanto mantemos a compatibilidade com versões anteriores. Na prática, você definirá primeiro os atributos. Posteriormente, você poderá adicionar a propriedade à classe, se necessário.

Juntando tudo.

from pprint import pprint


class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def set_age(self, age):
        if age <= 0:
            raise ValueError('The age must be positive')
        self._age = age

    def get_age(self):
        return self._age

    age = property(fget=get_age, fset=set_age)


print(Person.age)

john = Person('John', 18)
pprint(john.__dict__)

john.age = 19
pprint(Person.__dict__)Linguagem de código:  Python  ( python )

Resumo

  • Use a classe Python property()para definir uma propriedade para uma classe.

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *