如何比较两个Python类中同名方法的代码是否一致?
比较两个Python类的方法代码一致性
问题场景
需要对比两个Python类的方法,识别出代码完全一致和存在差异的方法。例如以下两个类:
class A: def func1(self): return 1 def func2(self): return 2 class B: def func1(self): return 1 def func2(self): return 1000
其中func1的代码逻辑完全相同,func2存在差异,但现有实现无法正确识别。
无效实现及问题分析
以下代码尝试直接对比方法对象,结果错误地将两个方法都判定为不同:
from collections import defaultdict # 获取每个类的方法列表 a_funcs, b_funcs = dir(A), dir(B) all_funcs = set(a_funcs).union(b_funcs) all_funcs_no_builtins = [f for f in all_funcs if not f.startswith('__')] # 对比方法 equal_funcs = defaultdict(list) for f in list(all_funcs_no_builtins): if ((f in a_funcs) and (f in b_funcs)): a_code = getattr(A, f) b_code = getattr(B, f) if a_code == b_code: equal_funcs['same'].append(f) else: equal_funcs['different'].append(f) else: equal_funcs['different'].append(f) # 输出结果 print("Total number of methods:", len(all_funcs_no_builtins)) # 2 print("Number that are the same:", len(equal_funcs['same'])) # 0 print("Same:", equal_funcs['same']) # [] print("Different:", equal_funcs['different']) # ['func1', 'func2']
问题原因
- 直接对比方法对象(
a_code == b_code)是比较对象的引用地址,而非代码内容。即使两个方法逻辑完全一致,它们是不同的函数对象,所以结果为False。 - 仅对比
.__code__.co_code也可能失败,因为字节码可能会因为常量存储位置、局部变量名顺序等细节差异,导致逻辑相同的代码字节码不同。
正确解决方法
可以通过对比方法的源码或者全面对比函数代码对象的关键属性来实现准确判断:
方法1:使用inspect模块获取源码对比
利用inspect.getsource()获取方法的源码文本,直接对比文本内容:
import inspect from collections import defaultdict class A: def func1(self): return 1 def func2(self): return 2 class B: def func1(self): return 1 def func2(self): return 1000 # 获取每个类的方法列表 a_funcs, b_funcs = dir(A), dir(B) all_funcs = set(a_funcs).union(b_funcs) all_funcs_no_builtins = [f for f in all_funcs if not f.startswith('__')] equal_funcs = defaultdict(list) for f in all_funcs_no_builtins: if f in a_funcs and f in b_funcs: try: # 获取方法的源码文本 a_source = inspect.getsource(getattr(A, f)) b_source = inspect.getsource(getattr(B, f)) if a_source == b_source: equal_funcs['same'].append(f) else: equal_funcs['different'].append(f) except TypeError: # 处理无法获取源码的情况(如内置方法) equal_funcs['different'].append(f) else: equal_funcs['different'].append(f) # 输出结果 print("Total number of methods:", len(all_funcs_no_builtins)) # 2 print("Number that are the same:", len(equal_funcs['same'])) # 1 print("Same:", equal_funcs['same']) # ['func1'] print("Different:", equal_funcs['different']) # ['func2']
方法2:对比函数代码对象的关键属性
如果无法获取源码(例如代码已被编译为字节码),可以对比__code__对象的多个核心属性,包括字节码、常量、局部变量等:
from collections import defaultdict class A: def func1(self): return 1 def func2(self): return 2 class B: def func1(self): return 1 def func2(self): return 1000 def is_method_equal(a_method, b_method): """判断两个方法的代码逻辑是否一致""" if not hasattr(a_method, '__code__') or not hasattr(b_method, '__code__'): return False a_code = a_method.__code__ b_code = b_method.__code__ # 对比核心属性:字节码、常量、局部变量、参数数量等 return (a_code.co_code == b_code.co_code and a_code.co_consts == b_code.co_consts and a_code.co_varnames == b_code.co_varnames and a_code.co_argcount == b_code.co_argcount) # 获取每个类的方法列表 a_funcs, b_funcs = dir(A), dir(B) all_funcs = set(a_funcs).union(b_funcs) all_funcs_no_builtins = [f for f in all_funcs if not f.startswith('__')] equal_funcs = defaultdict(list) for f in all_funcs_no_builtins: if f in a_funcs and f in b_funcs: a_method = getattr(A, f) b_method = getattr(B, f) if is_method_equal(a_method, b_method): equal_funcs['same'].append(f) else: equal_funcs['different'].append(f) else: equal_funcs['different'].append(f) # 输出结果 print("Total number of methods:", len(all_funcs_no_builtins)) # 2 print("Number that are the same:", len(equal_funcs['same'])) # 1 print("Same:", equal_funcs['same']) # ['func1'] print("Different:", equal_funcs['different']) # ['func2']
内容的提问来源于stack exchange,提问作者Scott
相关产品推荐
相关产品推荐

