Я хочу переопределить доступ к одной переменной в классе, но вернуть все остальные в обычном режиме. Как мне это сделать __getattribute__
?
Я пробовал следующее (что также должно иллюстрировать то, что я пытаюсь сделать), но получаю ошибку рекурсии:
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)
в Python 3.На самом деле, я считаю, что вы хотите использовать
__getattr__
вместо этого специальный метод.Цитата из документов Python:
Примечание: чтобы это работало, у экземпляра не должно быть
test
атрибута, поэтому строкуself.test=20
следует удалить.источник
__getattr__
fortest
было бы бесполезным, поскольку он всегда находил бы его «в обычных местах».Справочник по языку Python:
Смысл:
Вы вызываете атрибут с именем
__dict__
. Поскольку это атрибут, он вызывается__getattribute__
в поисках того,__dict__
какие вызовы__getattribute__
вызывают ... yada yada yadaИспользование базовых классов
__getattribute__
помогает найти настоящий атрибут.источник
Вы уверены, что хотите использовать
__getattribute__
? Чего вы на самом деле пытаетесь достичь?Самый простой способ сделать то, о чем вы просите, - это:
или:
Изменить: обратите внимание, что экземпляр
D
будет иметь разные значенияtest
в каждом случае. В первом случаеd.test
будет 20, во втором - 0. Я оставлю это вам решать, почему.Edit2: Грег указал, что пример 2 завершится ошибкой, потому что свойство доступно только для чтения, и
__init__
метод попытался установить его на 20. Более полный пример для этого:Очевидно, что как класс это почти полностью бесполезно, но дает вам идею, от которой нужно двигаться дальше.
источник
Вот более надежная версия:
Он вызывает метод __ getattribute __ из родительского класса, в конечном итоге возвращаясь к объекту. __ getattribute __, если другие предки не отменяют его.
источник
Он вызывается перед обычным поиском по точкам. Если он повышается
AttributeError
, мы делаем колл__getattr__
.Использование этого метода довольно редко. В стандартной библиотеке всего два определения:
Лучшая практика
Правильный способ программного управления доступом к одному атрибуту - использовать
property
. КлассD
должен быть записан следующим образом (с установщиком и удалителем, необязательно, для воспроизведения предполагаемого предполагаемого поведения):И использование:
Свойство - это дескриптор данных, поэтому это первое, что нужно искать в обычном алгоритме поиска по точкам.
Варианты для
__getattribute__
У вас есть несколько вариантов, если вам абсолютно необходимо реализовать поиск для каждого атрибута через
__getattribute__
.AttributeError
, вызывая__getattr__
вызов (если реализовано)super
для вызова родительской (вероятноobject
) реализации__getattr__
Например:
То, что вы изначально хотели.
И этот пример показывает, как вы могли бы сделать то, что изначально хотели:
И будет вести себя так:
Обзор кода
Ваш код с комментариями. У вас есть точечный поиск по себе
__getattribute__
. Вот почему вы получаете ошибку рекурсии. Вы можете проверить, указано ли имя,"__dict__"
и использовать егоsuper
для обходного пути, но это не касается__slots__
. Я оставлю это читателю в качестве упражнения.источник