Estou interessado em como usar @property
em Python. Eu li os documentos python e o exemplo lá, na minha opinião, é apenas um código de brinquedo:
class C(object):
def __init__(self):
self._x = None
@property
def x(self):
"""I'm the 'x' property."""
return self._x
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x
Não sei que benefícios posso obter ao envolver o _x
preenchido com o decorador da propriedade. Por que não apenas implementar como:
class C(object):
def __init__(self):
self.x = None
Eu acho que o recurso de propriedade pode ser útil em algumas situações. Mas quando? Alguém poderia me dar alguns exemplos do mundo real?
Obrigado.
python
oop
properties
python-decorators
xiao 啸
fonte
fonte
Respostas:
Outros exemplos seriam a validação / filtragem dos atributos do conjunto (forçando-os a ficar dentro dos limites ou aceitáveis) e a preguiçosa avaliação de termos complexos ou que mudam rapidamente.
Cálculo complexo oculto atrás de um atributo:
Validação:
fonte
Um caso de uso simples será definir um atributo de instância somente leitura, pois você sabe que levar um nome de variável com um sublinhado
_x
em python geralmente significa que é privado (uso interno), mas às vezes queremos ler o atributo de instância e não escrever para que possamos usarproperty
para isso:fonte
c._x
, se o usuário quiser. Na verdade, o Python não possui atributos privados reais.Dê uma olhada neste artigo para um uso muito prático. Em resumo, ele explica como, em Python, você geralmente pode abandonar o método getter / setter explícito, pois se precisar deles em algum momento, poderá usá-lo
property
para uma implementação perfeita.fonte
Uma coisa para a qual usei é o armazenamento em cache de valores de busca lenta, mas imutáveis, armazenados em um banco de dados. Isso generaliza para qualquer situação em que seus atributos exijam computação ou alguma outra operação longa (por exemplo, verificação de banco de dados, comunicação de rede) que você deseja executar somente sob demanda.
Isso ocorreu em um aplicativo da Web em que qualquer visualização de página específica pode precisar apenas de um atributo específico desse tipo, mas os próprios objetos subjacentes podem ter vários atributos - inicializá-los todos na construção seria um desperdício, e as propriedades permitem que eu seja flexível no qual atributos são preguiçosos e quais não são.
fonte
@cached_property
para isso?Lendo as respostas e comentários, o tema principal parece ser que as respostas parecem estar faltando um exemplo simples, mas útil. Eu incluí um aqui muito simples que demonstra o uso simples do
@property
decorador. É uma classe que permite ao usuário especificar e obter medições de distância usando uma variedade de unidades diferentes,in_feet
ou seja, ouin_metres
.Uso:
fonte
A propriedade é apenas uma abstração em torno de um campo que oferece mais controle sobre as maneiras pelas quais um campo específico pode ser manipulado e fazer cálculos de middleware. Poucos usos que vêm à mente são validação e inicialização prévia e restrição de acesso
fonte
Sim, para o exemplo original publicado, a propriedade funcionará exatamente da mesma maneira que simplesmente ter uma variável de instância 'x'.
Essa é a melhor coisa sobre as propriedades do python. Do lado de fora, eles funcionam exatamente como variáveis de instância! O que permite que você use variáveis de instância de fora da classe.
Isso significa que seu primeiro exemplo pode realmente usar uma variável de instância. Se as coisas mudarem e você decidir alterar sua implementação e uma propriedade for útil, a interface da propriedade ainda será a mesma do código fora da classe. Uma mudança da variável de instância para propriedade não afeta o código fora da classe.
Muitas outras linguagens e cursos de programação instruirão que um programador nunca deve expor variáveis de instância e, em vez disso, usar 'getters' e 'setters' para que qualquer valor seja acessado de fora da classe, mesmo no caso simples, conforme citado na pergunta.
Código fora da classe com muitas linguagens (por exemplo, Java)
E ao implementar a classe, existem muitos 'getters' e 'setters' que fazem exatamente como o seu primeiro exemplo: replicar uma variável de instância simplesmente. Esses getters e setters são necessários porque, se a implementação da classe mudar, todo o código fora da classe precisará ser alterado. Mas as propriedades python permitem que o código fora da classe seja o mesmo que nas variáveis de instância. Portanto, o código fora da classe não precisa ser alterado se você adicionar uma propriedade ou tiver uma variável de instância simples. Portanto, diferente da maioria das linguagens orientadas a objetos, para o seu exemplo simples, você pode usar a variável de instância em vez de 'getters' e 'setters' que realmente não são necessários, com a certeza de que, se você mudar para uma propriedade no futuro, o código usando sua classe não precisa mudar.
Isso significa que você só precisa criar propriedades se houver um comportamento complexo e, para o caso simples muito comum em que, conforme descrito na pergunta, basta uma variável de instância simples, basta usar a variável de instância.
fonte
outro recurso interessante das propriedades sobre o uso de setters e getters, que permitem que você continue usando operadores OP = (por exemplo, + =, - =, * = etc) em seus atributos, mantendo ainda qualquer validação, controle de acesso, armazenamento em cache, etc. os setters e getters forneceriam.
por exemplo, se você escreveu a classe
Person
com um settersetage(newage)
e um gettergetage()
, para aumentar a idade, você teria que escrever:mas se você fez
age
uma propriedade, pode escrever o muito mais limpo:fonte
A resposta curta para sua pergunta é que, no seu exemplo, não há benefício. Você provavelmente deve usar o formulário que não envolve propriedades.
A razão pela qual as propriedades existem é que, se o seu código mudar no futuro, e você precisar repentinamente fazer mais com seus dados: armazenar valores em cache, proteger o acesso, consultar algum recurso externo ... seja qual for, você pode modificar facilmente sua classe para adicionar getters e setters para os dados sem alterar a interface, para que você não precise encontrar em todo lugar do código onde esses dados são acessados e alterá-los também.
fonte
Algo que muitos não percebem a princípio é que você pode criar suas próprias subclasses de propriedade. Isso eu achei muito útil para expor atributos de objeto somente leitura ou atributo que você pode ler e escrever, mas não remover. É também uma excelente maneira de agrupar funcionalidades, como rastrear modificações nos campos de objetos.
fonte
attr = reader('_attr')
linha ou alguma forma de pré-precificaçãoattr = if self.__isValid(value): reader('_attr')
. Sugestões?attr = reader('_attr')
paraattr = accessor('_attr')
. Obrigado