0

ぬりかべというパズルゲームを解くためのコードがありますが、最近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()

しかし、私はグローバルがいかに悪であるかについて多分読みすぎました。また、includes.py内のコードは少しハックです。インポートの順序を変更すると、プログラムが実行されず、一部の名前をインポートできないという不満が出るためです。

また、別の方法を試しました。CBoardクラスをグローバルにインスタンス化し、他のクラスについては、必要なクラスのインスタンスを作成するだけです。しかし、それはちょっと反復的で、たとえば、各クラス内にCHeuristicsの一意のグローバルインスタンスを作成し、それでもCBoardグローバル問題を解決できないと感じました。

また、各クラスのinit内にインスタンスを作成することも考えましたが、コードは非常に冗長になり、たとえば、self.Heuristics.doSomeStuff()を呼び出す必要があります。

だから私の質問は、これを構造化するためのより良いアプローチは何でしょうか?シングルトンパターン(小さなプロジェクトなのでやり過ぎかもしれません)と、C++やPHPなどの複数の言語でそれを行うための無限の方法について読んだことがあります。実際、私がそれを行っている方法は、「externClassインスタンス」の方法に似ています。C ++でそれを行う方法は、ずっと前にそのスタイルのC ++プロジェクトに取り組んでいて、クラスインスタンスはグローバルでしたが、それが好きで、問題は見られませんでした。

4

1 に答える 1

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()

import boardモジュールオブジェクトのインスタンスが1つしかないため、シングルトンインスタンスへの参照を取得することと考えてください。また、構文的には古いコードと同じになりますが、インスタンス(モジュール)の取得が簡単になる点が異なります。

更新:さらにインスタンスが必要になったら、クラスでもう一度考える必要があります。ただし、Pythonではオブジェクトの受け渡しは非常に安価な操作です。参照値(技術的にはアドレス、つまり4バイトまたは8バイト)のみをコピーします。参照値を取得したら、それをローカル変数に簡単に割り当てることができます。(Pythonでのすべての割り当ては、参照値をコピーすることを意味します。したがって、割り当てられたオブジェクトへのアクセスを共有します。このように、実際にはグローバル変数は必要なく、グローバル変数を使用する言い訳もありません。

ローカル変数を使用しても、構文は同じままです。

于 2013-02-02T09:41:09.783 に答える