Python如何通过变量动态指定、调用类方法并传入自定义参数
问题实现方案
你写的调用逻辑无法直接运行的核心原因是:@property装饰的方法是绑定到类实例的描述符,直接通过类名取到的是property对象本身,不能直接传入参数调用;同时原生Python列表不支持直接做加减乘、和标量做数值运算,原示例代码的运算逻辑也需要做小调整。
第一部分:动态指定类方法调用
最整洁的实现方式是通过**方法名+getattr**动态获取实例对应的方法,不需要修改原有类的property结构,直接在main函数开头配置要调用的方法名即可:
from dataclasses import dataclass from typing import List @dataclass class MyFirstClass: y1: List[float] y2: List[float] @property def my_func1(self) -> List[float]: # 原生list不支持直接相减,用zip遍历计算 return [a - b for a, b in zip(self.y1, self.y2)] @property def my_func2(self) -> List[float]: return [a + b for a, b in zip(self.y1, self.y2)] @property def my_func3(self) -> List[float]: return [a * b for a, b in zip(self.y1, self.y2)] def main(): # 开头直接配置要调用的方法名 FUNCTION = "my_func1" y1 = [1, 2, 3, 4, 5] y2 = [3, 4, 5, 6, 7] # 实例化后动态取方法执行 test = getattr(MyFirstClass(y1, y2), FUNCTION)
如果需要实现FUNCTION(y1, y2)的直接传参调用形式,用简单的lambda包装即可:
FUNCTION = lambda y1, y2: getattr(MyFirstClass(y1, y2), "my_func1") test = FUNCTION(y1, y2)
第二部分:动态传入归一化方法
这个需求完全可以在不降低代码整洁度的前提下实现,核心是把归一化方法作为可调用对象传入类实例,注意给类的norm字段加上正确的Callable类型标注即可。
完整可运行实现:
from dataclasses import dataclass from typing import List, Callable import numpy as np # 可以直接把归一化逻辑定义为纯函数,也可以保留原有类结构 def norm1(arr: List[float]) -> List[float]: return arr def norm2(arr: List[float]) -> List[float]: return [x / np.mean(arr) for x in arr] # 原有MySecondClass可以保留,调用时传实例绑定方法即可 @dataclass class MySecondClass: list_vals: List[float] @property def norm1(self): return self.list_vals @property def norm2(self): return [x / np.mean(self.list_vals) for x in self.list_vals] @dataclass class MyFirstClassUpdated: y1: List[float] y2: List[float] # 标注norm为可调用对象:输入float列表,返回float列表 norm: Callable[[List[float]], List[float]] @property def my_func1(self) -> List[float]: return [a - b for a, b in zip(self.norm(self.y1), self.norm(self.y2))] @property def my_func2(self) -> List[float]: return [a + b for a, b in zip(self.norm(self.y1), self.norm(self.y2))] @property def my_func3(self) -> List[float]: return [a * b for a, b in zip(self.norm(self.y1), self.norm(self.y2))] def main(): # 开头统一配置 FUNCTION = "my_func1" # 方式1:直接传预定义的归一化函数 NORM = norm1 # 方式2:如果要用MySecondClass的方法,传入包装后的调用逻辑即可 # NORM = lambda x: MySecondClass(x).norm2 y1 = [1, 2, 3, 4, 5] y2 = [3, 4, 5, 6, 7] # 实例化时传入NORM参数,动态取方法执行 instance = MyFirstClassUpdated(y1=y1, y2=y2, norm=NORM) test = getattr(instance, FUNCTION)
如果要实现你期望的FUNCTION(y1, y2, NORM)调用形式,加一层通用包装函数即可,不会破坏代码结构:
def run_calc(func_name: str, y1: List[float], y2: List[float], norm: Callable): return getattr(MyFirstClassUpdated(y1, y2, norm), func_name) # 直接按你期望的形式调用 test = run_calc(FUNCTION, y1, y2, NORM)
注意事项
- 不要直接对原生Python列表做加减乘、标量除法等数值运算,会直接抛出类型错误,要么转numpy数组,要么用
zip遍历逐元素计算。 - 如果不需要property的惰性计算特性,也可以把类里的计算方法改成普通实例方法,调用时加括号即可,动态调用逻辑完全不变。
内容的提问来源于stack exchange,提问作者Denver Dang
相关产品推荐
相关产品推荐

