接下来是我的代码:
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而不是self.a ['a'],这显然不想看到
为什么,有没有办法避免它
答案 0 :(得分:3)
您正在混淆getattr
内置函数,它在运行时动态地(按名称)检索对象的某些属性绑定,以及__getattr__
方法,当您访问某些对象时会调用该方法缺少对象的属性。
你不能问
if x in self:
来自__getattr__
,因为in
运算符会导致__getattr__
被调用,从而导致无限递归。
如果您只想将未定义的属性全部定义为某个值,则
def __getattr__(self, ignored):
return "Bob Dobbs"
答案 1 :(得分:3)
你的第一个问题:你正在定义一个旧式的课程(我们知道你使用Python 2.something,即使你没有告诉我们,因为你使用print
作为关键词;-)。在Python 2中:
class foo:
意味着你要定义一种旧式的,也就是遗产的类,它的行为有时会相当古怪。永远不要那样做 - 没有充分的理由!旧式类仅存在与依赖于它们的怪癖的旧遗留代码的兼容性(并且最终在Python 3中被废除)。改为使用 new 样式类:
class foo(object):
然后检查if x in self:
将不会导致递归__getattr__
调用。然而, 会导致失败,因为您的类没有定义__contains__
方法,因此您无法检查该类的实例中是否包含x
。
如果您要做的是x
是否在self
的实例字典中定义,请不要打扰:__getattr__
不要甚至在这种情况下被调用 - 只有当self
中的属性为而不是时才会调用它。
要支持对getattr
内置raise AttributeError
的三个参数调用,必要时只需__getattr__
方法__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
这样的“超级类实现的上调”(你也可以通过内置的{{1}}获得)是规则的罕见例外之一“不要直接调用特殊方法,调用内置函数在或使用运算符“ - 在这里,您希望专门绕过正常行为,因此显式特殊方法调用是可能的。