Определите, является ли данный атрибут класса свойством или нет, объект Python
Все в заголовке. Ниже приведен пример:
class A(object):
my_var = 5
def my_method(self, drink='beer'):
return 'I like %s' % drink
@property
def my_property(self):
return 'I do not drink coffee'
Я создаю экземпляр объекта A, и я хочу знать тип каждого атрибута и если он является вызываемым. Для этого я использую dir()
.
obj = A()
for attr in dir(obj):
print 'Type: %s' % type(obj)
print 'Is callable: %s' % callable(attr)
Я должен знать также, если атрибут является свойством. Я уверен, что есть способ узнать это.
Все предложения будут оценены.
Ответы
Ответ 1
Вам нужно взглянуть на класс (это в общем случае на дескрипторы), который для объектов можно найти с помощью атрибута class или с помощью функции типа:
>>> obj.__class__.my_property
<property object at 0xb74bd16c>
или
>>> type(obj).my_property
<property object at 0xb720b93c>
Они приводят к тому же "объекту свойства", как если бы вы непосредственно проверяли атрибут класса (подразумевая, что вы знаете имя класса в своем коде, а не проверяете его динамически, как вы, вероятно, должны это делать):
>>> A.my_property
<property object at 0xb7312345>
Итак, чтобы проверить, является ли конкретный атрибут объекта свойством, это было бы одним из решений:
>>> isinstance(type(obj).my_property, property)
True
Ответ 2
Однажды я задал аналогичный вопрос. Беда, с которой вы столкнетесь, конечно, заключается в том, что вы не можете получить доступ к свойству через экземпляр, чтобы определить его тип, не вызывая геттер, который получает вам тип того, что возвращает геттер. Таким образом, вам нужно получить доступ к свойству через свой класс, а не через экземпляр.
property
уже является типом, поэтому вы можете просто сравнить его с этим. (У меня изначально был некоторый лишний код, который получил тип свойства из класса, у которого было свойство. Я думал, что это необходимо из-за опечатки, когда я тестировал вещи.)
obj_type = type(obj)
for attr in dir(obj):
if isinstance(getattr(type(obj), attr, None), property):
print attr, "is a property"
Не беспокойтесь о наличии атрибута экземпляра с тем же именем. Он игнорируется при поиске атрибутов, если в классе есть дескриптор данных с таким же именем (property
- дескриптор данных).
Конечно, любой класс может быть дескриптором данных, а не только property
, поэтому в теории вы действительно хотите проверить атрибуты __get__()
и/или __set__()
и/или __delete__()
для типа. Но проблема с этим подходом заключается в том, что все функции и методы сами являются дескрипторами, и поэтому они будут пойманы этой проверкой. Быстро становится глупо пытаться найти все исключения.