
Атрибуты объекта в Python – это именованные поля (данные, функции), присущие данному объекту (экземпляру, классу).
Самый простой доступ к атрибутам – через точку:
class Foo:Если мы обратимся к атрибуту, которого нет, то получим ошибку AttributeError. Мы можем переопределить это поведение путем реализации магических методов
def __init__(self):
self.x = 88 # установка значения атрибута
f = Foo()
print(f.x) # доступ к атрибуту через точку
__getattr__
или __getattribute__
.__getattr__
вызывается, если атрибут не найден обычным способом (не был задан ранее через точку, функцию setattr
, или через __dict__
). Если атрибут найден, то __getattr__
НЕ вызывается.📎 Пример. Возвращаем -1 для любого несуществующего атрибута.
class Test:Метод
def __getattr__(self, item):
print(f'__getattr__({item})')
return -1
t = Test()
# зададим x и y
t.x = 10
setattr(t, 'y', 33)
print(t.x) # 10
print(t.y) # 33
print(t.z) # __getattr__(z) -1
__getattribute__
вызывается, когда мы пытаемся получить любой атрибут, не зависимо от того, есть он или нет. Этот метод, вызывается прежде __getattr__
. Он немного хитрее. Если __getattribute__
кидает AttributeError
, то будет вызвана __getattr__
. 📎 Пример. Мы можем запретить чтение каких-то атрибутов:
class Test:⚠️ Внимание! В
def __getattr__(self, item):
print(f'__getattr__({item})')
return -1
def __getattribute__(self, item):
print(f'__getattribute__({item})')
if item == 'y': # запретим получать y
raise AttributeError
return super().__getattribute__(item)
# зададим x и y
t = Test()
t.x = 10
t.y = 20
print(t.x) # __getattribute__(x) 10
print(t.y) # __getattribute__(y) __getattr__(y) -1
print(t.z) # __getattribute__(z) __getattr__(z) -1
__getattribute__
мы можем вызвать super().__getattribute__(item)
или object.__getattribute__(self, item)
, что посути тоже самое, но не слудует делать return self.__dict__[item]
или return self.__getattribute__(item)
или return getattr(self, item)
, так как это приведет к бесконечной рекурсии.💡 Также есть магический метод
__setattr__(self, key, value)
, вызываемый при obj.key = value
или setattr(obj, 'key', value)
. У него нет более длинно-названного брата-близнеца.Для полноты картины еще есть встроенная функция
getattr(object, name[, default])
. Вызов getattr(x, 'y')
аналогичен обращению через точку: x.y
В первом случае 'y'
– это строка, что позволяет нам динамически получать атрибуты объектов, в отличие от точки, которая требует фиксированного имени на этапе написания кода. В случае, если атрибут недоступен мы получим AttributeError
при незаданном default
или получим default
(без возникновения ошибки), если default был задан третьим аргументом.