为什么我的模块不能像单例一样工作?

3

我有一个JSON文件,作为小游戏中的数据存储,用来学习Python语言。
我熟练掌握其他几种编程语言。

我有几个类想要读取JSON,因此我想将JSON从文件加载到变量中,并允许其他类通过getter和setter方法访问该变量,因为每个类都需要JSON的不同部分。

这听起来像是一个Singleton模式。我知道Python模块的行为类似于Singleton模式。

然而,当我将模块导入到我的类中时,变量会重置?

以下是非常简化的示例:

模块:- 状态管理器(state_manager)

x=45
def set_x(value):
    x=value

def get_x():
    return x

类:- 游戏

import Player

import state_manager
value = state_manager.get_x()

类别:- 玩家

import state_manager
state_manager.set_x(12)

通过设置断点,我发现当游戏导入玩家时,Playerstate_manager中的x值设置为12。

但是当我使用state_manager.get_x()查看返回给游戏的x值时,结果是45。

这是为什么呢?

在Python中创建一个可以在其他类之间共享的模块或对象的正确方法是什么?

我知道我可以自己构造Singleton,但我想使用Python的功能。


也许这篇文章可以帮到你,它们提出了一个类似的问题:https://dev59.com/Ho_ea4cB1Zd3GeqPR7ji - Molessia
1
@AlessiaM 那个链接指的是一个完全不同的问题。 - Dolda2000
2个回答

3
通过设置断点,我可以看到当Game导入Player时,Player会将state_manager中的x值设为12。 我相当确定你在检查方面做错了什么,因为你引用的set_x函数至少有问题...
x=45
def set_x(value):
    x=value

...这并不是你想象中的那样。由于在set_x的作用域内给x赋值,它并不引用全局(模块级别)变量x,而是引用一个本地变量x,该变量随即被丢弃并从堆栈帧中移除。实际上,静态赋值的存在有效地声明了Python中的本地变量。解决方法是将x声明为引用全局变量:

x=45
def set_x(value):
    global x
    x=value

我刚刚再次运行了我的代码,并在x=value下设置了断点(我卡在一个虚拟行y=5上,只是为了有一个放置断点和x=45中的x的地方),结果x确实从45变成了12。 然而,添加建议的全局x确实解决了我的问题,因此我倾向于认为我的IDE可能会误报。 - Richard210363
@Richard210363 如果是这样,那么你的调试工具可能有问题,因为x在这种情况下显然是一个局部变量。 - Dolda2000
我们的评论交叉了 :-) - Richard210363

2

在任何试图全局设置变量 x 的函数中,您需要声明它为全局变量:

def set_x(value):
    global x
    x=value

没有全局声明,x只是一个函数本地变量。

一般来说,如果函数在任何地方分配给一个变量,那么该变量是本地的,除非它被明确声明为global(或nonlocal)。如果函数仅读取变量而不设置它,则变量从更高的作用域(例如全局或上层引用)中获取。


全局的或者非本地的。 - Ecir Hana
@EcirHana 我编辑了我的答案,提到了 nonlocal - Tom Karzes

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