Получите все, что есть у экземпляра, что бы ни случилось

getattr() — одна из самых крутых встроенных функций в Python. Он принимает три аргумента:

  • объект
  • имя атрибута объекта, но в строковом формате
  • значение по умолчанию (это не обязательно)

Он возвращает:

  • значение этого атрибута

Давайте определим класс Book в качестве примера

и создайте экземпляр:

book = Book("Moby Dick", "Herman Melville", 1851)

Теперь мы можем получить доступ к атрибутам экземпляра book. Нет ничего более естественного, чем использовать для этого запись через точку.

>>> book.title
'Moby Dick'

Мы можем сделать то же самое, используя функцию getattr():

>>> getattr(book, 'title')
'Moby Dick'

Итак, book.title и getattr(book, 'title') — это абсолютноодно и то же! Они одинаковые, за исключением:

  • Атрибут title передается в виде строки ('title') в функцию getattr().
  • Вы можете передать значение по умолчанию в качестве аргумента.

Например:

>>> book.language

вызовет ошибку, потому что класс Book не имеет такого атрибута.

Traceback (most recent call last):
  File "<input>", line 1, in <module>
AttributeError: 'Book' object has no attribute 'language'

Вместо этого мы можем сделать:

>>> getattr(book, 'language', 'English')
'English'

Имейте в виду, что без значения по умолчанию это также вызывает ошибку.

>>> getattr(book, 'language')

Выход:

Traceback (most recent call last):
  File "<input>", line 1, in <module>
AttributeError: 'Book' object has no attribute 'language'

Потому что getattr() и запись через точку эквивалентны, если вы не передаете значение по умолчанию.

Если вы предприимчивы (как и я), вам может быть интересно, возможно ли также получить доступ к методу класса. Давайте посмотрим:

>>> getattr(book, 'describe')

Выход:

<bound method Book.describe of <__main__.Book object at 0x103cd7a0>>

Он возвращает метод describe(), не вызывая его. Помните, что функции также являются объектами, и вы можете назначать их переменным. Таким образом, мы можем либо вызвать его напрямую, добавив круглые скобки в конец

>>> getattr(book, 'describe')()
Moby Dick (1851) was published by Herman Melville.

или мы можем сохранить это значение и вызвать его позже.

>>> desc = getattr(book, 'describe')
>>> desc()
Moby Dick (1851) was published by Herman Melville.

Все идет нормально! Вы можете спросить: не странно ли обращаться к атрибуту, потому что мы уже знаем содержимое класса?

Фактически, getattr() пригодится, если вам нужно решить, какой атрибут будет использоваться, пока программа уже запущена. Например, в веб-приложениях может потребоваться динамическое получение атрибутов на основе поступающего запроса. Или вы получаете имя атрибута от пользователей.

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

attr = input()
print(getattr(book, attr))

Допустим, пользователь вводит pub_year в качестве ввода. Тогда вывод:

1851

Приведенный выше код эквивалентен:

attr = input()
if attr == 'title':
    print(book.title)
elif attr == 'author':
    print(book.author)
elif attr == 'pub_year':
    print(book.pub_year)

Это действительно сокращает наш код, верно?

Давайте посмотрим на другой пример. Теперь вы получаете разрешенные HTTP-методы динамически из API и отправляете соответствующий HTTP-запрос через requests lib на основе разрешенного метода (POST или PUT). Конечно, вам нужно использовать getattr().

что эквивалентно:

Как видите, getattr() делает нашу жизнь проще и уменьшает количество повторений кода.

Если вы находитесь в похожей ситуации и ваш объект имеет много атрибутов, использование этой функции избавит вас от написания множества предложений if-elif.

Если вы действительно собираетесь писать длинные строки кода из-за того, что не используете getattr(), и думаете, что вам это удалось, копируя и вставляя снова и снова. Ну… у меня для тебя плохие новости. Большинство ошибок программирования вызвано операциями копирования-вставки. Так что эта функция еще и защищает вас от возможных ошибок при копировании-вставке.

Таким образом, если вы знаете имя атрибута, всегда используйте запись через точку. Однако, когда имя атрибута задается как поток программы, следует использовать getattr().

Спасибо, что прочитали мою статью. Если вам понравилось то, что вы прочитали, ознакомьтесь с этой историей ниже:



Не используйте «или для проверки нескольких условий в Python
Есть более сложное решение!betterprogramming.pub»