Resumo : neste tutorial, você aprenderá sobre a property
classe 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 age
e cria uma nova instância da Person
classe:
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 Person
classe, você pode atribuir a ele um novo valor como este:
john.age = 19
Linguagem de código: Python ( python )
A seguinte atribuição também é tecnicamente válida:
john.age = -1
Linguagem 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 if
instrução para adicionar um cheque da seguinte forma:
age = -1
if age <= 0:
raise ValueError('The age must be positive')
else:
john.age = age
Linguagem de código: Python ( python )
E você precisa fazer isso toda vez que quiser atribuir um valor ao age
atributo. 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 age
atributo privado (por convenção) e definir um getter e um setter para manipular o age
atributo.
O seguinte mostra a nova Person
classe com um getter e um setter para o age
atributo:
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._age
Linguagem de código: Python ( python )
Como funciona.
Na Person
classe, 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 ValueError
se the age
for menor ou igual a zero. Caso contrário, atribuímos o age
argumento ao _age
atributo:
def set_age(self, age):
if age <= 0:
raise ValueError('The age must be positive')
self._age = age
Linguagem de código: Python ( python )
O get_age()
método retorna o valor do _age
atributo:
def get_age(self):
return self._age
Linguagem de código: Python ( python )
No __init__()
método, chamamos o set_age()
método setter para inicializar o _age
atributo:
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 age
atributo:
john = Person('John', 18)
john.set_age(-19)
Linguagem de código: Python ( python )
E o Python emitiu um ValueError
como esperado.
ValueError: The age must be positive
Linguagem 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 Person
classe 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 property
objeto. 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 age
propriedade da Person
classe.
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 Person
classe, 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 property
objeto:
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 Person
classe e acessa o age
atributo:
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 age
atributo.
O seguinte atribui um valor ao age
atributo do objeto john:
john.age = 19
Linguagem de código: Python ( python )
Nesse caso, o Python procura o age
atributo primeiro john.__dict__
. Como o Python não encontra o age
atributo no arquivo john.__dict__
, ele o encontrará age
no 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 age
atributo no Person.__dict__
, ele chamará o age
objeto de propriedade.
Ao atribuir um valor ao age
objeto:
john.age = 19
Linguagem de código: Python ( python )
Python chamará a função atribuída ao fset
argumento, que é o set_age()
.
Da mesma forma, quando você lê o age
objeto de propriedade, o Python executará a função atribuída ao fget
argumento, 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.