[英]Why is getattr() not working like I think it should? I think this code should print 'sss'
the next is my code: 接下来是我的代码:
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')
i know the __getattr__
must be 2 argument,but i want to get a default attribute if the attribute is no being. 我知道
__getattr__
必须是2个参数,但是如果该属性不存在,我想获得一个默认属性。
how can i get it, thanks 我该如何获得,谢谢
and 和
i found if defined __setattr__
,my next code is also can't run 我发现如果定义了
__setattr__
,我的下一个代码也无法运行
class foo:
def __init__(self):
self.a={}
def __setattr__(self,name,value):
self.a[name]=value
a=foo()#error ,why
hi alex, i changed your example: 您好亚历克斯,我改变了你的例子:
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')
it print {'a': 'boh'},not 'boh' i think it will print self.a not self.a['a'], This is obviously not want to see 它打印{'a':'boh'},而不是'boh'我认为它将打印self.a不是self.a ['a'],这显然是不想看到的
why ,and Is there any way to avoid it 为什么,还有什么办法可以避免它
You are confusing the getattr
built-in function, which retrieves some attribute binding of an object dynamically (by name), at runtime, and the __getattr__
method, which is invoked when you access some missing attribute of an object. 您会混淆
getattr
内置函数和__getattr__
方法,该函数在运行时动态(按名称)检索对象的某些属性绑定,而__getattr__
方法在访问对象的某些缺少属性时会被调用。
You can't ask 你不能问
if x in self:
from within __getattr__
, because the in
operator will cause __getattr__
to be invoked, leading to infinite recursion. 从
__getattr__
内部进行,因为in
运算符将导致__getattr__
被调用,从而导致无限递归。
If you simply want to have undefined attributes all be defined as some value, then 如果您只是想将所有未定义的属性都定义为某个值,那么
def __getattr__(self, ignored):
return "Bob Dobbs"
Your problem number one: you're defining an old-style class (we know you're on Python 2.something, even though you don't tell us, because you're using print
as a keyword;-). 问题一:您正在定义一个老式的类(我们知道您使用的是Python2。即使您不告诉我们,因为您使用
print
作为关键字;-)。 In Python 2: 在Python 2中:
class foo:
means you're defining an old-style, aka legacy, class, whose behavior can be rather quirky at times. 表示您正在定义一个旧式的(又名“旧式”类),其行为有时可能很古怪。 Never do that -- there's no good reason!
永远不要那样做-没有充分的理由! The old-style classes exist only for compatibility with old legacy code that relies on their quirks (and were finally abolished in Python 3).
存在旧类仅是为了与依赖于其怪癖的旧遗留代码兼容(并最终在Python 3中被废除了)。 Use new style classes instead:
改用新样式类:
class foo(object):
and then the check if x in self:
will not cause a recursive __getattr__
call. 然后检查
if x in self:
是否不会导致递归__getattr__
调用。 It will however cause a failure anyway, because your class does not define a __contains__
method and therefore you cannot check if x
is contained in an instance of that class. 但是无论如何它都会导致失败,因为您的类未定义
__contains__
方法,因此您无法检查x
是否包含在该类的实例中。
If what you're trying to do is whether x
is defined in the instance dict of self
, don't bother: __getattr__
doesn't even get called in that case -- it's only called when the attribute is not otherwise found in self
. 如果你正在尝试做的是是否
x
在实例字典定义self
,不要打扰: __getattr__
甚至不被调用在这种情况下-当属性不以其他方式找到这只是所谓的self
。
To support three-arguments calls to the getattr
built-in, just raise AttributeError
in your __getattr__
method if necessary (just as would happen if you had no __getattr__
method at all), and the built-in will do its job (it's the built-in 's job to intercept such cases and return the default if provided). 要支持对内置
getattr
三个参数的调用,只需在必要时在__getattr__
方法中raise AttributeError
(就像根本没有__getattr__
方法时发生的那样),并且内置__getattr__
将完成其工作(即内置-in的工作来拦截此类情况并返回默认值(如果提供)。 That's the reason one never ever calls special methods such as __getattr__
directly but rather uses built-ins and operators which internally call them -- the built-ins and operators provide substantial added value. 这就是为什么从不直接调用诸如
__getattr__
特殊方法,而是使用内部调用它们的内置函数和运算符的原因-内置函数和运算符提供了可观的附加值。
So to give an example which makes somewhat sense: 因此,举个有意义的例子:
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')
This prints sss
, as desired. 根据需要打印
sss
。
If you add a __setattr__
method, that one intercepts every attempt to set attributes on self
-- including self.blah =
whatever. 如果添加
__setattr__
方法,则该方法将拦截对self
设置属性的所有尝试-包括self.blah =
任意。 So -- when you need to bypass the very __setattr__
you're defining -- you must use a different approach. 因此,当您需要绕过要定义的
__setattr__
,必须使用其他方法。 For example: 例如:
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')
This also prints sss
. 这也会打印
sss
。 Instead of 代替
self.__dict__['blah'] = {}
you could also use 您也可以使用
object.__setattr__(self, 'blah', {})
Such "upcalls to the superclass's implementation" (which you could also obtain via the super
built-in) are one of the rare exceptions to the rules "don't call special methods directly, call the built-in or use the operator instead" -- here, you want to specifically bypass the normal behavior, so the explicit special-method call is a possibility. 这样的“对超类的实现的调用”(您也可以通过
super
内置实现获取)是“不直接调用特殊方法,调用内置方法或使用运算符代替”规则的罕见例外之一。 -在这里,您要专门绕过正常行为,因此有可能进行显式的特殊方法调用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.