Я хочу переопределить __getattr__
метод класса, чтобы сделать что-то необычное, но я не хочу нарушать поведение по умолчанию.
Какой правильный способ сделать это?
Я хочу переопределить __getattr__
метод класса, чтобы сделать что-то необычное, но я не хочу нарушать поведение по умолчанию.
Какой правильный способ сделать это?
Ответы:
Переопределение __getattr__
должно быть в порядке - __getattr__
вызывается только в крайнем случае, т. Е. Если в экземпляре нет атрибутов, соответствующих имени. Например, если вы обращаетесь foo.bar
, то __getattr__
будет вызываться, только если foo
не было вызвано ни одного атрибута bar
. Если атрибут тот, который вы не хотите обрабатывать, поднимите AttributeError
:
class Foo(object):
def __getattr__(self, name):
if some_predicate(name):
# ...
else:
# Default behaviour
raise AttributeError
Однако, в отличие от __getattr__
, __getattribute__
будет вызываться первым (работает только для новых стилевых классов, то есть тех, которые наследуются от объекта). В этом случае вы можете сохранить поведение по умолчанию следующим образом:
class Foo(object):
def __getattribute__(self, name):
if some_predicate(name):
# ...
else:
# Default behaviour
return object.__getattribute__(self, name)
Смотрите документы Python для получения дополнительной информации .
__getattr__
- есть идеи, что делать? ( AttributeError: 'super' object has no attribute '__getattr__'
)
AttributeError
контекст без атрибута в аргументах исключения.
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__
следует использовать, а не self.__class__
в случае переопределения класса__repr__
Чтобы расширить ответ Михаэля, если вы хотите сохранить поведение по умолчанию, используя его __getattr__
, вы можете сделать это так:
class Foo(object):
def __getattr__(self, name):
if name == 'something':
return 42
# Default behaviour
return self.__getattribute__(name)
Теперь сообщение об исключении более наглядно:
>>> 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__
и __getattribute__
?