user861537
user861537

Reputation:

Elegant way of grouping attributes

I want to group attributes of instances of a class, so that it would be easy to iterate through all the attributes belonging to a group. The obvious answer would be to put all these into a list or dict, but then I wouldn't be able to access them as attributes of my object, and I would prefer that.

Some code should make it clear what I want. Here I actually have a list and real attributes.

class Vectors(object):

    def __init__(self, v1, v2, v3):
        self.v1 = v1
        self.v2 = v2
        self.v3 = v3
        self.rotatable = ['v2', 'v3']

    def rotate(self, angle):
        for v in self.rotable:
            new_vector = do_rotate(getattr(self, v), angle)
            setattr(self, v, new_vector)

class MoreVectors(Vectors):
    def __init__(self, v4, *args, **kwargs):
        super(MoreVectors, self).__init__(*args, **kwargs)
        self.v4 = v4
        self.rotable.append('v4')

Now when calling rotate() it know what vectors to rotate and I can add more vectors to that list dynamically. However, while this does its job, it doesn't look that elegant to me as I have to manage the list by myself.

Is there some simpler way to write this? I thought about storing all attributes in a dictionary, where each group is a key, and then use properties() to let me access all items of the dictionary as attributes. That would be clean enough for me, but I don't know how to set properties dynamically inside a method.

Upvotes: 3

Views: 462

Answers (1)

unutbu
unutbu

Reputation: 879471

How about make rotatable an attribute of a Vector class:

class Vector(object):
    def __init__(self,v,rotatable=False):
        self.value = v
        self.rotatable = rotatable

And then use properties to access the values easily:

class Vectors(object):
    def __init__(self, v1, v2, v3):
        self.vectors = [Vector(v1),Vector(v2,rotatable=True),Vector(v3,rotatable=True)]
    @property
    def v1(self):
        return self.vectors[0].value
    @property    
    def v2(self):
        return self.vectors[1].value
    @property    
    def v3(self):
        return self.vectors[2].value
    def rotate(self, angle):
        for vector in self.vectors:
            if vector.rotatable:
                vector.value = do_rotate(vector.value, angle)

class MoreVectors(Vectors):
    def __init__(self, v4, *args, **kwargs):
        super(MoreVectors, self).__init__(*args, **kwargs)
        self.vectors.append(Vector(v4,rotatable=True))
    @property
    def v4(self):
        return self.vectors[3].value

Upvotes: 3

Related Questions