Python类方法属性、self及类/静态方法使用报错排查
Python类方法差异说明与Module类修正方案
三类方法的核心区别
- 实例方法:默认第一个参数为
self,指向当前创建的实例,必须通过实例调用,可读写当前实例的独有属性,也可访问类共享属性 - 类方法:需要添加
@classmethod装饰器,默认第一个参数为cls,指向类本身,可通过类或者实例调用,只能读写类共享属性,无法访问单个实例的独有属性 - 静态方法:需要添加
@staticmethod装饰器,无强制默认参数,本质是归类管辖的普通函数,不需要访问类或实例的任何属性,可通过类或者实例调用
属性归属的实现规则
对应需要的属性特性,实现逻辑非常明确:
- 实例独有属性(
name、finite_state_machine):在__init__构造方法中通过self.属性名赋值,每个实例持有独立副本,修改互不影响 - 类共享属性(
modules_dictionary、call_stack):直接定义在类的顶层代码块(不要写在__init__里),所有实例共享同一份数据,任意位置修改后所有实例读取到的值同步更新
原代码的报错原因
- 方法装饰器缺失:
reading_file、message_stack不需要访问实例或类属性,没有加@staticmethod装饰器时,Python会默认把第一个传入的参数当做self处理,直接调用会报参数数量不匹配错误 - 命名冲突覆盖:定义了名为
fsm的实例方法,又在__init__里写self.fsm = self.fsm(...),赋值操作会直接把实例上绑定的方法替换成调用后的返回值,不仅本次调用容易出问题,后续也无法再正常调用fsm方法 - 重复IO开销:原写法两次调用
reading_file(),会重复读取磁盘文件,且共享属性只需要初始化一次,不需要每个实例创建时都重新计算 - 变量未定义:调用时传入的
modules变量没有提前赋值,属于笔误
修正后的完整代码
class Module: # 类共享属性,所有实例共用同一份数据 modules_dictionary = None call_stack = None _shared_initialized = False # 私有标记,避免重复初始化共享数据 def __init__(self, name): # 实例独有属性初始化 self.name = name self.finite_state_machine = None # 仅第一次实例化时初始化共享属性,避免重复读文件、重复计算 if not Module._shared_initialized: lines = Module.reading_file() Module.modules_dictionary = Module._build_modules_dict(lines) Module.call_stack = Module._build_message_stack(lines, Module.modules_dictionary) Module._shared_initialized = True # 调用内部方法生成当前实例独有的状态机,方法名加前缀避免和属性重名 self.finite_state_machine = self._generate_fsm(Module.call_stack, self.name) def _generate_fsm(self, call_stack, module_name): """实例方法:生成当前实例专属的有限状态机,替换原fsm方法避免命名冲突""" # 此处填写原fsm方法的业务逻辑 pass @staticmethod def reading_file(path="default_path"): """静态方法:文件读取逻辑,不依赖类或实例属性""" # 此处填写文件读取逻辑,返回按行分割的内容列表 pass @classmethod def _build_modules_dict(cls, lines): """类方法:构建所有实例共享的模块字典""" # 此处填写原modules_dictionary方法的业务逻辑,返回构建好的字典 pass @staticmethod def _build_message_stack(lines, modules_dict): """静态方法:构建所有实例共享的调用栈""" # 此处填写原message_stack方法的业务逻辑,返回构建好的call_stack pass
效果验证
- 执行
m1 = Module('Alpha')时,会自动完成一次文件读取、共享属性计算,生成Alpha对应的独立状态机 - 执行
m2 = Module('Beta')时,不会重复读取文件和计算共享属性,直接复用已生成的类共享数据,仅生成Beta自己的独立状态机 - 访问属性时,
m1.name、m2.name取值互不干扰,m1.finite_state_machine、m2.finite_state_machine为各自独立的对象;m1.modules_dictionary is m2.modules_dictionary返回True,确认是所有实例共享的同一份数据
内容的提问来源于stack exchange,提问作者Maxime Bouhadana
相关产品推荐
相关产品推荐

