【问题标题】:Cheking if an object has an attribute, without relying on '__getattr__'检查对象是否具有属性,而不依赖于 '__getattr__'
【发布时间】:2019-10-05 10:53:46
【问题描述】:

有没有办法检查对象是否具有不依赖于__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


    【解决方案1】:

    内置hasattr()函数

    通过调用getattr(object, name) 并查看它是否引发AttributeError 来实现。

    inspect模块有getattr_static()方法,可以用来

    通过描述符协议__getattr__()__getattribute__()"在不触发动态查找的情况下检索属性。

    使用此方法,您可以定义类似于hasattr()hasattr_static() 方法,但调用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
    

    然后在 Proxy 类的 __setattr__() 方法中使用它作为检查:

    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()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-26
      • 2014-05-08
      • 1970-01-01
      • 2013-07-03
      • 2017-10-09
      • 2012-02-02
      • 2021-03-12
      • 1970-01-01
      相关资源
      最近更新 更多