gpt4 book ai didi

python - 如何访问惰性变量类的属性?

转载 作者:太空宇宙 更新时间:2023-11-04 10:58:11 25 4
gpt4 key购买 nike

我已经为自己创建了一个惰性变量类,并在另一个类中使用了它。我怎样才能访问惰性变量类的属性?我尝试过 __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__ 方法?

最佳答案

在访问类属性时绕过 __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__ 之前运行,后者仅在未找到属性时运行。此逻辑由继承自 object__getattribute__ 控制。因此,如果您想绕过 __get__,您需要在子类中编写一个新的 __get__ 或通过在中定义 __getattribute__ 来更改查找逻辑子类。

要修复 lazyobject2 类,请将 __getattr__ 替换为:

class lazyobject2(lazyobject):

def __getattribute__(self, key):
# bypass __get__
return object.__getattribute__(self, '__dict__')[key]

综上所述,解决这个问题的关键知识点是:

  • object.__getattribute__ 控制查找逻辑。
  • 它首先寻找 __get__ 无论是在当前类中定义还是继承。
  • 仅当未找到任何内容时,它才会尝试调用 object.__getattr__
  • 以上三个步骤仅适用于点式查找。
  • 可以通过__dict__ vars() 直接访问字典来绕过这些步骤。

描述符逻辑的完整细节可以在 this writeup 中找到。或在 this presentation .

关于python - 如何访问惰性变量类的属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8045069/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com