我有一些代码来解决一个名为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 ++项目,我很喜欢它,虽然类实例是全局的,但没有看到任何问题。
答案 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中的每个赋值都意味着复制引用值,因此共享对赋值对象的访问。这样,实际上不需要全局变量,也没有理由使用全局变量。
使用局部变量,语法再次保持不变。