我已经把自己变成了一个懒惰的变量类,并在另一个类中使用它。那我怎么才能访问惰性变量类的属性呢?我没有运气就试过__getattr__
。这是一个例子:
class lazyobject(object):
def __init__(self,varname,something='This is the something I want to access'):
self.varname = varname
self.something = something
def __get__(self, obj, type=None):
if obj.__dict__.has_key(self.varname):
print "Already computed %s" % self.varname
return obj.__dict__[self.varname]
else:
print "computing %s" % self.varname
obj.__dict__[self.varname] = "something else"
return obj.__dict__[self.varname]
class lazyobject2(lazyobject):
def __getattr__(self):
return self.something
class dummy(object):
def __init__(self):
setattr(self.__class__, 'lazy', lazyobject('lazy'))
class dummy2(object):
def __init__(self):
setattr(self.__class__, 'lazy', lazyobject2('lazy'))
d1 = dummy()
d2 = dummy2()
try:
print "d1.lazy.something - no getattr: ",d1.lazy.something
except:
print "d2.lazy is already computed - can't get its .something because it's now a string!"
print "d1.lazy - no getattr: ",d1.lazy
try:
print "d2.lazy.something - has getattr: ",d2.lazy.something
except:
print "d2.lazy is already computed - can't get its .something because it's now a string!"
print "d2.lazy - no getattr: ",d2.lazy
打印:
d1.lazy.something - no getattr: computing lazy
d2.lazy is already computed - can't get its .something because it's now a string!
d1.lazy - no getattr: something else
d2.lazy.something - has getattr: computing lazy
d2.lazy is already computed - can't get its .something because it's now a string!
d2.lazy - no getattr: something else
我想要打印的内容:
d1.lazy.something - no getattr: This is the something I want to access
computing lazy
d1.lazy - no getattr: something else
上面的例子是人为的,但我希望能够解决这个问题。另一种表达我的问题的方法是:在访问类属性时如何绕过__get__
方法?
答案 0 :(得分:4)
访问类属性时绕过 __ get __ 的方法是通过类字典查找,而不是使用虚线访问。
使用函数对象很容易演示。例如:
>>> class A(object):
def f(self):
pass
>>> A.f # dotted access calls f.__get__
<unbound method A.f>
>>> vars(A)['f'] # dict access bypasses f.__get__
<function f at 0x101723500>
>>> a = A()
>>> a.f # dotted access calls f.__get__
<bound method A.f of <__main__.A object at 0x10171e810>>
>>> vars(a.__class__)['f'] # dict access bypasses f.__get__
<function f at 0x101723500>
您缺少的另一条信息是继承的 __ get __ 在 __ getattr __ 之前运行,只有在找不到属性时才会运行。此逻辑由 __ getattribute __ 控制,该继承自 object 。因此,如果您想绕过 __ get __ ,您需要在子类中编写新的 __ get __ ,或者通过定义 __ getattribute __ 来更改查找逻辑子类。
要修复 lazyobject2 类,请将 __ getattr __ 替换为:
class lazyobject2(lazyobject):
def __getattribute__(self, key):
# bypass __get__
return object.__getattribute__(self, '__dict__')[key]
总之,用于解决此问题的关键知识是:
描述符逻辑的完整细节可以在this writeup或this presentation中找到。