在类中包装全局变量(python)

时间:2012-12-25 16:41:06

标签: python oop global-variables

我是编程新手,最近学过python和面向对象编程的基础知识。我知道有很多全局变量通常是一个坏主意,我可以将它们全部放入一个类中。这是正确的方法吗?

class GameState(object):
    def __init__(self):
        self.variable1 = 1
        self.variable2 = 2
        self.list = [3, 4, 5]

g_state = GameState()

而且,如果我想访问g_state中的变量,那么最好的方法是什么?

将g_state传递给需要访问的函数/类? 实施getter并调用它们? 直接使用g_state.variable1?

或者有更好的方法吗?

编辑:更具体地说,我正在尝试使用pygame在python中编写游戏,并且正在考虑将我的游戏状态变量放入类中,以便不会有一堆全局变量。我不确定如何以良好的设计访问这些变量,所以我以后不会遇到麻烦。

4 个答案:

答案 0 :(得分:4)

你是对的,太多的全局变量不是一个好主意。污染的全局命名空间可能会导致错误。

然而,不要为了它而将它们放入课堂。如果你真的有很多变量,你应该考虑将你的程序分成多个模块。

另外请理解,你不能像在JavaScript中那样在Python中创建全局变量。您的变量始终作为模块的范围。

让我举一个例子来说明。模块a.py:

A = 42

模块b.py:

import a

print(A)

你得到了什么? NameError。为什么?因为变量A不是全局的,所以它在模块a下。您需要使用a.A来引用它。

没有必要在类下填充变量。它们位于模块下,充当命名空间,并且没有错误

答案 1 :(得分:2)

创建一个仅用于存储变量的类是没有必要的。如果您确实需要该类的多个实例,每个实例都具有唯一值,则只需要一个类。

但是对于单个全局状态,字典对象就足够了。如果需要,可以将其存储在专门用于配置和状态的模块中:

<强> conf.py

GAME_STATE = {
    'level': 0,
    'score': 0,
    'misc': [1,2,3],
}

<强> main.py

import conf

conf.GAME_STATE['score'] = 100

所以你的其他模块只能导入conf.py模块并访问状态字典。您可以在此对象中存储所需的任何类型。它还为您提供了一个方便的位置,可以根据需要添加将这些值序列化到磁盘的功能,并在将来的程序运行中将它们读回来,并将它们与配置选项一起保存。

答案 2 :(得分:1)

有两种方法可以访问变量:一个全局对象或将一个实例传递给一个函数。第一个也是一个坏主意。第二个更好。但是不要用所有变量创建单个对象! (见第一条评论)。

如果绕过一个物体,还有很多事情需要考虑。如果合适的话,一个好主意是将事物作为成员函数来实现。

class VariableBox(object):
    def __init__(self):
        self.variable1 = 1
        self.variable2 = 2
        self.list = [3, 4, 5]

    def do_something(self):
        self.variable1 = self.variable2 + 42
        return self.variable1

答案 3 :(得分:1)

NO !!!构建VariableBox将帮助您

只需使用您想要的var,无论它适用于何处。如果你有太多的全局变量,那么它应该被视为全局变量,而应该与特定结构有什么关系。甚至在命名变量或创建数组时遇到困难,而不是var1, var2, var3, ...

类用于构建对象,i。例如,用于创建具体不同但具有相同基础的东西。有价值的类可以在某种程度上定义一个实体,以及该实体的主要行为。

修改

Python不提供可见性约束,因此您无法通过简单地将数据填充到类中来保护数据;可以从类的实例所在的任何地方访问这些条目。

创建getter或只是维护一个类的实例只是决定使用哪个实例。为了保持清晰,最好为游戏制作一个控制器,这将在游戏资产和游戏玩法之间建立这种界面。

例如,在执行期间,您可以:

class Controller:

    def __init__():
        self.turn = 0
        self. ...

    def begin():
        self.turn += 1
        self.opening_scene()

class Gameplay:

    def __init__(self, num_players, turn, ...):
        self.turn = turn # if it happens you want to use this value in the game
        self.num_player = num_players

# Main loop
controller = Controller()
controller.num_players = int(raw_input("Number of players: "))

gameplay = Gameplay(controller.num_players, controller.turn)
while True:

    if gameplay.action == ...:
    elif ...:
        ...
    elif *next turn*:
        controller.next_turn() # to set things up to next turn
    else ...:
        ...

Controller内,您可能会聚合相关信息,因此您在即将推出的功能中不会有无穷无尽的参数列表。

无论如何,我无法告诉你哪个是最好用的;有很多人研究这些模块化问题,我不是其中之一,所以这只是我对你的应用程序可以解决的问题的看法。