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

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

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

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

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

【问题讨论】:

    标签: python class metaprogramming tastypie metaclass


    【解决方案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 作为示例。
    猜你喜欢
    • 2011-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-16
    • 1970-01-01
    • 2012-03-13
    相关资源
    最近更新 更多