Получите все, что есть у экземпляра, что бы ни случилось
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»