类继承中如何保留变量?子类调用父类方法遇属性缺失怎解决?
要保证类里的变量在继承过程中不“失踪”,主要有两种实用的方式:
用类级别的属性(类变量):直接在类的顶层、所有方法外面定义的变量,属于整个类的资源,子类会自动继承,除非你在子类里特意重写它。举个例子:
class Parent: shared_value = "这个变量子类能直接用" class Child(Parent): pass print(Child.shared_value) # 会输出:这个变量子类能直接用小贴士:如果子类修改了这个类变量,只会影响子类自己的版本,不会改掉父类的原值。
子类初始化时必须调用父类的
__init__:如果变量是在父类的构造方法__init__里定义的实例变量,子类的__init__一定要调用super().__init__(),不然父类的初始化逻辑根本不会执行,那些实例变量自然就不会被创建。比如:class Parent: def __init__(self): self.instance_val = "父类的实例变量" class Child(Parent): def __init__(self): super().__init__() # 这行不能少! self.child_val = "子类自己的变量" kid = Child() print(kid.instance_val) # 正常输出:父类的实例变量
先扫一眼你代码里的几个小问题,再解决核心报错:
首先修正语法错误
你的代码里有两处明显的语法问题:
def stop:漏了括号,应该写成def stop(self):self.color = blue里的blue是字符串,得加引号,改成self.color = "blue"
然后补全父类初始化调用
StopSign继承了Car,但它的__init__没调用父类的构造方法,这会导致Car里的初始化逻辑跑不起来,虽然不是这次报错的直接原因,但不补的话后面肯定会出别的问题,所以一定要加上super().__init__()。
核心问题:movement_code还没创建就被调用了
你在stop()里直接调用self.movement_code.kill(),但movement_code是在go()方法里才赋值的。如果go()从来没被调用过,self.movement_code根本就不存在,这时候调用stop()当然会报“找不到属性”的错。
给你两种解决思路:
思路一:在父类构造方法里先初始化movement_code
不管go()有没有被调用,先让这个属性存在,比如初始化为None,然后在stop()里先判断再执行:
class Car: def __init__(self): self.color = "blue" self.movement_code = None # 先把属性创建出来 def go(self): # 假设movement_function是你已经定义好的对象 self.movement_code = movement_function def stop(self): # 先检查是否存在,再调用kill() if self.movement_code is not None: self.movement_code.kill() class StopSign(Car): def __init__(self): super().__init__() # 调用父类初始化 # 这里写你的子类初始化代码 def active(self): self.stop()
思路二:确保调用active()前先调用go()
如果你的业务逻辑里,stop()必须在go()之后执行,那可以在active()里加个检查,要么提示用户先调用go(),要么自动帮用户调用:
class StopSign(Car): # ...其他代码... def active(self): if self.movement_code is None: # 可以抛异常提示,或者自动执行go() raise ValueError("得先让车跑起来啊!先调用go()方法") # 或者直接写 self.go() self.stop()
最后给你一个完整的可运行示例
假设movement_function是一个带有kill()方法的对象,完整代码如下:
# 模拟你的movement_function,根据实际情况替换 class MovementController: def kill(self): print("车停下来啦!") movement_function = MovementController() class Car: def __init__(self): self.color = "blue" self.movement_code = None def go(self): self.movement_code = movement_function def stop(self): if self.movement_code: self.movement_code.kill() class StopSign(Car): def __init__(self): super().__init__() # 子类初始化代码 def active(self): self.stop() # 测试一下 stop_sign = StopSign() stop_sign.go() # 先让车启动 stop_sign.active() # 触发停车,输出:车停下来啦!
内容的提问来源于stack exchange,提问作者John Applestein

