Я хочу змінити __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__
?