类内调用依赖全局变量的拟合函数时,如何传递类内定义的变量?
类内调用依赖全局变量的拟合函数时,如何传递类内定义的变量?
你好!这个问题的核心很明确——原来的fit_func_simple_a_fixed依赖全局变量a,但在类的fit_curve方法里定义的a = 0.8只是方法的局部变量,根本没进入全局作用域,所以函数自然找不到它。而且全局变量本身就不符合类的封装性原则,下面给你几个靠谱的解决办法,都能完美解决这个问题:
方法1:将拟合函数定义为类方法的内部函数(闭包)
直接把fit_func_simple_a_fixed放到fit_curve方法内部,这样它就能直接捕获方法里的a变量,完全不需要全局变量。同时我还简化了你原来的numpy运算部分(numpy支持向量化操作,不用手动map,效率更高):
import pandas as pd import numpy as np from scipy.optimize import curve_fit time = [i for i in range(0, 9)] cumulative_rate = [0, 0.14, 0.28, 0.36, 0.43, 0.50, 0.57, 0.60, 0.62] df = pd.DataFrame({'time': time, 'cumulative_rate': cumulative_rate}) class Curve_Fit(): def __init__(self, data): self.data = data self.param = self.fit_curve() def fit_curve(self): a = 0.8 x = np.array(self.data.time) y = np.array(self.data.cumulative_rate) # 把拟合函数定义在方法内部,直接使用外部的a变量 def fit_func_simple_a_fixed(x, b): x2 = -b * x x3 = 1 - np.exp(x2) # numpy向量化运算,替代map和自定义函数 return a * x3 params = curve_fit(fit_func_simple_a_fixed, x, y) return params # 测试 result = Curve_Fit(data=df) print(result.param)
方法2:用functools.partial绑定a的值
如果你想把拟合函数保留在类外部,可以用functools.partial把a的值绑定到函数上,将全局变量改为函数参数,彻底避免全局依赖:
import pandas as pd import numpy as np from scipy.optimize import curve_fit from functools import partial time = [i for i in range(0, 9)] cumulative_rate = [0, 0.14, 0.28, 0.36, 0.43, 0.50, 0.57, 0.60, 0.62] df = pd.DataFrame({'time': time, 'cumulative_rate': cumulative_rate}) # 修改拟合函数,把a作为第一个参数 def fit_func_simple_a_fixed(a, x, b): x2 = -b * x x3 = 1 - np.exp(x2) return a * x3 class Curve_Fit(): def __init__(self, data): self.data = data self.param = self.fit_curve() def fit_curve(self): a = 0.8 x = np.array(self.data.time) y = np.array(self.data.cumulative_rate) # 用partial绑定a的值,生成只接收x和b的新函数 bound_fit_func = partial(fit_func_simple_a_fixed, a) params = curve_fit(bound_fit_func, x, y) return params # 测试 result = Curve_Fit(data=df) print(result.param)
方法3:将a设为类的实例属性
如果a需要在类的多个方法中复用,可以把它设为实例属性,然后将拟合函数改为类的方法,通过self.a访问变量,结构更清晰:
import pandas as pd import numpy as np from scipy.optimize import curve_fit time = [i for i in range(0, 9)] cumulative_rate = [0, 0.14, 0.28, 0.36, 0.43, 0.50, 0.57, 0.60, 0.62] df = pd.DataFrame({'time': time, 'cumulative_rate': cumulative_rate}) class Curve_Fit(): def __init__(self, data, a=0.8): self.data = data self.a = a # 将a设为实例属性,支持初始化时自定义传入 self.param = self.fit_curve() # 拟合函数改为类方法,通过self.a访问变量 def fit_func_simple_a_fixed(self, x, b): x2 = -b * x x3 = 1 - np.exp(x2) return self.a * x3 def fit_curve(self): x = np.array(self.data.time) y = np.array(self.data.cumulative_rate) params = curve_fit(self.fit_func_simple_a_fixed, x, y) return params # 测试,还可以自定义a的值 result = Curve_Fit(data=df, a=0.8) print(result.param)
为什么原来的全局变量方式在类里失效?
在类的fit_curve方法里定义的a = 0.8是方法局部变量,和全局作用域的a完全是两个独立的对象。你原来的fit_func_simple_a_fixed明确要求使用全局的a,但方法里并没有给全局a赋值,所以会抛出NameError。就算你在方法里加global a,那也会修改全局变量,导致多个Curve_Fit实例共享同一个a,完全违背类的封装性设计。
备注:内容来源于stack exchange,提问作者koteletje




