Проверка наличия у объекта атрибута, не полагаясь на '__getattr__'

Есть ли способ проверить, есть ли у объекта атрибут, который не зависит от __getattr__ или особенности реализации объекта?

Рассмотрим код ниже. я хочуProxy делегировать Wrappedс чем он не может справиться. Код работает, но я бы не хотел тестироватьattr in self.__dict__(Я бы предпочел для этого стабильный интерфейс, без использования причуд реализации). Функцияhasattr здесь не помогает, потому что он направляется к обернутому объекту через __getattr__.

class Wrapped:
    def __init__(self):
        self.a = 0
        self.b = 1

class Proxy:
    def __init__(self, wrapped):
        object.__setattr__(self, 'wrapped', wrapped)
        object.__setattr__(self, 'a', 2)
    def __getattr__(self, attr):
        return getattr(self.wrapped, attr)
    def __setattr__(self, attr, value):
        if attr in self.__dict__:  # <-- Don't like this, hasattr doesn't work
            object.__setattr__(self, attr, value)
        elif hasattr(self.wrapped, attr):
            setattr(self.wrapped, attr, value)
        else: object.__setattr__(self, attr, value)

Тест-драйв:

>>> w = Wrapped()
>>> p = Proxy(w)
>>> p.a
2
>>> p.b
1
>>> p.a = 3
>>> p.a
3
>>> w.a
0
>>> p.b = 4
>>> p.b
4
>>> w.b
4
>>> p.c = 5
>>> p.c
5
>>> w.c
AttributeError: 'Wrapped' object has no attribute 'c'

1 ответ

Решение

Встроенный hasattr() функция

реализуется путем вызова getattr(object, name) и посмотреть, вызывает ли это AttributeError или не.

Модуль проверки имеет getattr_static() метод, который можно использовать для

Получать атрибуты без запуска динамического поиска через протокол дескриптора, __getattr__() или __getattribute__()".

Используя этот метод, вы можете определить hasattr_static() метод аналогичен hasattr(), но звонит inspect.getattr_static(object, name) вместо того getattr(object, name):

import inspect


def hasattr_static(object, name):
    try:
        inspect.getattr_static(object, name)
        return True
    except AttributeError:
        return False

А затем используйте это в __setattr__() метод вашего Proxy класс как проверка:

def __setattr__(self, attr, value):
    if hasattr_static(self, attr):
        object.__setattr__(self, attr, value)
    elif hasattr(self.wrapped, attr):
        setattr(self.wrapped, attr, value)
    else:
        object.__setattr__(self, attr, value)

В качестве альтернативы вы можете использовать dir() функция вместо __dict__ чтобы получить список атрибутов вашего объекта, или используйте inspect.getmembers().

Другие вопросы по тегам