__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
值:
超类有一个atributenot\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两人都在调用classClassOne
的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)