Quero substituir o acesso a uma variável em uma classe, mas retornar todas as outras normalmente. Como faço para fazer isso com __getattribute__
?
Tentei o seguinte (que também deve ilustrar o que estou tentando fazer), mas recebo um erro de recursão:
class D(object):
def __init__(self):
self.test=20
self.test2=21
def __getattribute__(self,name):
if name=='test':
return 0.
else:
return self.__dict__[name]
>>> print D().test
0.0
>>> print D().test2
...
RuntimeError: maximum recursion depth exceeded in cmp
super(D, self).__getattribute__(name)
super().__getattribute__(name)
em Python 3.Na verdade, acredito que você deseja usar o
__getattr__
método especial.Citação dos documentos Python:
Nota: para que isso funcione, a instância não deve ter um
test
atributo, então a linhaself.test=20
deve ser removida.fonte
__getattr__
portest
seria inútil, uma vez que sempre o encontraria "nos lugares de costume".Referência da linguagem Python:
Significado:
Você está chamando por um atributo chamado
__dict__
. Por ser um atributo,__getattribute__
é chamado em busca de__dict__
quais chamadas__getattribute__
que chama ... blá blá bláUsar as classes básicas
__getattribute__
ajuda a encontrar o atributo real.fonte
Tem certeza que deseja usar
__getattribute__
? O que você está realmente tentando alcançar?A maneira mais fácil de fazer o que você pede é:
ou:
Edit: Observe que uma instância de
D
teria valores diferentes detest
em cada caso. No primeiro casod.test
seria 20, no segundo seria 0. Vou deixar para você descobrir o porquê.Edit2: Greg apontou que o exemplo 2 falhará porque a propriedade é somente leitura e o
__init__
método tentou defini-la como 20. Um exemplo mais completo para isso seria:Obviamente, como classe, isso é quase totalmente inútil, mas dá uma ideia para seguir em frente.
fonte
Aqui está uma versão mais confiável:
Ele chama __ getAttribute __ método da classe pai, acabou caindo de volta para objeto. Método __ getattribute __ se outros ancestrais não o substituírem.
fonte
É chamado antes da pesquisa pontilhada normal. Se aumentar
AttributeError
, então pagamos__getattr__
.O uso deste método é bastante raro. Existem apenas duas definições na biblioteca padrão:
Melhor prática
A maneira correta de controlar programaticamente o acesso a um único atributo é com
property
. A classeD
deve ser escrita da seguinte forma (com o setter e o deleter opcionalmente para replicar o comportamento pretendido aparente):E uso:
Uma propriedade é um descritor de dados, portanto, é a primeira coisa procurada no algoritmo normal de pesquisa pontilhada.
Opções para
__getattribute__
Você terá várias opções se for absolutamente necessário implementar a pesquisa para cada atributo via
__getattribute__
.AttributeError
, fazendo__getattr__
com que seja chamado (se implementado)super
para chamar aobject
implementação pai (provavelmente )__getattr__
Por exemplo:
O que você queria originalmente.
E este exemplo mostra como você pode fazer o que queria originalmente:
E vai se comportar assim:
Revisão de código
Seu código com comentários. Você tem uma pesquisa pontilhada sobre si mesmo em
__getattribute__
. É por isso que você obtém um erro de recursão. Você pode verificar se o nome é"__dict__"
e usarsuper
para contornar o problema, mas isso não cobre__slots__
. Vou deixar isso como um exercício para o leitor.fonte