我有一个案例,我的类有一个自定义元类,在创建它时调用类的类方法,如:
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):
...
(此类代码示例位于Tastypie。)
问题是如果我想这样做:
class NewBar(FooBar):
@classmethod
def get_fields(cls):
super(NewBar, cls).get_fields()
...
这不起作用,因为在调用NewBar
点时尚未创建super
(程序流仍在元类中)。那么,有没有解决方法呢?
我知道可能get_fields
方法可能成为元类的方法,但这会使继承更难实现(你必须定义新的元类和类本身,对于想要扩展它的开发人员不好类)。
(Python 2.7。)
答案 0 :(得分:3)
如果在调用NewBar
时get_fields
无效,您仍然可以在cls
的MRO中找到它:
@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()
...
尽管此代码看起来很有趣,但它可以正常工作,并且比问题中提出的替代方案简单得多。虽然大多数使用非常量第一个参数(例如非限定super
)调用super(cls, cls)
是不正确的并且中断继承,但这个是安全的,因为生成器表达式只是一种非传统的方式来保持NewBar
。
在MRO中查找clas时,我们会检查类和模块名称(可用__name__
,as pointed out by Mitar),以避免在othermodule.NewBar
继承自thismodule.NewBar
时出现误报}}
答案 1 :(得分:0)
基于来自@ user4815162342的回答,我发现了更简单的解决方案:
try:
super(NewBar, cls).get_fields()
except NameError, e:
if 'NewBar' in str(e):
super(cls, cls).get_fields()
else:
raise
答案 2 :(得分:0)
我知道这个问题是特定于python 2.7的,但对于那些使用python 3.6的人,你可以简单地调用super()
。
class NewBar(FooBar):
@classmethod
def get_fields(cls):
super().get_fields()
...