动态向已导入的模块添加函数

4
这可能是一个非常幼稚的问题,最好通过一个例子来解释: module1.py
import module2

def new_func():
    print(var_string)
module2.new_func = new_func

module2.func()
module2.new_func()

module2.py

var_string = "i'm the global string!"

def func():
    print(var_string)

结果

> python module1.py
i'm the global string!
Traceback (most recent call last):
  File "module1.py", line 8, in <module>
    module2.new_func()
  File "module1.py", line 4, in new_func
    print(var_string)
NameError: name 'var_string' is not defined

我的问题是:是否可能将一个函数插入到模块中,并使其全局命名空间相应更新?
相关链接:主脚本中定义的全局变量无法被不同模块中定义的函数访问。请注意,我知道共享全局变量是个坏主意,也知道配置模块是一个好的折衷方案,但请注意这不是我想要实现的。

永远不需要这样做。您只需使用if语句来确定调用哪个方法或将什么参数传递到方法中即可。等等... - FirebladeDan
我不同意。我认为这会非常有用。一个类比是动态地向现有类添加方法,该方法利用类的其他属性和方法。我还希望其他模块可以调用这个插入的函数。本质上,我是在动态扩展模块,而不是物理编辑模块的源代码。 - Gregory Kuhn
你需要将 print(var_string) 改为 print(module2.var_string)。 - Damián Montenegro
@DamiánMontenegro 不,那不是我要找的。我希望func可以直接访问module2的全局成员,就像它最初在global2中定义一样。 - Gregory Kuhn
我从来没有必须这样做过。但你所说的是方法重写吗?查看以下链接:http://lgiordani.com/blog/2014/05/19/method-overriding-in-python/#.VbjrbPlVhBc - FirebladeDan
@FirebladeDan 感谢建议,但不是我想要的。我想以与动态更改类类似的方式动态更改模块的实现。显然,对于类或类实例的更改,self 可以方便地访问成员... - Gregory Kuhn
2个回答

1
您可能认为这很有用,但很少有Python代码是这样编写的,我认为大多数Python程序员会对这种代码感到困惑。在导入模块后修改它(猴子补丁)通常被看作是不好的做法,因为很容易做错事情并引起奇怪的错误。
您将其比作覆盖/扩展类上的方法,但如果这确实是您想要做的事情,为什么不使用类?类的特性使得这种事情更加安全和容易。
如果您这样做,您的代码将会工作:
from module2 import var_string
#or..
from module2 import *

但我不确定这是否是你要寻找的解决方案。无论如何,我个人不会尝试使这段代码工作,它与通常编写 Python 代码的方式相抵触。如果你有一个实际的代码示例,认为通过动态修改模块可以改进它,我想看看。通过你提供的示例代码很难看出好处。


公正的观点。一些背景:我正在使用日志记录模块,并且我想向该模块添加一个函数(该函数使用模块中的其他内容),然后我可以从应用程序中的其他模块引用它。这是促使我提出此问题的原始问题。https://dev59.com/gI3da4cB1Zd3GeqP1Ijn - Gregory Kuhn
史蒂文,8年后,另一个例子:我们正在使用的一个FOSS库缺少一个函数 - 我们无法将其贡献给这个库,因为它是一个不太适用于一般情况的特殊情况,但我们仍然希望使用该库而不是分叉它(并且需要手动更新)。我们知道这段代码可能会在某个时候出错,但这比始终保持分支最新更容易。 - Thomas
@Thomas 这是一个很好的使用案例。它在实际的系统中确实有其用武之地。在过去的一些遗留系统中,我不得不做类似的事情,比如失去了更新第三方包的能力。 - Steven Kryskalla

0

我不明白你想要什么,以及这个字符串"module2.new_func = new_func"的作用是什么,因为你的module2中并没有函数new_func。 但是如果你想要在每个模块中重置变量,你不能像这样使用:

Module1:

import module2

def new_func():
    print(var_string)

new_class=module2.MyStuff()
var_string=new_class.func()
new_func()

模块2:

class MyStuff:

    def __init__(self):
        self.var_string  = "i'm the global string!"

    def func(self):
        print(self.var_string)
        return self.var_string

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接