当您尝试使用hasattr()
访问属性时,是否可以使装饰器使属性变得懒惰?我弄清楚如何让它变得懒惰,但是hasattr()
让它过早地进行评估。如,
class lazyattribute:
# Magic.
class A:
@lazyattribute
def bar(self):
print("Computing")
return 5
>>> a = A()
>>> print(a.bar)
'Computing'
5
>>> print(a.bar)
5
>>> b = A()
>>> hasattr(b, 'bar')
'Computing'
5
# Wanted output: 5
答案 0 :(得分:4)
可能很难做到。来自hasattr documentation:
参数是一个对象和一个字符串。如果字符串是对象属性之一的名称,则结果为True,否则返回False。 (这是通过调用getattr(object,name)并查看它是否引发异常来实现的。)
由于属性可能由__getattr__
方法动态生成,因此没有其他方法可靠地检查它们的存在。对于您的特殊情况,也许明确地测试字典就足够了:
any('bar' in d for d in (b.__dict__, b.__class__.__dict__))
答案 1 :(得分:2)
到目前为止,没有人似乎已经解决过,或许最好的办法就是不要使用hasattr()
。相反,去EAFP(更容易请求宽恕而不是许可)。
try:
x = foo.bar
except AttributeError:
# what went in your else-block
...
else:
# what went in your if hasattr(foo, "bar") block
...
这显然不是替代品,你可能需要稍微调整一下,但它可能是“最好的”解决方案(主观上,当然)。
答案 2 :(得分:0)
问题是hasattr
使用getattr
因此,当您使用hasattr
时,您的属性始终会被评估。如果您发布lazyattribute
魔法的代码,希望有人可以建议另一种方法来测试不需要hasattr
或getattr
的属性。请参阅hasattr
的帮助:
>>> help(hasattr)
Help on built-in function hasattr in module __builtin__:
hasattr(...)
hasattr(object, name) -> bool
Return whether the object has an attribute with the given name.
(This is done by calling getattr(object, name) and catching exceptions.)
答案 3 :(得分:0)
我很好奇为什么你需要这样的东西。如果hasattr
最终调用您的“计算功能”,那么就这样吧。你的财产究竟需要多么懒惰?
但是,通过检查调用函数的名称,这是一种相当不切实际的方法。它可能编码得更好一些,但我认为它不应该被认真使用。
import inspect
class lazyattribute(object):
def __init__(self, func):
self.func = func
def __get__(self, obj, kls=None):
if obj is None or inspect.stack()[1][4][0].startswith('hasattr'):
return None
value = self.func(obj)
setattr(obj, self.func.__name__, value)
return value
class Foo(object):
@lazyattribute
def bar(self):
return 42
答案 4 :(得分:-2)
好的修复有点hackish但它包含以下
def hasattr(obj, name):
try:
return obj._hasattr(name) or _hasattr(obj, name)
except:
return _hasattr(obj, name)
通过检查一些填充了所有惰性属性名称的数据结构(即数组)来实现类方法_hasattr(对于你要说的数组:name in lazyAttrArray)
最后以某种方式让你的@lazyattribute装饰器将项添加到某种结构中(比如我们上面提到的数组),然后当你调用_hasattr时,你会看到那个结构