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.