繁体   English   中英

python中的__getattr__方法

[英]__getattr__ method in python

我今天遇到这个代码,看起来很混乱

class ClassOne:
    def __init__(self,some_object):
        self.not_important_attribute=some_object   
class ClassTwo:
    def __init__(self,some_object):
        self.tmp=ClassOne(some_object)
    def __getattr__(self,attr):
        return getattr(self.tmp,attr)
a=ClassTwo('not_important_string')
print(getattr(a,'undefined_attribute',3))

当我们在最后一行使用getattr时,我们在SubClass触发__getattr__方法,然后委托给getattr(self.tmp,attr)函数,如果该属性未定义且没有给出默认值,则会引发异常。 但是最后一行的值3如何仍然经历所有过程,并最终返回到getattr(a,'undefined_attribute',3)函数? 因为当我们委托getattr(self.tmp,attr)时我们没有用于默认值的插槽,这怎么可能?

在你的情况下

getattr(self.tmp,attr)

引发AttributeError,如果getattr有第三个参数(默认值),则返回默认值而不是引发AttributeError

一步一步为什么显示3值:

超类有一个属性not_important_attribute ,它在调用构造函数时设置

class ClassOne:
    def __init__(self,some_object):
        self.not_important_attribute=some_object   

这里,在ClassTwo构造ClassTwo ,您创建一个ClassOne实例并将其保存到tmp变量中。 这意味着当你覆盖__getattr__你将要求ClassOne的属性值

print(getattr(a,'not_important_attribute',3))
not_important_string # founds the method
print(getattr(a,'any',3))
3 #doesn't found method, returns default

这是直接做的:

b = ClassOne("not_important_string")
print(getattr(b,'not_important_attribute',3))
not_important_string # founds the method
print(getattr(b,'any',3))
3 # doesn't found method, returns default  

当调用getattr(a,'undefined_attribute',3)您调用标准的python getattr函数并将其传递给默认值。 这实际上将您的自定义getattr包装在ClassTwo中。 我们可以看到通过稍微修改getattr

   def __getattr__(self, attr, *args, **kwargs):
        print(args)  # -> empty
        print(kwargs)  # -> empty
        return getattr(self.tmp, attr)

实际上,您可以使用print(a.__getattr__('undefined_attribute', 3))绕过包装并直接从ClassTwo调用getattr 此方法会引发异常。

所以基本上getattr(a,'undefined_attribute',3)是内部从ClassTwo调用自定义getattr的标准python方法。

class ClassTwo:
...
    def __getattr__(self,attr):
        return getattr(self.tmp,attr)

getattr(a,'undefined_attribute',3)方法是一个调用__getattribute__的包装器,如果__getattribute__失败,它将调用__getattr__ 它通过处理异常AttributeError来实现。 在你的情况下, getattr(a,'undefined_attribute',3)调用ClassTwo.__getattr__

看来你认为当它到达return getattr(self.tmp,attr) ,它会抛出错误或返回某种错误并在那一点完成破解和停止。 但是,在python中,程序会将异常传递给调用堆栈。 沿着调用堆栈的上游,如果该异常得到处理,它将正常退出/完成。 在这种情况下, AttributeError会沿着调用堆栈传递回getattr(a,'undefined_attribute',3) getattr具有AttributeError默认值,因此它返回3并正常退出。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM