Python,一次实例化类的正确方法,并在其他类中使用它们

时间:2013-02-02 06:28:35

标签: class python-3.x instance global

我有一些代码来解决一个名为nurikabe的益智游戏,最近我一直在将它重写为OOP(仍然在学习)并具有以下结构:

# CNurikabe.py
from includes import Board, Validation, Heuristics
class CNurikabe(object):
    ...

# CValidation.py
from includes import Board, Heuristics
class CValidation(object):
    ...

# CHeuristics.py
from includes import Board
class CHeuristics(object):
    ...

# CBoard.py
class CBoard(object):
    def __init__(self, filename):
        # Vars shared by every class
        self.x, self.y, self.z, self.t = self.parseData(filename)

# run.py
from CNurikabe import CNurikabe
nurikabe = CNurikabe()
nurikabe.solve('output')

# includes.py
from CBoard import CBoard   
Board = CBoard('data.dat')

from CHeuristics import CHeuristics
Heuristics = CHeuristics()

from CValidation import CValidation
Validation = CValidation()

CBoard类的信息必须在所有其他类之间共享(例如电路板尺寸,数字坐标等),我也希望它实例化一次,如果可能的话,防止依赖注入(不必要地将文件名传递给每个例如,类init方法)

需要这些类才能访问以下内容:

CValidation类使用:CBoard和CHeuristics

CHeuristics课程使用:CBoard

CNurikabe课程使用:CBoard,CValidation和CHeuristics

我的代码,按预期工作。我可以按照我想要的方式在其他类中调用其他类的方法,例如:

# CNurikabe.py:
class CNurikabe(object):
    def someFunc(self):
        for i in range(Board.dimensionx):
            Heuristics.doSomeStuff()
            Validation.doSomeMore()

但我读过太多关于全局变量是邪恶的。另外include.py中的代码有点hackish,因为如果我更改了导入的顺序,程序将无法运行,抱怨无法导入某些名称。

我还尝试了另一种方法,只是全局实例化CBoard类,然后,对于其他类,创建我需要的类的实例。但我觉得这有点重复,例如,在每个班级中创建一个独特的全球CHeuristics实例,但仍然无法解决CBoard全球问题。

我还想过在每个类的 init 中创建一个实例,但是代码会非常冗长,不得不调用例如:self.Heuristics.doSomeStuff()

所以我的问题是什么是更好的方法来构建它?我已经读过关于单例模式(这可能是过度的,因为它是一个小项目),以及为C ++和PHP等多种语言进行无休止的方式。实际上,我正在做的方式类似于“extern类实例”;在C ++中这样做的方法,很久以前我正在研究一个具有那种风格的C ++项目,我很喜欢它,虽然类实例是全局的,但没有看到任何问题。

1 个答案:

答案 0 :(得分:0)

全球是邪恶的。但是,您可能需要一个将一些东西封装在一起的单例模式。我从C ++和Python的经验是,您可以很好地使用该语言的混合字符,并使用单例角色的模块。 (如果你更多地考虑它,模块变量扮演单例成员变量的角色,模块中的普通函数类似于单例的方法。)

这样我建议将电路板功能放入board.py启发式功能{...}},...,将方法转换为函数,heuristic.py转换为self.variable并使用:

variable

考虑import board import heuristic import validation ... class CNurikabe: # the explicit (object) base class is not needed in Python 3 def someFunc(self): for i in range(board.dimensionx): heuristics.doSomeStuff() validation.doSomeMore() 关于获取对单例实例的引用 - 实际上是因为存在模块对象的单个实例。它在语法上与旧代码相同 - 除了获取实例(模块)将更容易。

更新:一旦您需要更多实例,您应该再次考虑课程。但是,在Python中传递对象是非常便宜的操作 - 您只复制参考值(技术上是地址,即4或8个字节)。获得参考值后,您可以轻松地将其分配给局部变量。 (Python中的每个赋值都意味着复制引用值,因此共享对赋值对象的访问。这样,实际上不需要全局变量,也没有理由使用全局变量。

使用局部变量,语法再次保持不变。