Я сейчас работаю над проектом, который занимается функциями в абстрактном математическом смысле. Без скучных читателя с подробностями, скажу, что я имел следующую структуру в более ранней версии:Переопределение метода __getattr__ для одного экземпляра класса?
class Foo(Bar):
def __init__(self, a, b):
self.a = a
self.b = b
self.sub_unit = Foo(a, not b)
Конечно, это не совсем изменение, которое я делаю для аргументов Foo
, но достаточно необходимо, чтобы это свойство, если его неоднократно обращали, приводило к бесконечно длинной цепочке Foo
объектов. Очевидно, это приводит к бесконечной рекурсии, когда один экземпляр Foo
. Я решил эту проблему в более ранней версии, удалив последнюю строку init
и добавив следующее в Foo
класс:
def __getattr__(self, attr: str):
if attr == 'sub_unit':
return Foo(self.a, not self.b)
else:
return super().__getattr__(attr)
Это работало довольно хорошо, как я мог рассчитать следующий объект в цепочке по мере необходимости.
Однако, перейдя по коду, я понимаю, что по другим причинам мне нужен экземпляр Bar
, а не его подкласс. Для того, чтобы увидеть, если я мог бы переопределить getattr
для одного экземпляра, я попробовал следующее:
>>> foo = Bar(a=1, b=2) # sub_unit doesn't get set here.
>>> foo.__getattr__ = lambda attr: 'foo'
>>> foo.a
1
>>> foo.__getattr__('a')
'foo'
Что здесь происходит, что я не понимаю? Почему не foo.a
, вызывающий foo.__getattr__('a')
?
Есть ли способ переписать __getattr__
для одного экземпляра, или это мой лучший выбор, чтобы перефакторировать весь код, который у меня есть, который читает sub_unit
и друзей, чтобы назвать их как функции для обработки этого специального случая?
См. Ссылку в другом комментарии - причина, по которой вы не можете ее переопределить, потому что '__getattr__' является специальным методом –
Также' __getattr__' вызывается только для * отсутствующих * атрибутов, то есть тех, которые не найдены обычным способом , Если вы хотите перехватить доступ к * всем * атрибутам, реализуйте '__getattribute__'. – jonrsharpe
Я не был полностью осведомлен об этой тонкости со специальными методами, и, похоже, проблема здесь. В ответ на ваш комментарий, jonrsharpe, я также попытался перезаписать '__getattribute__' (хотя я забыл упомянуть об этом, мой плохой), безрезультатно. Кроме того, если это за отсутствующие аргументы, почему это работает в ситуации на основе классов? В 'init' я устанавливаю' sub_unit = None'. –