Make a dynamic class in Python

Tagged as python, django
Written on 2015-05-14 23:17:00

Sometimes, we hope a class can be dynamicly created in python runtime.

Take this scenario, we have two Django model classes:

from django.db import models

class Musician(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    sex = models.IntegerField()
    instrument = models.CharField(max_length=100)

    def update_sex(cls, id, sex):
    if cls.objects.filter(pk=id).update(sex=sex) > 0:
        # update Redis

class Album(models.Model):
    name = models.CharField(max_length=30)
    release_date = models.DateField()
    num_stars = models.IntegerField()

    def update_name(cls, id, name):
    if cls.objects.filter(pk=id).update(name=name) > 0:
        # update Redis

Ok, what if we just need Redis key-value cache, how can we design our Redis class ? Most of all, we think about two same like classes like this:

class RMusician:

    def set_sex(cls, key, sex):

    def get_sex(cls, key):

class RAlbum:

    def set_sex(cls, key, sex):

    def get_sex(cls, key):

This may be very ugly ! But we can make things better in Python:

def make_class(cls, *fields):
    RedisFactory = type('RedisFactory', (), {'r': redis.Redis()})

    def set_x(key, x):
    Redisfactory.r.set(key, x)

    def get_x(field, key):
    x = Redisfactory.r.get(key)
    if not x:
        obj = globals()[cls].objects.filter(id=key).first()
        if obj:
        x = getattr(obj, field)
        set_x(key, x)
    return x

    for f in fields:
    # setattr(RedisFactory, 'get_{0}'.format(f), classmethod(lambda kls, key: get_x(f, key)))
    # setattr(Redisfactory, 'set_{0}'.format(f), classmethod(lambda kls, key, x: set_x(key, x)))

    return RedisFactory

RMusician = make_class('Musician', 'sex')
RAlbum = make_class('Album', 'name')

That's it.

Load Disqus

Unless otherwise credited all material Creative Commons License by Lingchao Xin