gpt4 book ai didi

python - 为什么 getattr() 没有像我认为的那样工作?我认为这段代码应该打印 'sss'

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

接下来是我的代码:

class foo:
def __init__(self):
self.a = "a"
def __getattr__(self,x,defalut):
if x in self:
return x
else:return defalut

a=foo()
print getattr(a,'b','sss')

我知道 __getattr__ 必须是 2 个参数,但如果属性不存在,我想获取默认属性。

如何获取,谢谢


我发现如果定义了__setattr__,我的下一段代码也无法运行

class foo:
def __init__(self):
self.a={}
def __setattr__(self,name,value):
self.a[name]=value

a=foo()#error ,why

嗨,亚历克斯,我改变了你的例子:

class foo(object):
def __init__(self):
self.a = {'a': 'boh'}
def __getattr__(self, x):
if x in self.a:
return self.a[x]
raise AttributeError

a=foo()
print getattr(a,'a','sss')

它打印{'a': 'boh'},而不是'boh'我认为它会打印 self.a not self.a['a'], 这显然是不想看到的

为什么,有什么办法可以避免吗

最佳答案

您的第一个问题:您正在定义一个旧式类(我们知道您使用的是 Python 2.something,即使您没有告诉我们,因为您正在使用 print 作为关键字;-)。在 Python 2 中:

class foo:

意味着您正在定义一个旧式的,也就是传统的类,其行为有时可能相当古怪。永远不要那样做——没有充分的理由!旧式类的存在只是为了与依赖于它们的怪癖的旧遗留代码兼容(并最终在 Python 3 中被废除)。改用样式类:

class foo(object):

然后检查 if x in self: 不会导致递归 __getattr__ 调用。但是无论如何它都会导致失败,因为您的类没有定义__contains__ 方法,因此您无法检查实例中是否包含x那个类的。

如果你想做的是 x 是否在 selfinstance dict 中定义,请不要打扰:__getattr__ 在这种情况下甚至不会被调用——只有当属性 否则在 self 中找到时才会被调用。

要支持对内置的 getattr 的三参数调用,如有必要,只需在 __getattr__ 方法中 raise AttributeError(就像将如果您根本没有 __getattr__ 方法,就会发生这种情况),内置函数将完成它的工作(内置 的工作是拦截这种情况并返回如果提供默认)。这就是为什么人们从不直接调用 __getattr__ 等特殊方法,而是使用在内部调用它们的内置函数和运算符的原因——内置函数和运算符提供了大量的附加值。

举个比较有道理的例子:

class foo(object):
def __init__(self):
self.blah = {'a': 'boh'}
def __getattr__(self, x):
if x in self.blah:
return self.blah[x]
raise AttributeError

a=foo()
print getattr(a,'b','sss')

这会根据需要打印 sss

如果您添加一个__setattr__ 方法,那个 方法会拦截每次 尝试在self 上设置属性——包括 self.blah = 什么的。所以——当你需要绕过你正在定义的 __setattr__ 时——你必须使用不同的方法。例如:

class foo(object):
def __init__(self):
self.__dict__['blah'] = {}
def __setattr__(self, name, value):
self.blah[name] = value
def __getattr__(self, x):
if x in self.blah:
return self.blah[x]
raise AttributeError

a=foo()
print getattr(a,'b','sss')

这也会打印 sss。而不是

        self.__dict__['blah'] = {}

你也可以用

        object.__setattr__(self, 'blah', {})

这种“对父类(super class)实现的调用”(您也可以通过内置的 super 获得)是“不要直接调用特殊方法,调用内置或改用运算符”——在这里,您想要专门绕过正常行为,因此可以进行显式特殊方法调用。

关于python - 为什么 getattr() 没有像我认为的那样工作?我认为这段代码应该打印 'sss',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1964980/

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