Python - 实例变量访问
我现在正在制作一个游戏。我有两个类,我想让一个类能够访问另一个类的实例变量。我不太确定这样做是否可行,或者该怎么做。
这两个类在某个时候都继承了一个叫做 gameEngine 的类。
gameEngine <- Game
gameEngine <- SuperSprite <- Character <- Enemy
gameEngine <- SuperSprite <- Character <- Player
我的 Game 类创建了一个对象的实例变量 self.player = Player(self)
,我想在 Enemy 类中使用这个变量,这样我就可以写 self.player.x
。这样我就可以在敌人类中制作 AI,让它知道我的玩家的位置。你有什么建议吗?我可能逻辑上有问题,所以任何帮助都非常感谢。如果我需要发布我的代码或者其他信息,请告诉我。
另外,我一直在尝试把一个对象传递给一个函数。这样 bob 就可以在游戏类中获取 enemyAI。但是我遇到了一个错误,提示 'Enemy' 对象不可调用。尽管它传递了对象并执行了函数,打印出信息后就结束了。但是如果我把 self.enemyAi(self.bob)
移到点击条件里面,它就能正常工作。
if self.enemyWeakBtn.clicked:
print "spawning enemey"
self.bob = Enemy(self)
self.enemies.append(self.bob)
self.enemyGroup = self.makeSpriteGroup(self.enemies)
self.addGroup(self.enemyGroup)
self.enemyActive = True
elif self.enemyActive:
print self.bob
self.enemyAi(self.bob)
print " active"
2 个回答
这个错误很可能是因为没有为敌人(Enemy)类定义一个构造函数。通过运行:
self.bob = Enemy(self)
它会在Enemy
类中寻找一个叫__init__(self, arg1)
的函数。如果这个函数没有提供,Python就无法把Enemy
当作一个“可调用的”对象,这意味着你不能像使用函数那样使用它,或者在这种情况下,不能用来调用一个带有一个参数的构造函数。
如果我理解得没错,你是想让敌人(Enemy)的实例能够访问玩家(Player)的实例。
有两种方法可以实现这个目标。我现在在我的程序中使用第二种方法,并计划添加第一种方法。
第一种方法是让某个类拥有一个实例,然后通过调用这个类的方法来获取这个实例。
class Game:
instance = False
def __init__(self):
if self.__class__.instance:
raise RunTimeError("Game has already been initialized.") # RunTimeError might be a bad choice, but you get the point
self.__class__.instance = self
@classmethod
def getInstance(cls):
return cls.instance
##>>> g = Game()
##>>> g
##<__main__.Game instance at 0x02A429E0>
##>>> del g
##>>> Game.getInstance()
##<__main__.Game instance at 0x02A429E0>
##>>>
## Here you can have, in your enermy class, g = Game.getInstance(). And g.player will be able to access the player instance, and its properties
第二种方法是我正在使用的。这种方法是让游戏类(Game)管理游戏中的所有内容。也就是说,游戏中的所有东西都是游戏类的一个变量。此外,每个游戏变量(比如玩家)都会有一个叫做“game”的属性,这个属性指向游戏的实例。
举个例子:
class Player:
def __init__(self, game):
self.game = game
print self.game.enermy
class Game:
def __init__(self):
self.enermy = "Pretend I have an enermy object here"
self.player = Player(self)
##>>> g = Game()
##Pretend I have an enermy object here
##>>> g.player.game.enermy
##'Pretend I have an enermy object here'
##>>>
## Iin your enermy class, self.game.player will be able to access the player instance, and its properties
有些人可能会对第二种方法提出异议,我也看到多了一步的确有点麻烦。也许有人可以帮忙比较一下这两种方法的优缺点。
还有一种组合方法,我希望能转向这种方法,但这会引发一些问题,比如你需要先在文件中放哪一个类,否则可能会出现“玩家未定义”或“游戏未定义”的错误。不过我觉得可以通过把这两个类分到不同的文件中来解决这个问题。
class Player:
def __init__(self):
self.game = Game.getInstance()
class Game:
instance = False
def __init__(self):
if self.__class__.instance:
raise RunTimeError("Game has already been initialized.") # RunTimeError might be a bad choice, but you get the point
self.__class__.instance = self
@classmethod
def getInstance(cls):
return cls.instance