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.)
如果调用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
。