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

Class Python,一次实例化类并在其他类中使用它们的正确方法,class,python-3.x,instance,global,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): ... # CH

我有一些用于解决名为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类具有必须在所有其他类(如board维度、数字坐标等)之间共享的信息,我还希望它被实例化一次,如果可能的话,防止依赖注入(例如,不必要地将文件名传递给每个类的init方法)

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

C验证类用途: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()
但我可能读了太多关于地球人是如何邪恶的。另外,includes.py中的代码有点粗糙,因为如果我更改导入顺序,程序将无法运行,并抱怨无法导入某些名称

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

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


所以我的问题是什么是更好的方法来构建这个?我已经阅读过单模式(可能是过度的,因为它是一个小项目),以及对C++和PHP这样的多种语言的无尽的方式。实际上,我做的方式类似于“ExtLeC类实例”,在C++中做的方式,很久以前我在一个C++项目中工作,我喜欢它,但没有发现任何问题,虽然类实例是全局的。但是,您可能需要一个将某些内容封装在一起的单例模式。我从C++和Python的经验是,你可以很好地使用语言的混合字符,并在单角色中使用一个模块。(如果您仔细想想,模块变量扮演着单一成员变量的角色,模块中的普通函数类似于单一成员的方法。)

通过这种方式,我建议将board功能放入
board.py
启发式功能,放入
启发式.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中的每个赋值都意味着复制引用值,从而共享对赋值对象的访问。这样,实际上就不需要全局变量,也没有理由使用全局变量


使用局部变量,语法仍然保持不变。

感谢您的提示,我想这样做可以保持语法与我喜欢的完全相同,但对于更大的项目,这可能不是正确的方法。我还实现了一个小型依赖项注入,但komodo edit 7失去了以这种方式自动完成的功能。更新。我不知道如何更新您实现了依赖项注入(您确切的意思是什么)。事实是,你应该选择你能找到的最自然的解决方案。如果编辑器失去了跟踪你思维的能力,这可能是解决方案不太自然的症状。或者编辑器不太聪明。无论如何,你编写代码并不是为了让编辑满意:)我真的不确定你的更新,你的意思是仅仅创建我需要的对象作为类中的局部变量吗?例如,如果需要CNurikabe中的CHeuristics对象,我是否会在类代码之前:Heuristics=CHeuristics()?当然也有相应的意义。关于依赖注入,我刚刚将已经创建的对象传递给需要它的对象的init。例如,Nurikabe=CNurikabe(Board、启发式、验证),其中Board、启发式和验证已经创建。然后我在类中称之为:self.Heuristics.dosomething(),然后我们谈论的是完全相同的事情。你叫它注射,我叫它任务。如果将say
启发式
传递给另一个
CNurikabe
,则两个
CNurikabe
实例将共享相同的启发式对象。实际上,对象是在赋值给局部变量时首先创建的还是从外部传入的并不重要。只有当你想分享它时,它才会有所不同。我认为这个方法很好。现在我理解了您在更新中的意思并实现了它,语法仍然是一样的(我通过init方法传递它,这是一样的,但必须在self之前加上前缀。对于每个传递的参数),无论如何,我想这有助于更好的单元测试,我终于理解了这个概念并避免了全局变量,谢谢。