Quero substituir o __getattr__
método em uma classe para fazer algo sofisticado, mas não quero interromper o comportamento padrão.
Qual é a maneira correta de fazer isso?
Quero substituir o __getattr__
método em uma classe para fazer algo sofisticado, mas não quero interromper o comportamento padrão.
Qual é a maneira correta de fazer isso?
Respostas:
A substituição __getattr__
deve estar correta - __getattr__
é chamada apenas como último recurso, ou seja, se não houver atributos na instância que correspondam ao nome. Por exemplo, se você acessar foo.bar
, __getattr__
somente será chamado se foo
não tiver nenhum atributo chamado bar
. Se o atributo for um que você não deseja manipular, aumente AttributeError
:
class Foo(object):
def __getattr__(self, name):
if some_predicate(name):
# ...
else:
# Default behaviour
raise AttributeError
No entanto, ao contrário __getattr__
, __getattribute__
será chamado primeiro (funciona apenas para novas classes de estilo, ou seja, aquelas que herdam do objeto). Nesse caso, você pode preservar o comportamento padrão da seguinte maneira:
class Foo(object):
def __getattribute__(self, name):
if some_predicate(name):
# ...
else:
# Default behaviour
return object.__getattribute__(self, name)
__getattr__
- tem alguma idéia do que fazer? ( AttributeError: 'super' object has no attribute '__getattr__'
)
AttributeError
sem o contexto do atributo nos argumentos da exceção.
class A(object):
def __init__(self):
self.a = 42
def __getattr__(self, attr):
if attr in ["b", "c"]:
return 42
raise AttributeError("%r object has no attribute %r" %
(self.__class__.__name__, attr))
>>> a = A()
>>> a.a
42
>>> a.b
42
>>> a.missing
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 8, in __getattr__
AttributeError: 'A' object has no attribute 'missing'
>>> hasattr(a, "b")
True
>>> hasattr(a, "missing")
False
self.__class__.__name__
deve ser usado em vez de self.__class__
no caso das substituições de classe__repr__
Para estender a resposta do Michael, se você deseja manter o comportamento padrão usando __getattr__
, é possível:
class Foo(object):
def __getattr__(self, name):
if name == 'something':
return 42
# Default behaviour
return self.__getattribute__(name)
Agora a mensagem de exceção é mais descritiva:
>>> foo.something
42
>>> foo.error
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in __getattr__
AttributeError: 'Foo' object has no attribute 'error'
__getattr__
e __getattribute__
?