Python Meta-programming Gotcha With __getattr__

Recently I’ve been working with Python at work. I’ve had to create a very lightweight ORM and each model class derived from the base model class. However, to access the fields in an instance of a model class required some meta-programming. This was pretty straight forward since Python provides the __getattr__ that gets executed when a field is not found. But I did run into one gotcha!

In my __getattr__ method, I was determining the value of the property that was being accessed from an internal dictionary that stored the values of the model fields. However, something really strange was happening. The __getattr__ method was being called for properties that were defined directly on the class. An example of this can be seen here.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Example(object):
    @property
    def foo(self):
        return 'bar'

    @property
    def boom(self):
        raise AttributeError

    def __getattr__(self, name):
        return 'Trying to get the {0} property.'.format(name)

v = Example()

print v.foo
>>> 'bar'

print v.boom
>>> 'Trying to get the boom property.'

It turns out that what was happening was that I was trying to access the boom property from the Example class and it was trying to be retrieved from the __getattr__ method implementation. This threw me for a loop because I am still fairly new to Python.

From the example above you can see that the foo property works correctly, but the boom property runs the __getattr__ method when accessed. If an exception is thrown in the @property method, the Python class will revert to using the __getattr__ method. Once I addressed the underlying exception everything worked properly.

Comments
« Node.js, CoffeeScript and Eco Templates Keeping an eye on productivity »

Comments