如何引用在不同对象中创建的对象

2024-04-25 10:03:53 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在用一个名为测试.py. 我只是在学习编程,所以这只是一个练习项目。有一个地图集(地图),我可以把多个'机器人'在一个地图。你知道吗

#test.py
from Atlas import Atlas
atlas = Atlas()
atlas.add_robot('rbt1')


#atlas.py
from Robot import Robot

class Atlas:

    def __init__(self):
        ...

    def add_robot(self, robot, zone = 'forrest'):
        self.robot = Robot(robot)
        print 'added robot %s to %s' % (robot, zone)


#robot.py
class Robot():

    def __init__(self, rbt, zone = 'forrest'):
        self.name = rbt
        print "%s initiated" % rbt

    def step(self, direction):
        ...

“我使用代码”atlas.add\机器人('rbt1')”将一个新机器人放入地图集。你知道吗

我希望能够用中的“rbt1.step('left')”之类的命令来控制机器人测试.py. 你知道吗


Tags: frompyselfaddzonedef地图机器人
3条回答

您应该能够引用由atlas.robotatlas中创建的robot,因为它是您存储它的地方。您可以创建一个指向该变量的新变量,如下所示:

rbt1 = atlas.robot

然后您应该能够引用您描述的内容:

rbt1.step('left')

请注意,如果希望atlas能够拥有多个机器人,则应考虑将机器人存储在listdict对象中。你知道吗

您应该将您的机器人添加到Atlas中的列表中。代替self.robot = Robot(robot),将robots = []添加到Atlas.__init__(),并在Atlas.add_robot(robot)中执行self.robots.append(Robot(robot))。然后可以通过列表(atlas.robots[0].step()atlas.robots[1].step()等)访问它们。你知道吗

你应该把你的机器人弄进去测试.py使用newRobot = Robot('rbt1'),然后执行atlas.add_robot(newRobot)。为此,我们传入一个完整的机器人,而不是机器人名称。阿特拉斯不应该试图初始化机器人,因为它是一个阿特拉斯。它应该只关心地图集的功能:跟踪机器人的位置。你知道吗

在编程中要学习的一个好概念是允许哪些代码片段接触某些东西。在本例中,我们将在测试.py(这样我们就可以触摸它),然后把它传给地图册(这样地图册就可以触摸它)。这实际上是你问题的核心。以下是一些处理此问题的一般方法:

  • 通过改变控制流重构代码,这样就不会有这个问题(如下面的演示)
  • 传入参数/访问器-要求对象为您提供与您所知道的匹配的robot(在本例中为名称)
  • 浅层数据结构—Atlas将是一个浅层shell,其行为类似于一个字典,您只需将其视为一个字典(与下面的yourAtlas.robotsToZones(...)相反)
  • 滥用globals-永远不要这样做,这是可怕的编程
  • 闭包-如果在函数中定义一个函数(甚至在类中定义一个类,但这很难看),那么内部函数可以访问外部函数中的变量,尽管您必须使用python中的nonlocal关键字来声明您的意图

改变控制流程,这样你就不会有这个问题:阿特拉斯可以通过传递一个完全制造的机器人变得更加灵活。这毕竟是一本地图集。为什么阿特拉斯会负责制造机器人?你知道吗

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

(如果你关心速度,你实际上可以两者兼得。。。但是你通常不应该关心速度,这需要确保两个结构是同步的)

你也应该有数据存在于一个地方。在你的例子中,机器人和阿特拉斯都需要知道机器人在哪个区域。这是不好的,因为您必须确保这两个值始终相等且同步,从而导致不必要的头痛和并发症,甚至可能是错误。解决方法是忽略机器人所在的区域机器人.py地址:

class Robot(object):
    def __init__(self, name):
        self.name = name

一个机器人永远不需要知道它在哪里,这是阿特拉斯的工作。如果测试.py需要知道机器人在哪里,它可以做一些类似myAtlas.whereIs(myRobot)的事情,它可以return self.robotsToZones[robot.name]。这被称为模块化关注点分离。你知道吗

(旁注:以上假设你有一些其他的机制来跟踪哪些机器人在哪个区域,而你没有坐标。如果使用step()函数处理坐标,则必须确定是全局坐标还是分区坐标。后一种情况可能更容易,因为您只需要定义区域的边界是如何缝合在一起的;不过,如果您让Atlas为哪个区域定义了非重叠(ick,可能的bug)边界,您可以执行第一种情况。你也可以做一些类似的事情,比如有路标来定义区域边界,机器人在最近的路标区域。尽管让每个区域由大小相等的矩形组成,通过网格表示,可能是最简单的。)

相关问题 更多 >