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 |
|
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.