views:

91

answers:

3

What special method(s?) should I redefine in my class so that it handled AttributeErrors exceptions and returned a special value in those cases?

For example,

>>> class MySpecialObject(AttributeErrorHandlingClass):
      a = 5
      b = 9
      pass
>>>
>>> obj = MySpecialObject()
>>>
>>> obj.nonexistent
'special value'
>>> obj.a
5
>>> obj.b
9

I googled for the answer but couldn't find it.

+1  A: 

Your question isn't clear to me, but it sounds like you are looking for __getattr__ and possibly for __setattr__, and __delattr__.

Mike Graham
Oh. What I want to do is when the object doesn't have the given property, it returns special value.For example, given that `obj` has the property `a` writing `obj.a` returns the value of `a`. But when `obj` doesn't have a property, like `nosuch` then writing `obj.nosuch` returns value `special value`.Does this explanation make sense?
bodacydo
+1  A: 

You have do override __getattr__, it works like this:

class Foo(object):
    def __init__(self):
        self.bar = 'bar'

    def __getattr__(self, attr):
          return 'special value'

foo = Foo()
foo.bar # calls Foo.__getattribute__() (defined by object), returns bar
foo.baz # calls Foo.__getattribute__(), throws AttributeError, 
        # then calls Foo.__getattr__() which returns 'special value'. 
Otto Allmendinger
Thanks for telling about the gotchas! Before I read your full answer, I did this: class Foo(object): def __init__(self): self.attrx = 'valx' ... def __getattr__(self, attr): return 'special value' and it somehow worked! Should it or should it not really work?
bodacydo
By "somehow worked" I mean when i accessed `foo_obj.attrx` it returned `valx`, but when I accessed `foo_obj.nonexist` it returned 'special value'.
bodacydo
That is not a proper use of `__getattr__` at all. `__getattr__`, as opposed to `__getattribute__` operates as a fallback method if the meaningful attributes are already defined, so you don't have to look up normal attributes in `__getattr__`.
Mike Graham
@Bodacydo: true, the gotcha I described doesn't apply to your case. First __getattribute__() is called, when that throws an exception, `__getattr__()` is called.
Otto Allmendinger
+2  A: 

The example of how to use __getattr__ by Otto Allmendinger overcomplicates its use. You would simply define all the other attributes and—if one is missing—Python will fall back on __getattr__.

Example:

class C(object):
    def __init__(self):
        self.foo = "hi"
        self.bar = "mom"

    def __getattr__(self, attr):
        return "hello world"

c = C()
print c.foo # hi
print c.bar # mom 
print c.baz # hello world
print c.qux # hello world
Mike Graham
This is how I did it before I read Otto's answer. :) Thanks!
bodacydo