Dynamic Python Mixins

I was pretty surprised to find out how straightforward it is to create mixin factories and templates in Python. I had a bunch of classes with attributes that needed special getter and setter methods with JSON serialization logic inside of them.

class Model:
    parameter = None

    def get_parameter(self):
        return json.loads(self.parameter)

    def set_parameter(self, value)
        return self.parameter = json.dumps(value)

With several such classes, each containing different amount of attributes that need JSON setters and getters I was aiming to keep it DRY with mixins, but since the number of attributes and their names differ between classes, I’d need a template mixin, a mixin factory that generates mixins dyanmically.

Here we go:

def JSONAttributes(attributes):
    class JSONAttributeMixin:
        pass

    def create_setter(attribute):
        def setter(self, value):
            setattr(self, attribute, json.dumps(value))
        return setter

    def create_getter(attribute):
        def getter(self):
            return json.loads(getattr(self, attribute))
        return getter

    for attribute in attributes:
        setattr(JSONAttributeMixin, 'set_' + attribute, create_setter(attribute))
        setattr(JSONAttributeMixin, 'get_' + attribute, create_getter(attribute))

    return JSONAttributeMixin

As you can see, the factory creates an inner class that will be used as a mixin, and for each attribute creates a getter and setter functions and tack them onto the mixin.

class ModelA(JSONAttributes(['permissions', 'rules'])):
    pass

m = ModelA()
m.set_rules([{'name': 'general'}])
m.set_permissions([{'type': 'all'}])

m.get_rules()
# [{'name': 'general'}]
m.get_permissions()
# [{'type': 'all'}]

m.permissions
# '[{"type": "all"}]'

Easy đŸ™‚