gpt4 book ai didi

python - Python 模块中的全局变量自发重置

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

我有一个用 Python 3.5 编写的程序的一部分,并从测试前两个模块开始。我设法在其中一个模块中找出一个问题,似乎两个全局变量无缘无故地切换回它们的原始值,我无法理解。这些全局变量之一 (event_count) 仅在一个函数中使用(grep 显示字符串“event_count”未出现在我的任何 *.py 文件中的任何其他位置),但值变量在函数调用之间发生变化。如果我在这个模块中为其他全局变量添加打印语句,它也会同时恢复到它的原始值。将 event_count 移动到另一个模块(将其替换为 eventcount() 中的 sensorlogic.event_count 并将初始化移动到另一个模块)使行为继续离开,所以我有解决办法但不理解。

这是模块 sensoreval 中使用 event_count 的所有代码:

event_count = 0

def eventcount(increment):
global event_count
print("entering eventcount, increment =", increment,
", event_count =", event_count)
event_count += increment
print("leaving eventcount, event_count =", event_count)
return event_count

如果我运行以下代码段:

    e.setvalue(1)
print("I am at marker #1")
eventcount(0)

(e.setvalue() 中的最后一个操作是调用 eventcount(0))它产生以下输出:

entering eventcount, increment = 0 , event_count = 4
leaving eventcount, event_count = 4
I am at marker #1
entering eventcount, increment = 0 , event_count = 0
leaving eventcount, event_count = 0

我曾尝试将这两个模块缩减到合理的大小,但是当我这样做时问题仍然存在。我会继续努力。由于我以前从未使用过 Python 3,并且只有一点点 Python 2.7 经验,所以我认为我在做一些愚蠢的事情,我只是不知道是什么。

我相信我的示例与一些相关帖子的不同之处在于,变量 event_count 只是全局变量,因此它将是静态的。它仅用于此单一功能。字符串“event_count”没有出现在这个模块或任何其他模块的任何其他地方。


在多次编辑/重新运行迭代之后,我有一个易于管理的小示例来演示正在发生的事情。涉及两个模块,共8行代码。第一个模块 a.py__main__:

import b
c = 0
if __name__ == '__main__':
b.init()
print("c =", c)

第二个模块是b.py:

import a
def init():
a.c = 1

运行 a.py 产生输出:

c = 0

我预计 c 仍然是 1 来自 b.py 中的 a.c = 1

此外,我试图通过从 a.py 中删除 if __name__ == '__main__' 来进一步减少它,但是示例不再运行:

Traceback (most recent call last):
File "...\a.py", line 1, in <module>
import b
File "...\b.py", line 1, in <module>
import a
File "...\a.py", line 3, in <module>
b.init()
AttributeError: module 'b' has no attribute 'init'

我也无法解释,但它似乎是相关的。


在 Mata 的带领下,我相信以下代码显示了正在发生的事情。涉及三个模块。 a.py:

print("__name__ =", __name__)
import b
print("__name__ =", __name__)
def f(): pass
print(f)
if __name__ == '__main__':
print("f is b.a.f?", f is b.a.f)

b.py:

import a

c.py:

import a
import b
print("__name__ =", __name__)
print("a.f is b.a.f?", a.f is b.a.f)

运行a.py可以看到问题,给出结果:

__name__ = __main__
__name__ = a
__name__ = a
<function f at 0x0000021A4A947840>
__name__ = __main__
<function f at 0x0000021A484E0400>
f is b.a.f? False

运行 c.py 以便 __main__ 不是导入周期的一部分导致:

__name__ = a
__name__ = a
<function f at 0x000001EA101B7840>
__name__ = __main__
a.f is b.a.f? True

最佳答案

让我们逐步查看您的双模块示例。那里的行为是预期的,但最初令人困惑,并且可能很好地解释了其他情况下发生的事情。

如果您将 a 作为脚本运行,它不会作为 a 导入到 sys.modules 中,而是作为 __main__ 。第一条语句是 import b,它创建一个空模块对象 sys.modules['b'] 并开始初始化它。

b 的第一行再次导入a。通常,会找到 sys.modules['a'] 下的模块对象,但在这种情况下,您正在将 a 作为脚本运行,因此发生了初始导入在不同的名字下。由于 a 的名称是 a 而不是 __main__ 这一次, a.c 被设置为零并且没有其他任何事情发生.

现在执行返回到b。它现在创建一个函数 init,它将 sys.modules['a'].c 设置为 1。我非常明确地写出了对 a 模块的引用,因为这是造成您的差异的根本原因。

一旦 b 被导入,执行返回到 a,而不是 sys.modules['a']。下一行 c = 0 实际上将 sys.modules['__main__'].c 设置为零。希望你现在看到了问题。下一行调用 b.init,它将 sys.modules['a'] 设置为 1。然后打印 sys.modules['__main__'],如预期的那样为零。

为了验证这个说明的正确性,尝试添加打印语句

print(sys.modules['a'].c)

您将获得 1。此外,sys.modules['a'] is sys.modules['__main__'].c 将是 False。解决此问题的最简单方法是不在给定模块的导入中初始化其他模块的成员。

您的具体案例记录在此处:http://effbot.org/zone/import-confusion.htm#using-modules-as-scripts .

其他资源

您可以在此处获得有关导入系统的详细信息的更多信息:https://docs.python.org/3/reference/import.html .此处描述了各种导入陷阱和注意事项:http://python-notes.curiousefficiency.org/en/latest/python_concepts/import_traps.html .

关于python - Python 模块中的全局变量自发重置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39708118/

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