Python面向对象:使用m、a实例与循环内临时实例化的差异问题
Python类实例写法差异导致运行结果不符问题
问题背景
我是Python初学者,最初认为下述两段代码逻辑完全一致,但实际运行结果差异显著,特此咨询两种写法中实例使用逻辑的核心区别。
错误代码
class Enemy: name = "" lives = 0 def __init__(self, name, lives): self.name = name self.lives = lives def hit(self): self.lives -= 1 if self.lives <= 0: print(self.name + ' killed') else: print(self.name + ' has '+ str(self.lives) + ' lives') class Monster(Enemy): def __init__(self): super().__init__('Monster', 3) class Alien(Enemy): def __init__(self): super().__init__('Alien', 5) # 错误逻辑段 while True: x = input() if x == 'exit': break if x=='gun': Monster().hit() if x=='laser': Alien().hit()
正确代码
class Enemy: name = "" lives = 0 def __init__(self, name, lives): self.name = name self.lives = lives def hit(self): self.lives -= 1 if self.lives <= 0: print(self.name + ' killed') else: print(self.name + ' has '+ str(self.lives) + ' lives') class Monster(Enemy): def __init__(self): super().__init__('Monster', 3) class Alien(Enemy): def __init__(self): super().__init__('Alien', 5) # 正确逻辑段 m = Monster() a = Alien() while True: x = input() if x == 'exit': break if x=='gun': m.hit() if x=='laser': a.hit()
实际测试表现
运行错误代码时连续输入三次
laser,每次输出均为Alien has 4 lives;运行正确代码时连续输入三次laser,依次输出Alien has 4 lives、Alien has 3 lives、Alien has 2 lives,符合生命值递减预期。
差异根本原因
两种写法的核心区别是类实例的生命周期和复用逻辑完全不同:
- 错误写法中,每次循环匹配到攻击指令时,都会临时执行
Monster()/Alien(),这行代码会当场创建一个全新的、初始生命值满值的类实例。对这个临时实例调用hit()扣1血后,因为没有变量持有这个实例的引用,它会被Python自动回收销毁。下一次再触发攻击指令时,又会创建一个全新的满血实例,扣1血后的结果自然永远是初始值减1,不会累计扣血效果。 - 正确写法中,进入循环前就提前创建了
m、a两个实例,且用变量持续持有这两个实例的引用,两个实例会一直存在于内存中。每次触发攻击指令时,都是在同一个已经存在的实例上调用hit()方法,生命值的修改会直接保存在对应实例的属性上,扣血效果会持续累计,符合预期。
打个通俗的比方:错误写法相当于每次要打外星人的时候,都当场刷新一个满血的新外星人打一枪,打完这个外星人就消失,下次打又是新的满血外星人;正确写法相当于提前把怪物和外星人都固定在场上,每次开枪打的都是场上已经存在的同一个目标,伤害自然会累加。
内容的提问来源于stack exchange,提问作者jack
相关产品推荐
相关产品推荐

