Объекты в Python могут иметь атрибуты - атрибуты данных и функции для работы с ними (методы). Собственно, у каждого объекта есть встроенные атрибуты.
Например, у вас есть объект person
, у которого есть несколько атрибутов: name
, gender
и т. Д.
Вы получаете доступ к этим атрибутам (будь то методы или объекты данных), обычно записывая: person.name
, person.gender
, person.the_method()
и т. Д.
Но что, если вы не знаете имя атрибута во время написания программы? Например, имя атрибута хранится в переменной attr_name
.
if
attr_name = 'gender'
тогда вместо того, чтобы писать
gender = person.gender
ты можешь написать
gender = getattr(person, attr_name)
Немного практики:
Python 3.4.0 (default, Apr 11 2014, 13:05:11)
>>> class Person():
... name = 'Victor'
... def say(self, what):
... print(self.name, what)
...
>>> getattr(Person, 'name')
'Victor'
>>> attr_name = 'name'
>>> person = Person()
>>> getattr(person, attr_name)
'Victor'
>>> getattr(person, 'say')('Hello')
Victor Hello
getattr
вызовет AttributeError
, если атрибут с данным именем не существует в объект:
>>> getattr(person, 'age')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Person' object has no attribute 'age'
Но вы можете передать значение по умолчанию в качестве третьего аргумента, который будет возвращен, если такой атрибут не существует:
>>> getattr(person, 'age', 0)
0
Вы можете использовать getattr
вместе с dir
для перебора всех имен атрибутов и получения их значения:
>>> dir(1000)
['__abs__', '__add__', ..., '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']
>>> obj = 1000
>>> for attr_name in dir(obj):
... attr_value = getattr(obj, attr_name)
... print(attr_name, attr_value, callable(attr_value))
...
__abs__ <method-wrapper '__abs__' of int object at 0x7f4e927c2f90> True
...
bit_length <built-in method bit_length of int object at 0x7f4e927c2f90> True
...
>>> getattr(1000, 'bit_length')()
10
На практике это можно использовать для поиска всех методов, имена которых начинаются с test
и позвоните им.
Подобно getattr
, есть _ 21_, который позволяет вам установить атрибут объекта, имеющего его имя:
>>> setattr(person, 'name', 'Andrew')
>>> person.name # accessing instance attribute
'Andrew'
>>> Person.name # accessing class attribute
'Victor'
>>>
02.11.2010
getattr
с двумя параметрами (что эквивалентно), а во втором маркере упоминается getattr с 3 параметрами. Даже если бы это было несистематично, я бы, наверное, оставил это, акцент важнее. 02.07.2020o.x
эквивалентноo['x']
. Но второе выражение можно использовать с любымиo[some_string]
, которые могут быть определены во время выполнения (например, из пользовательского ввода или проверки объекта), в то время как в первом выраженииx
фиксировано. 21.08.2020object.x
16.09.2020.
или-
(как я сейчас имею дело).getattr(obj, 'some.val')
будет работать там, где obj.some.val не будет. 26.10.2020setattr
использовался ранее, либо из-за прямого взлома__dict__
объекта. Это может происходить неявно при использованииtypes.SimpleNamespace
илиargparse.Namespace
. 28.03.2021