gpt4 book ai didi

python - 如何以优雅且安全(关于Python模块重新加载)的方式使用super()?

转载 作者:太空宇宙 更新时间:2023-11-03 14:33:46 25 4
gpt4 key购买 nike

我发现了 reload()(Python 2 内置的和来自 importlib)的一个烦人的行为,我正在尝试解决这个问题。

我正在交互式 Python 解释器中分析数据。我的代码按模块(Python 2 和 3 兼容)进行组织,我经常更改这些模块。

由于加载数据的时间较长,重新启动解释器是不可行的,所以我更喜欢递归地重新加载模块。

问题是 reload() updates the code but preserves the module global scope (它也适用于Python 3 importlib.reload())。这对于使用 super() 的方法似乎是有害的(我花了一段时间才意识到发生了什么)。

模块 bar.py 的最小失败示例:

class Bar(object):
def __init__(self):
super(Bar, self).__init__()

是:

>>> import bar
>>> class Foo(bar.Bar):
... pass
...
>>> reload(bar)
<module 'bar' from '[censored]/bar.py'>
>>> Foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "[censored]/bar.py", line 3, in __init__
super(Bar, self).__init__()
TypeError: super(type, obj): obj must be an instance or subtype of type

我可以:

  1. use super() without arguments in Python 3 manner (这不是与 Python 2 兼容),
  2. 放弃它并调用 Bar.__init__(self) ( which is harder tomaintaindiscouraged ),
  3. 猴子修补类添加包含循环的类属性对类本身的引用。

没有一个想法是我喜欢的。还有其他方法可以解决这个问题吗?

最佳答案

你不能,因为在模块重新加载方面基本上不可能优雅且安全地做任何事情。这种事情要做好是非常棘手的。

这里问题表现的具体方式是,Foo的父类(super class)仍然是旧的Bar,但是旧的Bar引用的是本身的名称,并且 Bar 名称现在引用它所查找的命名空间中的新 Bar。旧的 Bar 正在尝试将新的 Bar 传递给 super

<小时/>

我可以给你一些选择。所有这些都是不优雅不安全,并且最终可能会给你带来奇怪的惊喜,但对于模块重新加载来说,这也是事实。 p>

可能最容易理解的选项是重新运行 Foo 类定义,以获取从新 Bar 派生的新 Foo 类:

reload(bar)
class Foo(bar.Bar):
pass

Foo 的新实例将使用新的 Bar,并且不会遇到 super 的问题。旧实例将使用旧的 Foo 和旧的 Bar。他们不会遇到 __init__ 问题,因为它已经运行了,但他们可能会遇到其他问题。

您可以采取的另一个选择是更新 Foo 的父类(super class),因此 Foo 现在源自新的 Bar:

reload(bar)

Foo.__bases__ = (bar.Bar,)

Foo 的新旧实例将使用新的 Bar。根据您在 Bar 中所做的更改,新类可能与旧实例不兼容,特别是如果您更改了 Bar 在其实例上保留的数据或 的保存方式Bar.__init__ 执行初始化。

关于python - 如何以优雅且安全(关于Python模块重新加载)的方式使用super()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47103306/

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