有人可以用Python解释器解释这背后的逻辑吗?这种行为只是本地线程吗?为什么第二个模块导入后第一个模块导入中的赋值仍然存在?我刚刚进行了长时间的调试会议。
external_library.py
def the_best():
print "The best!"
modify_external_library.py
import external_library
def the_best_2():
print "The best 2!"
external_library.the_best = the_best_2
main.py
import modify_external_library
import external_library
external_library.the_best()
测试:
$ python main.py
The best 2!
答案 0 :(得分:9)
没有关于此的线程本地。 somemodule.anattr = avalue
非常全球行为!在此分配之后,无论如何,属性都会更改(直到可能稍后更改)。
没有神秘的机制在起作用!对允许这种赋值的对象的任何属性的赋值(如模块对象那样)只是以明显的方式工作 - 没有线程本地的东西,没有什么奇怪的 - 并且属性的赋值仍然存在,只要对象的属性为你&#当然,我已经分配了坚持。
重复的import external_library
没有重新加载模块(reload
是一个完全独立的内置,import
做不调用它!) - 它只检查sys.modules
,在external_library
中找到dict
键,并将相应的值(之前由该赋值修改)绑定到名称{{ 1}}在相应的命名空间中(这里是模块external_library
的全局变量)。
答案 1 :(得分:1)
模块是新式类的实例。修改模块的属性(在本例中为函数)时,您正在修改模块实例。当您尝试再次导入它时(使用import external_library
),您只需获取modify_external_library.py
内已引用的相同模块对象。
编辑:当然,尝试再次导入同一个模块并不能真正起作用(正如Alex Martelli指出的那样)。加载后,除非使用reload
明确执行,否则不会重新初始化模块。
答案 2 :(得分:1)
正如亚历克斯所说,你需要重新加载external_library
,如果它已经被导入,只是导入它就什么都不做。您可以将print
语句放入external_library
和modify_external_library
模块中进行检查。
import modify_external_library
#import external_library
reload(external_library)
external_library.the_best()
<强>输出强>
The best!
答案 3 :(得分:0)
Monkey补丁是可行的,因为类在python中是可修改的,但允许它像这样传播的机制是,一旦导入任何模块并初始化,稍后导入只需将现有实例添加到本地命名空间而不重新运行初始化,这也节省了模块进行大量初始化以及允许猴子补丁的时间。