3

我是编程新手,最近学习了 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

4 回答 4

5

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

但是,不要为了上课而让他们上课。如果你真的有那么多变量,也许你应该考虑将你的程序分成多个模块。

另请理解,您不能像在 JavaScript 中那样在 Python 中真正创建全局变量。您的变量始终位于模块下。

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

A = 42

模块 b.py:

import a

print(A)

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

无需在类下填充变量。它们位于作为命名空间的模块下,没有任何问题

于 2012-12-25T16:52:00.527 回答
2

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

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

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
于 2012-12-25T16:52:31.450 回答
2

没有必要仅仅为了存储变量而创建一个类。仅当您确实需要该类的多个实例时才需要该类,每个实例都有唯一的值。

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

配置文件

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

主文件

import conf

conf.GAME_STATE['score'] = 100

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

于 2012-12-25T17:42:14.077 回答
1

不!!!建立一个不会VariableBox帮助你!

只需使用您想要的 var,无论它适用于何处。如果你有太多的全局变量,那么什么应该被认为是全局的,什么应该与特定的结构有关,这是一个相当大的问题。甚至难以命名变量或创建数组,而不是var1, var2, var3, ....

类是为构建对象而设计的,即,用于创建具有不同特性但具有相同基础的事物。有价值的类在某种程度上定义了一个实体,以及这个实体的主要行为。

编辑

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,您可以聚合相关信息,因此您不会在即将到来的函数中拥有无穷无尽的参数列表。

无论如何,我无法告诉您哪个最好用;有很多人在研究这些模块化问题,而我不是其中之一,所以这只是我对在您的应用程序上可以做得很好的观点。

于 2012-12-25T16:54:42.150 回答