如何在Python类中动态生成带指定ReasonOptions的send_otp方法?
动态生成OTP发送方法的解决方案
你可以通过类装饰器+方法规范映射的方式,自动生成所有重复的send_xxx_otp方法,避免手动编写冗余代码。以下是两种可行的实现方案:
方案1:基础版(统一参数名)
如果可以接受所有方法使用统一参数名(比如identifier),用闭包+装饰器就能快速实现:
from functools import partial from your_module import ReasonOptions, Manager, BaseOtp # 定义方法名与对应ReasonOptions的映射表 REASON_METHOD_MAP = { "send_forget_password_otp": ReasonOptions.FORGET_PASSWORD, "send_phone_number_activation_otp": ReasonOptions.PHONE_NUMBER_ACTIVATION, "send_two_step_auth_activation_otp": ReasonOptions.ENABLE_TWO_STEP_AUTH, "send_two_step_auth_deactivation_otp": ReasonOptions.DISABLE_TWO_STEP_AUTH, "send_change_user_identifier_otp": ReasonOptions.CHANGE_USER_IDENTIFIER, } def add_otp_methods(cls): for method_name, reason in REASON_METHOD_MAP.items(): # 用partial捕获当前循环的reason,避免闭包变量共享问题 def otp_method(self, identifier, r=reason): return self.send_otp(identifier, reason=r) # 设置方法名,保证调用和调试的可读性 otp_method.__name__ = method_name # 添加类型提示 otp_method.__annotations__ = {"identifier": str} # 将方法绑定到类 setattr(cls, method_name, otp_method) return cls # 应用装饰器自动生成方法 @add_otp_methods class OtpBusinessLogicLayer(Manager, BaseOtp): pass
方案2:进阶版(保留原参数名与类型提示)
如果需要严格保留原代码中的参数名(比如phone_number、email)和类型提示,可以通过exec动态生成方法代码:
from your_module import ReasonOptions, Manager, BaseOtp # 定义详细的方法规范:包含方法名、reason、参数名、参数类型 OTP_METHOD_SPECS = [ { "method_name": "send_forget_password_otp", "reason": ReasonOptions.FORGET_PASSWORD, "param_name": "identifier", "param_type": str }, { "method_name": "send_phone_number_activation_otp", "reason": ReasonOptions.PHONE_NUMBER_ACTIVATION, "param_name": "phone_number", "param_type": str }, { "method_name": "send_two_step_auth_activation_otp", "reason": ReasonOptions.ENABLE_TWO_STEP_AUTH, "param_name": "email", "param_type": str }, { "method_name": "send_two_step_auth_deactivation_otp", "reason": ReasonOptions.DISABLE_TWO_STEP_AUTH, "param_name": "email", "param_type": str }, { "method_name": "send_change_user_identifier_otp", "reason": ReasonOptions.CHANGE_USER_IDENTIFIER, "param_name": "email", "param_type": str }, ] def add_otp_methods(cls): for spec in OTP_METHOD_SPECS: method_name = spec["method_name"] reason = spec["reason"] param_name = spec["param_name"] param_type = spec["param_type"] # 动态生成符合原代码结构的方法代码 method_code = f""" def {method_name}(self, {param_name}: {param_type.__name__}): return self.send_otp({param_name}, reason={reason}) """ # 执行代码并获取生成的方法 local_namespace = {} exec(method_code, globals(), local_namespace) otp_method = local_namespace[method_name] # 将方法绑定到类 setattr(cls, method_name, otp_method) return cls # 应用装饰器自动生成方法 @add_otp_methods class OtpBusinessLogicLayer(Manager, BaseOtp): pass
说明
- 两种方案都无需手动编写每个
send_xxx_otp方法,只需维护映射/规范表即可 - 方案2完全保留原代码的参数名和类型提示,调用方式与原代码完全一致
- 后续新增OTP场景时,只需在映射/规范表中添加新条目,就能自动生成对应方法
内容的提问来源于stack exchange,提问作者Bad Boy
相关产品推荐
相关产品推荐

