如何用Python类装饰器检查类是否重写了object的特定方法?
检查类是否重写特定方法的Python风格类装饰器实现
核心思路
要判断子类是否重写了从object继承的方法(比如__str__),最直接且符合Python风格的方式是检查类自身的__dict__中是否存在该方法——子类重写方法时,这个方法会被存入自身的__dict__;如果只是继承父类的方法,子类__dict__里不会有这个键。
没必要用mro()遍历或__bases__查找,原因如下:
dir(kls)会返回包括继承方法在内的所有属性,根本区分不出是不是子类自己写的;- 用
getattr(kls, "__str__") == object.__str__判断有漏洞:如果中间父类重写了__str__但子类没动,getattr拿到的是中间父类的方法,和object.__str__不相等,会误判成子类重写了。
正确实现代码
def check_overridden_method(method_name: str): # 做个通用装饰器工厂,支持检查任意方法,复用性更强 def decorator(kls: type) -> type: if method_name in kls.__dict__: print(f"类 {kls.__name__} 已重写 {method_name} 方法") else: print(f"类 {kls.__name__} 未重写 {method_name} 方法") return kls return decorator # 专门针对__str__方法的装饰器 check_str_method = check_overridden_method("__str__") @check_str_method class ChildClass1: pass @check_str_method class ChildClass2: def __str__(self): return "I HAVE OVERRIDDEN __str__" # 测试输出 obj1 = ChildClass1() obj2 = ChildClass2() print("obj1...", str(obj1)) print("obj2...", str(obj2))
额外说明
- 通用化设计:把装饰器做成工厂模式,传入不同方法名就能检查对应的方法(比如
__repr__、__eq__),不用重复写装饰器逻辑。 - 什么时候需要用mro?:如果你的需求是检查整个继承链里有没有类修改过目标方法(而不是当前子类是否重写),那才需要遍历
kls.mro(),逐个检查每个类的__dict__。但如果只是判断当前子类自己有没有重写,__dict__完全够用。
内容的提问来源于stack exchange,提问作者Toothpick Anemone
相关产品推荐
相关产品推荐

