Python中快速将构造参数转为类变量的更简洁实现方案求助
需求说明
初始化类实例时,将__init__方法接收的全部位置参数、关键字参数自动设置为所属类的类变量。
现有实现版本
初始版本
class Example(): def __init__( self, a: str, b: bool, c: int, d="str", e=True, f=123, ): class_member = dict(locals()) del class_member["self"] self.set_property(class_member) @classmethod def set_property(cls, kwargs): for key, value in kwargs.items(): setattr(cls, key, value) a = Example("test", True, 1, d="test", e=False, f=456) print(Example.d) # test
自行简化版本
class Example(): def __init__( self, a: str, b: bool, c: int, d="str", e=True, f=123, ): class_member = dict(locals()) del class_member["self"] for key, value in class_member.items(): setattr(Example, key, value) a = Example("test", True, 1, d="test", e=False, f=456) print(Example.d) # test
更简洁的实现方案
- 方案1:单类极简版本(无需额外导包,比现有简化版少一行代码)
直接遍历locals()跳过self即可,不需要额外做删除操作:
class Example(): def __init__(self, a: str, b: bool, c: int, d="str", e=True, f=123): for k, v in locals().items(): if k != "self": setattr(Example, k, v) a = Example("test", True, 1, d="test", e=False, f=456) print(Example.d) # 输出 test
- 方案2:通用装饰器版本(适合多类复用,稳定性更高)
用装饰器封装参数提取、赋值的通用逻辑,同时用inspect提取参数避免locals()误把__init__内的临时变量识别为入参的问题:
from functools import wraps import inspect def auto_set_class_vars(func): @wraps(func) def wrapper(self, *args, **kwargs): func(self, *args, **kwargs) sig = inspect.signature(func) # 提取参数(跳过self) param_list = list(sig.parameters.keys())[1:] # 合并位置、关键字参数 all_args = dict(zip(param_list, args)) all_args.update(kwargs) # 填充未传参的默认值 for name, param in sig.parameters.items(): if name == "self" or name in all_args: continue if param.default is not inspect.Parameter.empty: all_args[name] = param.default # 批量赋值类变量 for k, v in all_args.items(): setattr(type(self), k, v) return wrapper # 使用时只需加装饰器,无需写重复的参数处理逻辑 class Example(): @auto_set_class_vars def __init__(self, a: str, b: bool, c: int, d="str", e=True, f=123): # 可自由写其他初始化逻辑 pass a = Example("test", True, 1, d="test", e=False, f=456) print(Example.d) # 输出 test
注意事项
- 现有逻辑每次创建实例都会覆盖类的同名属性,若创建多个实例,最后一个实例的入参会成为最终的类变量值,若只需首次初始化赋值需要额外加状态判断。
- 用
locals()的方案要注意不要在变量遍历前定义__init__内部的临时变量,否则临时变量也会被误设为类变量,对稳定性要求高推荐用inspect方案。
内容的提问来源于stack exchange,提问作者Chuck Liu
相关产品推荐
相关产品推荐

