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.
how can i get it, thanks
and
i found if defined __setattr__,my next code is also can’t run
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
why ,and Is there any way to avoid it
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
printas a keyword;-). In Python 2: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). Use new style classes instead:
and then the check
if x in self:will not cause a recursive__getattr__call. It will however cause a failure anyway, because your class does not define a__contains__method and therefore you cannot check ifxis contained in an instance of that class.If what you’re trying to do is whether
xis defined in the instance dict ofself, don’t bother:__getattr__doesn’t even get called in that case — it’s only called when the attribute is not otherwise found inself.To support three-arguments calls to the
getattrbuilt-in, justraise AttributeErrorin 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). 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.So to give an example which makes somewhat sense:
This prints
sss, as desired.If you add a
__setattr__method, that one intercepts every attempt to set attributes onself— includingself.blah =whatever. So — when you need to bypass the very__setattr__you’re defining — you must use a different approach. For example:This also prints
sss. Instead ofyou could also use
Such “upcalls to the superclass’s implementation” (which you could also obtain via the
superbuilt-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.