python用内部类动态创建类

mno*_*tka 8 python metaprogramming metaclass class tastypie

I'm using django-tastypie and I need to create classes like this from my django models:

class MyModelResource(ModelResource):
    class Meta:
        queryset = MyModel.objects.all()
        allowed_methods = ['get']
Run Code Online (Sandbox Code Playgroud)

Since I have a lot of models in my django app I don't want to repeat myself, and use type() function instead to create all that resource classes. The problem is I don't know how to deal with this inner "Meta" class.

Can you give me an example of how to dynamically create a class with inner class using type()?

unu*_*tbu 12

class MyModel(object) : pass
modelClass = MyModel()

class ModelResource(object):
    def mymethod(self):
        print('got here')

Meta = type('Meta', (object, ), {'allowed_methods': ['get']})

def add_mymethod(cls):
    def mymethod(self):
        super(cls, self).mymethod()
    cls.mymethod = mymethod
    return cls

name = modelClass.__class__.__name__ + "Resource"
MyModelResource = add_mymethod(type(name, (ModelResource, ),
                                    {'Meta':Meta, }))

print(MyModelResource.Meta)
# <class '__main__.Meta'>

m = MyModelResource()
m.mymethod()
# got here
Run Code Online (Sandbox Code Playgroud)

就内容而言,内部类Meta只是另一个属性MyModelResource.


就所MyModelResource涉及的方法而言,方法也只是属性.其实,你定义一个函数MyModelResource.__dict__,和Python的属性查找机制导致inst.mymethod返回一个绑定的方法.

MyModelResourcesuper通话中没有问题

super(MyModelResource, self).mymethod()
Run Code Online (Sandbox Code Playgroud)

MyModelResource定义之前,因为名称查找是在运行时执行的,而不是在mymethod定义时.


你是完全正确的

super(self.__class_, self).mymethod()
Run Code Online (Sandbox Code Playgroud)

是错的.这会破坏所有好处super.如果MyModelResource要进行子类化,并且要调用子类的实例mymethod,那么Python将陷入无限循环.