__python中的getattr\uuu方法

__python中的getattr\uuu方法,python,oop,delegates,Python,Oop,Delegates,我今天遇到了这个代码,它看起来很混乱 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):

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

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
时,我们触发
子类中的
\uu getattr\uuu
方法,然后委托给
getattr(self.tmp,attr)
函数,如果属性未定义且未给出默认值,该函数将引发异常。但是,最后一行的值3如何仍然贯穿整个过程,并最终返回到
getattr(a,'undefined_attribute',3)
函数?。因为我们在委派
getattr(self.tmp,attr)
时没有默认值的插槽,这怎么可能呢

getattr(self.tmp,attr)

引发AttributeError,如果getattr有第三个参数(默认值),则返回默认值,而不是一步一步地引发AttributeError。为什么显示
3
值:

超类有一个atribute
not\u important\u属性
,它是在调用构造函数时设置的

在这里,在
ClassTwo
构造函数中,创建
ClassOne
的实例,并将其保存到
tmp
变量中。这意味着当您重写
\uuuu getattr\uuuu
时,您将询问
ClassOne
的属性值

这与直接执行相同:

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封装在类2中。我们可以通过修改getattral一点点看到这一点

   def __getattr__(self, attr, *args, **kwargs):
        print(args)  # -> empty
        print(kwargs)  # -> empty
        return getattr(self.tmp, attr)
实际上,您可以使用
print(a.。\uu getattr\uuuuuu('undefined\u attribute',3))
直接从类2中调用getattr。此方法将引发异常

因此本质上,
getattr(一个,'undefined_attribute',3)
是标准的python方法,它在内部从class2调用定制的getattr

class ClassTwo:
...
    def __getattr__(self,attr):
        return getattr(self.tmp,attr)
getattr(a,'undefined_attribute',3)
方法是调用
\uuuu getattribute\uuuuu
的包装器,如果
\uuu getattribute\uuuuuu
失败,它将调用
\uu getattr\uuuuuuuu
。它是通过处理异常
AttributeError
实现的。在您的例子中,
getattr(一个,'undefined\u attribute',3)
调用上面的
class2.\uuuu getattr\uuuu


似乎您认为当它到达
return getattr(self.tmp,attr)
时,它将抛出错误或返回某种错误,并在该点中断并停止。然而,在python中,程序会将异常向上传递到调用堆栈。沿着调用堆栈的上游,如果该异常得到处理,它将正常退出/完成。在这种情况下,
AttributeError
沿着调用堆栈传回
getattr(a,'undefined\u attribute',3)
。这个
getattr
AttributeError
的默认值,所以它返回
3
并正常退出。

是的,这不是一个继承机制,我会编辑它,如果getattr引发AttributeError,那么函数getattr返回默认值(如果存在)(在你的例子中是3)。@andreybernda我不确定这是否正确,调用方法
\uuu getattr\uuuu
时,它将返回我们在函数中定义的值,而不是类外的默认值,检查“如果getattr有第三个参数”您正在谈论的getattr,
getattr(self.tmp,attr)
getattr(a,'undefined\u attribute',3)
在类外。@TuấnĐoán两人都在调用class
ClassOne
的attribute
不重要的属性
,请查看我的答案以了解更多详细信息。我正在谈论getattr(一个“未定义的属性”,3)。getattr(self.tmp,attr)引发AttributeError,而getattr(a,'undefined_attribute',3)由于默认值而返回3value@AndreyBerenda当调用方法
\uuuu getattr\uuuu
时,它将返回我们在函数中定义的值,而不是类外的默认值,请检查我正在谈论的案例打印(getattr(b,“未定义的属性”,3))
   def __getattr__(self, attr, *args, **kwargs):
        print(args)  # -> empty
        print(kwargs)  # -> empty
        return getattr(self.tmp, attr)
class ClassTwo:
...
    def __getattr__(self,attr):
        return getattr(self.tmp,attr)