python用内部类动态创建类

Posted

技术标签:

【中文标题】python用内部类动态创建类【英文标题】:python dynamically create class with inner class 【发布时间】:2012-11-15 07:30:31 【问题描述】:

我正在使用 django-tastypie,我需要从我的 django 模型中创建这样的类:

class MyModelResource(ModelResource):
    class Meta:
        queryset = MyModel.objects.all()
        allowed_methods = ['get']

由于我的 django 应用程序中有很多模型,我不想重复自己,而是使用 type() 函数来创建所有资源类。问题是我不知道如何处理这个内部“元”类。

你能给我举个例子,说明如何使用 type() 动态创建具有内部类的类吗?

【问题讨论】:

【参考方案1】:
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

MyModelResource 而言,内部类Meta 只是另一个属性。


MyModelResource 而言,方法也只是属性。其实你在MyModelResource.__dict__中定义了一个函数,Python的属性查找机制 导致inst.mymethod 返回一个绑定的方法

super调用中引用MyModelResource没有问题

super(MyModelResource, self).mymethod()

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


你说的很对

super(self.__class_, self).mymethod()

错了。这将破坏super 的所有优点。如果 MyModelResource 被子类化,并且子类的一个实例要调用 mymethod,那么 Python 将陷入无限循环。

【讨论】:

这是正确答案。现在,如果我必须在内部定义调用 super() 的方法怎么办?我想避免写 super(self.__class__, self) 因为显然不是一个好主意... 问题是在定义方法的那一刻我不知道类的名称。在我的情况下,类的创建如下所示: type(modelClass.__class__.__name__ + "Resource",(ModelResource, ), "Meta"... 所以我不能在方法中按名称引用它。 好的,所以 mymethod 在定义 MyModelResource 之前无法定义。在这种情况下,请使用类装饰器。我添加了类装饰器 add_mymethod 作为示例。

以上是关于python用内部类动态创建类的主要内容,如果未能解决你的问题,请参考以下文章

Python中动态创建类实例

设计模式代理模式 ( 动态代理 )

如何在 python 中腌制一个动态创建的嵌套类?

在 Ruby 中动态定义命名类

Python:动态创建类,同时为 __init__subclass__() 提供参数

Python动态继承:如何在创建实例时选择基类?