Функция getattr в Python: назначение, пример использования

Встроенная функция getattr языка программирования Python позволяет получать значение атрибута объекта, когда этот атрибут "упакован" в строку и применять его к объекту в нотации через точку невозможно. Пусть имеется такой класс:

class Square:
    def __init__(self, width, height, units):
        self.a = width
        self.b = height
        self.units = units

    def area(self):
        return self.a * self.b

    def perimeter(self):
        return self.a * 2 + self.b * 2

    def __str__(self):
        return f'{__class__.__name__}: ' \
               f'{self.a} x {self.b} ({self.units})'

Вызов метода при условии, что мы не знаем, какой из них потребуется, может выглядеть так:

from square import Square

figure = Square(8.5, 14.1, 'cm')
print(figure)  # Square: 8.5 x 14.1 (cm)

q = input('Аrea or perimeter: ').lower()

if q == 'area':
    print(figure.area())  # 119.85
elif q == 'perimeter':
    print(figure.perimeter())  # 45.2

С функцией getattr задача решается проще:

from square import Square

figure = Square(8.5, 14.1, 'cm')
print(figure)

q = input('Аrea or perimeter: ').lower()

print(getattr(figure, q, lambda: "Error")())

Третий аргумент getattr не обязательный. В простом случае функция вызывается как getattr(объект, атрибут_в_виде_строки). Однако, если указанного атрибута у объекта не окажется, произойдет выброс исключения AttributeError. Если требуется избежать подобного, с помощью третьего аргумента подставляется значение по умолчанию. Это не значит, что у объекта появляется новый атрибут. Это значит, что функция getattr просто вернет какое-то значение.

В примере выше обратите внимание на скобки после вызова getattr. Функция getattr возвращает значение атрибута. Если мы напишем getattr(figure, 'a'), то получим 8.5. Но в случае атрибутов-методов это работает не так: мы получаем объект-метод, а не результат его вызова. Для вызова необходимы скобки и, если требуется, передача в них аргументов:

from square import Square

figure = Square(8.5, 14.1, 'cm')

side1 = getattr(figure, 'a')
print(side1)  # 8.5

side2 = getattr(figure, 'b', 0)
print(side2)  # 14.1

side3 = getattr(figure, 'c', 0)
print(side3)  # 0


P = getattr(figure, 'perimeter')

print(P)
# <bound method Square.perimeter of <square.Square object at 0x7ff287e63fd0>>

print(figure.perimeter)
# <bound method Square.perimeter of <square.Square object at 0x7ff287e63fd0>>


print(P())  # 45.2
print(figure.perimeter())  # 45.2

Также с помощью getattr можно проверять наличие определенного атрибута у объекта.

m = input('Метод списка: ')

try:
    get_m = getattr(list, m)
    help(get_m)
except AttributeError:
    print("Нет такого метода")