Подтвердить что ты не робот

Определите, является ли данный атрибут класса свойством или нет, объект 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)

Я должен знать также, если атрибут является свойством. Я уверен, что есть способ узнать это. Все предложения будут оценены.

4b9b3361

Ответ 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__() для типа. Но проблема с этим подходом заключается в том, что все функции и методы сами являются дескрипторами, и поэтому они будут пойманы этой проверкой. Быстро становится глупо пытаться найти все исключения.