を使用して test.py でロボットを作成してnewRobot = Robot('rbt1')
から、 を実行する必要がありますatlas.add_robot(newRobot)
。これを行うには、ロボット名ではなく、ロボット全体を渡します。Atlas は Atlas であるため、ロボットを初期化しようとしないでください。Atlases が何をするかだけを心配する必要があります: ロボットがどこにいるかを追跡します。
プログラミングで学ぶべき良い概念は、コードのどの部分が何かに触れることができるかということです。この場合、test.py でロボットを作成し (触ることができるようにするため)、それを Atlas に渡します (Atlas が触ることができるようにするため)。それが事実上あなたの質問の核心です。この問題に対処する一般的な方法を次に示します。
- 制御フローを変更してコードをリファクタリングし、この問題が発生しないようにします (以下のデモのように)。
- パラメーター/アクセサーを渡す - オブジェクトについて知っていること (この場合は名前) に一致するロボットを提供するようにオブジェクトに依頼します。
- 浅いデータ構造 - Atlas は辞書のように動作する浅いシェルであり、それを辞書のように扱うだけです (
yourAtlas.robotsToZones(...)
以下で行うのとは対照的に)。
- グローバルの乱用 - これは絶対に行わないでください。これはひどいプログラミングです
- クロージャー - 関数内で関数を定義する場合 (おそらくクラス内のクラスですが、それは見苦しくなります)、内側の関数は外側の関数の変数にアクセスできますが
nonlocal
、python でキーワードを使用して意図を宣言する必要があります。これを行う
この問題が発生しないように制御フローを変更するには、完全に作成されたロボットを渡すことで Atlas をより柔軟にすることができます。やっぱりアトラスです。アトラスがロボットの作成を担当するのはなぜですか?
from collections import *
class Atlas(object):
def __init__(self):
self.zones = defaultdict(set)
def add_robot(self, robot, zone='forest')
self.robots[zone].add(robot)
別の方法として、次のようにすることもできます: (ロボットがゾーンを変更することが予想されるため、おそらくより適切です)
class Atlas(object):
def __init__(self):
self.robotsToZones = {}
def add_robot(self, robot, zone='forest')
self.robotsToZones[robot.name] = zone
def robotsInWorlds(self):
return self.robotsToZones.keys() # .keys() not necessary, but hides representation
(速度を気にするなら、実際には両方を行うことができます...しかし、通常は速度を気にするべきではなく、両方の構造が同期していることを確認する必要があります)
また、データは 1 つの場所に存在する必要があります。あなたの場合、Robot と Atlas の両方が、ロボットがどのゾーンにいるかを知る必要があります。これは、これら 2 つの値が常に等しく、同期していることを確認する必要があるため、不必要な頭痛や複雑さ、さらにはバグにつながるため、悪いことです。解決策は、robot.py でロボットがどのゾーンにいるかを無視することです。
class Robot(object):
def __init__(self, name):
self.name = name
ロボットは自分がどこにいるかを把握する必要はありません。それがアトラスの仕事です。test.py がロボットの場所を知る必要がある場合、 のようなことを実行myAtlas.whereIs(myRobot)
できますreturn self.robotsToZones[robot.name]
。これは、関心のモジュール化および分離として知られています。
(補足:上記は、どのロボットがどのゾーンにいるかを追跡するための他のメカニズムがあり、座標がないことを前提としています。step()
関数に座標を処理させる場合は、グローバルまたはパーのどちらを使用するかを決定する必要があります。 -ゾーンの座標. 定義する必要があるのはゾーンの境界をどのようにつなぎ合わせるかだけなので、後者のケースはおそらく簡単です; ただし、アトラスに重複しない (バグの可能性がある) 境界を定義させれば、最初のケースを行うことができます。ゾーンはどこにあります. ゾーンの境界を定義する道しるべを持ち、ロボットが最も近い道しるべのゾーンにいるようなこともできるかもしれません. ただし、各ゾーンを同じサイズの長方形で作成し、グリッドを介して表現できるようにするのがおそらく最も簡単です. .)