在metaclass调用的classmethod中调用`super` .__ new__

Mit*_*tar 8 python inheritance super

我有一个案例,我的类有一个自定义元类,在创建它时调用类的类方法,如:

class Metaclass(type):
    def __new__(cls, name, bases, attrs):
        ...
        new_class = super(Metaclass, cls).__new__(cls, name, bases, attrs)
        ...
        new_class.get_fields() # do something
        ...
        return new_class

class FooBar(object):
    __metaclass__ = Metaclass

    @classmethod
    def get_fields(cls):
        ...
Run Code Online (Sandbox Code Playgroud)

(此类代码的示例在Tastypie中.)

问题是如果我想这样做:

class NewBar(FooBar):
    @classmethod
    def get_fields(cls):
        super(NewBar, cls).get_fields()
        ...
Run Code Online (Sandbox Code Playgroud)

这不起作用,因为NewBar尚未在super调用点创建(程序流仍在元类中).那么,有没有解决方法?

我知道可能get_fields方法可能成为元类的方法,但是这会使继承更难实现(你必须定义新的元类和类本身,对于想要扩展这个类的开发人员来说并不好).

(Python 2.7.)

use*_*342 2

如果调用NewBar时can不可用get_fields,您仍然可以在以下的MRO中找到它cls

@classmethod
def get_fields(cls):
    # we can get invoked before NewBar is available in globals,
    # so get NewBar from cls.__mro__
    NewBar = next(c for c in cls.__mro__
                  if c.__module__ == __name__ and c.__name__ == 'NewBar')
    super(NewBar, cls).get_fields()
    ...
Run Code Online (Sandbox Code Playgroud)

虽然这段代码看起来很有趣,但它工作正常,并且比问题中提出的替代方案简单得多。虽然大多数使用super非常量第一个参数(例如 unqualified super(cls, cls))的调用都是不正确的并且会破坏继承,但这个调用是安全的,因为生成器表达式只不过是一种获取 的非常规方法NewBar

当在 MRO 中查找 class 时,我们会检查类和模块名称(如 Mitar 指出的那样可用__name__othermodule.NewBar避免继承自时出现误报thismodule.NewBar