Question

I am implementing a user interface. Many objects expose various properties to the user interface. They each have an object "ExposedProperties" that contains amongst other things a list of the exposed properties (and their types, how they should be displayed, how input should validated, etc.) This ExposedProperties object is calculated once for each class.

I would like to get a concatenation of all of the exposed properties of an object. One way to do this is for each object to pass its "ExposedProperties" up the inheritance chain in __init__ and for each superclass to concatenate that with its own ExposedProperties. A base class would set the concatenated ExposedProperties on the object.

Another way is to wait until the total exposed properties are requested from an object. Then, a base class method that scans each class in the mro for exposed_properties attributes concatenates them at that time.

What is the most Pythonic way to concatenate these objects stored in an inheritance chain in Python?

Was it helpful?

Solution

Since the exposed properties are class attributes, it makes sense to construct the desired list (of the exposed properties of the class together with those of its ancestors) at the time of class creation, for which you can use a metaclass. (Edit: I see the same suggestion was made in the comments.)

Here's an example of doing that:

class ExposedMeta(type):

    def __init__(cls, name, bases, attrs):
        if not "exposed_properties" in attrs:
            cls.exposed_properties = []
        all_props = set(cls.exposed_properties)
        for base in bases:
            all_props.update(getattr(base, "all_exposed_properties", []))
        cls.all_exposed_properties = list(all_props)
        super(ExposedMeta, cls).__init__(name, bases, attrs)

class A(object):
    __metaclass__ = ExposedMeta
    exposed_properties = ['A1', 'A2']

class B(A):
    exposed_properties = ['B']

class C(A):
    pass

class D(object):
    __metaclass__ = ExposedMeta
    exposed_properties = ['D']

class E(B, D):
    exposed_properties = ['E1', 'E2']

for cls in [A, B, C, D, E]:
    print "Class %s, exposed: %s, all exposed: %s" % (cls.__name__, cls.exposed_properties, cls.all_exposed_properties)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top