Dynamically add properties to instances in Python
dynamic, properties, python
Solution
You can actually do this easily by just changing the name of your function:
>>> class Wrapper(object):
... def __init__(self, data):
... self.data = data
... def __getattr__(self, attr):
... return [d[attr] for d in self.data]
...
>>> Wrapper([{'x': 23}, {'x': 42}, {'x': 5}]).x
[23, 42, 5]
The `__getattr__()` special method is called whenever you request an attribute that doesn't exist. The only potential issue here is that you could override this by assigning an attribute. If you need to avoid that, simply override `__setattr__()` as well to stop that from happening.
Problem
I've got essentially an elaborate wrapper around a list of dictionaries: ``` class Wrapper(object): def __init__(self, data): self.data = data def get(self, attr): return [d[attr] for d in self.data] ``` So, ``` Wrapper([{'x': 23}, {'x': 42}, {'x': 5}]).get('x') ``` returns `[23, 42, 5]`. Now I want to assign shorthand properties, so that `Wrapper.x` will return the same as `Wrapper.get('x')`. I don't know what keys are present in the `data` a priori, so my current approach is (adapted from this question: ``` class Wrapper(object): def __init__(self, data): self.data = data for key in data[0].keys(): setattr(self, key, property(lambda self: self.get(key))) ``` So, assumption is that all elements of data have the same keys and they're all valid identifiers in python. But then, `Wrapper(...).x` returns `<property at 0x10a3d4838>` What am I doing wrong?