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.