Python dynamic class

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)

    @classmethod
    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()

    @classmethod
    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:

    @classmethod
    def set_sex(cls, key, sex):
	...

    @classmethod
    def get_sex(cls, key):
	...

class RAlbum:

    @classmethod
    def set_sex(cls, key, sex):
	...

    @classmethod
    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.

comments powered by Disqus

2015-05-14


On this page: