gpt4 book ai didi

python - 在基类 __init__ 的子类 __init__ 之后调用基类方法?

转载 作者:太空宇宙 更新时间:2023-11-04 09:58:04 29 4
gpt4 key购买 nike

这是我在多种语言中都怀念的一个特性,想知道是否有人知道如何在 Python 中完成它。

我的想法是我有一个基类:

class Base(object):
def __init__(self):
self.my_data = 0
def my_rebind_function(self):
pass

和派生类:

class Child(Base):
def __init__(self):
super().__init__(self)
# Do some stuff here
self.my_rebind_function() # <==== This is the line I want to get rid of
def my_rebind_function(self):
# Do stuff with self.my_data

如上所示,我有一个反弹函数,我想在Child.__init__ 完成其工作后 调用它。我希望对所有继承的类都这样做,所以如果它由基类执行就更好了,这样我就不必在每个子类中重新键入该行。

如果该语言具有像 __finally__ 这样的函数,它的运行方式类似于异常情况下的运行方式,那就太好了。也就是说,它应该在所有 __init__ 函数(所有派生类的)运行之后运行,这会很棒。所以调用顺序是这样的:

Base1.__init__()
...
BaseN.__init__()
LeafChild.__init__()
LeafChild.__finally__()
BaseN.__finally__()
...
Base1.__finally__()

然后对象构造完成。这也有点类似于使用 setuprunteardown 函数进行单元测试。

最佳答案

你可以用这样的元类来做到这一点:

    class Meta(type):
def __call__(cls, *args, **kwargs):
print("start Meta.__call__")
instance = super().__call__(*args, **kwargs)
instance.my_rebind_function()
print("end Meta.__call__\n")
return instance


class Base(metaclass=Meta):
def __init__(self):
print("Base.__init__()")
self.my_data = 0

def my_rebind_function(self):
pass


class Child(Base):
def __init__(self):
super().__init__()
print("Child.__init__()")

def my_rebind_function(self):
print("Child.my_rebind_function")
# Do stuff with self.my_data
self.my_data = 999


if __name__ == '__main__':
c = Child()
print(c.my_data)

通过覆盖 Metaclass.__call__,您可以在类树的所有 __init__(和 __new__)方法运行之后以及返回实例之前 Hook 。这是调用重新绑定(bind)函数的地方。为了理解调用顺序,我添加了一些打印语句。输出将如下所示:

start Meta.__call__
Base.__init__()
Child.__init__()
Child.my_rebind_function
end Meta.__call__

999

如果您想继续阅读并深入了解细节,我可以推荐以下精彩文章:https://blog.ionelmc.ro/2015/02/09/understanding-python-metaclasses/

关于python - 在基类 __init__ 的子类 __init__ 之后调用基类方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45000947/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com