首页 > 解决方案 > 检查对象是否具有属性,而不依赖于 '__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'

标签: python

解决方案


内置hasattr()函数

通过调用getattr(object, name)并查看它是否引发 an来实现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().


推荐阅读