0

I have a class whose attributes are not known beforehand:

class Event():
    def __init__(self, **kwargs):
        for key, value in kwargs.items():
            setattr(self, key, value)

and another one which is basically a list of objects Event:

class Collection(list):
    def __init__(self):
        self.members = []

    def add(self,new):
        try:
            self.members.extend(new)
        except TypeError:
            self.members.append(new)

Let's say now that I define 3 objects Event:

a = Event(name="a",value=1)
b = Event(name="b",value=2)
c = Event(name="c",other=True)

And I create a Collection from them:

col = Collection()
col.add([a,b,c])

What I want is to be able to print out all the values of the objects in the list for a given attribute (if the attribute does not exist for an object, it should return None or any other pre-defined value). For example:

print col.name #should return ["a","b","c"]
print col.value #should return [1,2,None]

I have read the following answer: Extract list of attributes from list of objects in python

But that doesn't work here since the name of my attribute is not known by advance, and some might not even be defined. How should I define my class Collection(), or maybe even re-think everything to achieve my goal ?

Community
  • 1
  • 1
ldocao
  • 129
  • 2
  • 12

2 Answers2

1

This is a variation of "I want to create dynamic variable names". The solution here is the same: use a dictionary.

class Event(object):
    def __init__(self, **kwargs):
        self.attributes = dict(kwargs)

Your Collection class will need a custom __getattr__ method, so that it can look up values in its Event list instead.

class Collection(object):
    # assume self.events is a list of Event objects
    def __getattr__(self, name):
        return [event.attributes.get(name) for event in self.events]

You could stick with your current implementation of Event, and have Collection look at event.__dict__ instead of event.attributes. I don't recall, though, if __dict__ might contain anything else besides the attributes you explicitly set. I'd err on the side of caution.

chepner
  • 497,756
  • 71
  • 530
  • 681
0

You can just override the __getattr__ method of the Collection class, which is called when an attribute is accessed. In order to access to unknown set of attributes you can use event.__dict__. So, a possible solution is like this:

def __getattr__(self, name):
    return [m.__dict__.get(name) for m in self.members]
Hgeg
  • 545
  • 6
  • 19