如何防止hasattr检索属性值本身

kor*_*der 7 python hasattr getattr

我有一个使用实现虚拟属性的类__getattr__.属性可能很昂贵,例如执行查询.现在,我正在使用一个库,它在实际获取之前检查我的对象是否具有该属性.

因此,查询执行两次而不是一次.当然,实际执行__getattr__以确定属性是否存在是有意义的.

class C(object):
    def __getattr__(self, name):
        print "I was accessed"
        return 'ok'

c = C()
hasattr(c, 'hello')
Run Code Online (Sandbox Code Playgroud)

有什么方法可以防止这种情况吗?

如果支持Python,__hasattr__那么我可以简单地检查查询是否存在,反对实际运行它.

我可以创建一个缓存,但它很重,因为查询可能有参数.当然,服务器可能会缓存查询本身并将问题最小化,但如果查询返回大量数据,它仍然很重要.

有任何想法吗?

kor*_*der 5

虽然最初我不喜欢猴子补丁的想法,总的来说是一个“坏主意”,但我从 1999 年开始遇到了一个非常巧妙的解决方案!!

http://code.activestate.com/lists/python-list/14972/

def hasattr(o, a, orig_hasattr=hasattr):
    if orig_hasattr(o, "__hasattr__"):
        return o.__hasattr__(a)
    return orig_hasattr(o, a)

__builtins__.hasattr = hasattr
Run Code Online (Sandbox Code Playgroud)

从本质上讲,它创建了__hasattr__对 Python 的支持,这是我最初认为的最佳解决方案。

  • **猴子补丁太棒了。** Rubyists 长期以来一直接受丑陋的猴子。Python 爱好者也应该如此。您对内置的库存 `hasattr()` 的增强以支持 `__hasattr__()` 特殊方法就是一个完美的例子。感谢您让这个优雅的黑客重焕活力! (2认同)

jwi*_*ner 0

我认为这通常可能是一个不好的模式,但您始终可以检查对象的底层__dict__.

In [1]: class A(object):
   ....:     @property
   ....:     def wha(self):
   ....:         print "was accessed"
   ....:

In [2]: A.__dict__
Out[2]:
<dictproxy {'__dict__': <attribute '__dict__' of 'A' objects>,
'__doc__': None,
'__module__': '__main__',
'__weakref__': <attribute '__weakref__' of 'A' objects>,
'wha': <property at 0x10f6b11b0>}>

In [3]: a = A()

In [4]: "wha" in a.__class__.__dict__
Out[4]: True
Run Code Online (Sandbox Code Playgroud)

  • 我认为 OP 正在处理一个调用“hasattr”的第三方库,因此这需要分叉该库。 (2认同)