我有如下两个类:
class Super(object):
def __init__(self, arg):
self.arg = arg
def load(self):
# Load data from disk if available
try:
self.data = load_routine()
except IOError as e:
if e[0] == errno.ENOENT:
pass
else:
raise
class Sub(Super):
def __init__(self, arg2, *args, **kwargs):
super(Sub, self).__init__(*args, **kwargs)
self.arg2 = arg2
def load(self):
# Load files specific to superclass
super(Sub, self).load()
# Load data from disk if available
try:
self.data2 = another_different_load_routine(self.arg2)
except IOError as e:
if e[0] == errno.ENOENT:
pass
else:
raise
我希望代码足够清晰,除非我遗漏了什么,否则这应该适用于两个类,例如:obj = Super(); obj.load().
但是,我实际上希望在 __init__() 结束时自动调用 load 方法,但我不确定如何实现这一点。如果我在 __init__() 的末尾添加 self.load() 两个类的 load() 子类的方法将被调用两次,如果尝试创建 Sub 的实例,一次来自父类(super class),一次来自子类。
如果我只在父类(super class)的 init 方法的末尾调用 self.load(),它只会被调用一次,但对象还没有被初始化为包含加载所需的属性。
在实例化 Sub 时,我真正想要的是为父类(super class)和子类初始化 __init__ 中的所有属性,并调用 load() 用于父类(super class)和子类。是否有序
Super -> __init__(), Super -> load(), Sub -> __init__(), Sub -> 加载()
或
Super -> __init__(), Sub -> __init__(), Super -> load(), Sub -> 加载()
并不重要。我怎样才能做到这一点?
请您参考如下方法:
答案是你没能列举出来的组合:
class Super(object):
def __init__(self):
print 'init super'
if self.__class__ == Super:
self.load()
def load(self):
print 'load super'
class Sub(Super):
def __init__(self):
# always do super first in init
super(Sub, self).__init__()
print 'init sub'
self.load()
def load(self):
# load is essentially an extension of init
# so you still need to call super first
super(Sub, self).load()
print 'load sub'
sub = Sub()
如果你真的想实例化 super(它不是抽象类),你需要在它的 init 中进行 if 测试。否则,您无法通过当前的类结构和初始化方案获得所需的有序语义。
Sub() 将调用 Sub.__init__,后者将调用 Super.__init__(在执行任何操作之前)。
之后,Sub 上的__init__ 将执行此操作。
最后,Sub.__init__ 将调用 Sub.load,这将调用 Super.load(在执行任何操作之前),然后执行它自己的作品。
执行此操作的“正常”方法是
sub = Sub()
sub.load()
sup = Super()
sup.load()
根本没有 __init__ 方法调用 load。如果您真的想在 load 中调用级别,这可能是我推荐的,因为它本质上是第二组 __init__。
编辑:阅读关于前两个版本失败的评论(并查看编辑以查看旧版本)。这是另一个版本,使用元类:
class Loader(type):
def __new__(cls, name, bases, attrs):
if attrs.get('__init__'):
attrs['_init'] = attrs['__init__']
del attrs['__init__']
if attrs.get('_init_'):
attrs['__init__'] = lambda self: self._init_()
attrs['_init'] = lambda self: None
return super(Loader, cls).__new__(cls, name, bases, attrs)
class Super(object):
__metaclass__ = Loader
def _init_(self):
print 'init super'
self._init()
self.load()
def load(self):
print 'load super'
class Sub(Super):
def __init__(self):
print 'init sub'
def load(self):
super(Sub, self).load()
print 'load sub'
sub = Sub()
sup = Super()
这有一个不同的限制:所有子类都可以正常运行,除了它们不能通过使用 super().__init__() 调用 Sub.__init__。我认为可以取消此限制,但如果没有另一层间接层,我目前还不知道如何做到这一点。
