Python中super().__init__(**kwargs)及多重继承使用问题求助
Python中super()用法问题解答
咱们逐个拆解你遇到的两个问题,同时也会聊聊super()结合**kwargs的正确姿势,以及多重继承里super()的使用要点。
问题1:输出中额外出现None的原因
先看你的代码里的get_rate方法:
def get_rate(self): print('The hourly rate of {} is {} '.format(self.firstname, self.rate))
这个方法内部用print输出内容,但它没有返回值——Python中,没有return语句的函数默认会返回None。当你执行print(hourlystaff1.get_rate())时,其实是两步操作:
- 调用
get_rate(),它自己会打印出The hourly rate of Bob is $15 - 打印这个方法的返回值,也就是
None
所以最终输出会多出一个None。
修正方案(二选一):
- 方案1:让
get_rate返回字符串,外部再打印:def get_rate(self): return 'The hourly rate of {} is {} '.format(self.firstname, self.rate) # 调用时 print(hourlystaff1.get_rate()) - 方案2:直接调用
get_rate,不用print包裹:def get_rate(self): print('The hourly rate of {} is {} '.format(self.firstname, self.rate)) # 调用时 hourlystaff1.get_rate()
另外补充:你的Employee类里all_staff列表没有初始化,记得加上all_staff = []类属性,否则会报错。
问题2:TypeError的原因与修正
你这段代码的错误点有好几个,咱们逐个说:
- 参数定义不匹配:
Hourly的__init__只定义了self和rate两个参数,但你实例化时传了5个位置参数('Bob', 'Bar', '23', '12/1/2019'),超出了方法的参数接收范围,直接触发TypeError。 - 未定义
kwargs参数却使用:Hourly的__init__里写了super().__init__(**kwargs),但kwargs根本没在方法的参数列表里声明,会导致NameError(如果前面的TypeError没触发的话)。 - 父类参数未传递:你想给
Employee传递的firstname、lastname等参数,没有在Hourly的__init__里处理,也没传给父类。 __str__方法格式字符串参数不匹配:你的__str__里写了6个占位符,但只传了5个参数,会触发IndexError。
正确结合super()与**kwargs的写法
核心思路是:每个子类只处理自己专属的参数,把剩下的参数通过**kwargs传递给父类,让父类去处理它关心的参数,这样在继承链(尤其是多重继承)中参数传递会更灵活。
修正后的代码:
class Employee: def __init__(self, firstname='', lastname='', age='', dob='', **kwargs): # 先处理当前类的参数,再把剩余kwargs传给父类(这里父类是object,空kwargs不会报错) super().__init__(**kwargs) self.firstname = firstname self.lastname = lastname self.age = age self.dob = dob class Hourly(Employee): # 接收自己专属的rate参数,用**kwargs接收父类需要的所有其他参数 def __init__(self, rate='', **kwargs): self.rate = rate # 把kwargs传给父类,父类会处理firstname、lastname等参数 super().__init__(**kwargs) def __str__(self): # 修正占位符和参数的匹配问题 return "{} {}\nAge: {}\nDOB: {}\nHourly Rate: {}".format( self.firstname, self.lastname, self.age, self.dob, self.rate ) def get_rate(self): print('The hourly rate of {} is {} '.format(self.firstname, self.rate)) # 用关键字参数传递,清晰不易错 bob = Hourly(firstname='Bob', lastname='Bar', age='23', dob='12/1/2019', rate='$12') bob.get_rate()
super()与**kwargs结合的要点及多重继承注意事项
结合**kwargs的核心优势
它能让你在继承链中避免重复定义父类的参数,每个类只关注自己的专属参数,剩下的交给上层父类处理,极大提升代码的可维护性,尤其是在多重继承场景下。
多重继承中super()的关键要点
- 遵循方法解析顺序(MRO):
super()不是直接调用父类方法,而是按照Python的MRO顺序调用继承链中的下一个类的方法。你可以通过ClassName.__mro__查看某个类的MRO顺序,比如print(Hourly.__mro__)。 - 所有类的
__init__都要调用super():确保继承链上的每个类都能完成初始化逻辑,并且要把未处理的**kwargs传递下去,直到继承链的末端(通常是object类,它的__init__不接受额外参数,所以最后要确保没有多余的kwargs)。 - 优先使用关键字参数:位置参数在多重继承中很容易导致参数匹配混乱,用关键字参数传递能明确每个参数的归属,避免错误。
- 不要忽略
super()的参数:在某些复杂的多重继承场景下,可能需要显式指定super()的类和实例参数(比如super(ChildClass, self).__init__(**kwargs)),不过Python3中默认的无参super()已经能处理大部分场景。
内容的提问来源于stack exchange,提问作者goblin_rocket
相关产品推荐
相关产品推荐

