You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

类内调用依赖全局变量的拟合函数时,如何传递类内定义的变量?

类内调用依赖全局变量的拟合函数时,如何传递类内定义的变量?

你好!这个问题的核心很明确——原来的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.partiala的值绑定到函数上,将全局变量改为函数参数,彻底避免全局依赖:

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

火山引擎 最新活动