4

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?

2
  • @Martijn Pieters - I think you should reconsider how you've marked as duplicate here. The article you link to is about classes, which in python for this particular topic is strangely very different from instances. Commented Mar 25, 2019 at 23:44
  • @JamieMarshall: no, the OP wants there to be dynamic attributes based on the values in an instance. That doesn't preclude adding a __getattr__ method to the class. The other post covers that option. Commented Mar 26, 2019 at 11:16

1 Answer 1

11

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Sure, classical case of overthinking on my side.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.