绘制函数切线时出现'Subs' is not defined错误的解决求助
修复SymPy lambdify生成切线时的Subs未定义错误
问题描述
已绘制出原函数,尝试绘制目标点处的切线时,运行Python代码出现NameError: name 'Subs' is not defined错误。
原代码
import numpy as np from sympy import lambdify, symbols, diff, Abs import matplotlib.pyplot as plt # 原代码遗漏导入,此处补全 point_of_interest = 8 graphRange = [1,15] # 定义变量与原函数 xsym = symbols('x') # 弦长60时的圆直径函数 origFunction = 2 * ((60 ** 2) / (8 * Abs(xsym)) + Abs(xsym) / 2) # 求导 derivative = diff(origFunction, xsym) # 定义目标点处的切线 tangentLine = derivative.subs(xsym, point_of_interest) * (xsym - point_of_interest) + origFunction.subs(xsym, point_of_interest) # 转换原函数为numpy可调用的lambda函数 origF = lambdify(xsym, origFunction, "numpy") # 生成x值 x_values = np.linspace(graphRange[0], graphRange[1], 100) # 计算原函数y值并绘图 y_values = origF(x_values) plt.plot(x_values, y_values, label='Original Function') # 切线部分报错代码 diffF = lambdify(xsym, tangentLine, "numpy") y_tang_values = diffF(x_values) plt.plot(x_values, y_tang_values, label='Tangent Line') # 绘制目标点 plt.plot(point_of_interest, origF(point_of_interest), 'ro', label='Point of Interest') # 添加图表元素 plt.xlabel('x') plt.ylabel('y') plt.title('Graph of Original Function and Tangent Line') plt.legend() plt.show()
错误信息
Traceback (most recent call last): File "x:\Python Projects\Chord calc.py", line 37, in y_tang_values = diffF(x_values) ^^^^^^^^^^^^^^^ File "", line 4, in _lambdifygenerated NameError: name 'Subs' is not defined
问题原因
原函数使用了Abs(xsym),SymPy对Abs(x)求导后会生成带有Subs对象的表达式。当代入point_of_interest=8(正数)时,SymPy未自动将Subs化简为具体数值,导致lambdify转换为numpy函数时无法识别Subs类型。
修复方案
方案1:显式计算切线的斜率和截距为数值
通过evalf()强制将SymPy表达式转换为数值,避免Subs对象残留:
import numpy as np from sympy import lambdify, symbols, diff, Abs import matplotlib.pyplot as plt point_of_interest = 8 graphRange = [1,15] xsym = symbols('x') origFunction = 2 * ((60 ** 2) / (8 * Abs(xsym)) + Abs(xsym) / 2) # 显式计算目标点处的斜率和函数值为数值 slope = diff(origFunction, xsym).subs(xsym, point_of_interest).evalf() y0 = origFunction.subs(xsym, point_of_interest).evalf() # 定义纯线性表达式的切线 tangentLine = slope * (xsym - point_of_interest) + y0 origF = lambdify(xsym, origFunction, "numpy") x_values = np.linspace(graphRange[0], graphRange[1], 100) y_values = origF(x_values) plt.plot(x_values, y_values, label='Original Function') # 转换切线函数并绘制 diffF = lambdify(xsym, tangentLine, "numpy") y_tang_values = diffF(x_values) plt.plot(x_values, y_tang_values, label='Tangent Line') plt.plot(point_of_interest, origF(point_of_interest), 'ro', label='Point of Interest') plt.xlabel('x') plt.ylabel('y') plt.title('Graph of Original Function and Tangent Line') plt.legend() plt.show()
方案2:利用x范围简化Abs函数
由于绘图范围graphRange=[1,15]内所有x值均为正数,Abs(xsym)等价于xsym,直接替换后可避免复杂的求导结果:
import numpy as np from sympy import lambdify, symbols, diff import matplotlib.pyplot as plt point_of_interest = 8 graphRange = [1,15] xsym = symbols('x') # 替换Abs(xsym)为xsym(x>0时等价) origFunction = 2 * ((60 ** 2) / (8 * xsym) + xsym / 2) derivative = diff(origFunction, xsym) tangentLine = derivative.subs(xsym, point_of_interest) * (xsym - point_of_interest) + origFunction.subs(xsym, point_of_interest) origF = lambdify(xsym, origFunction, "numpy") x_values = np.linspace(graphRange[0], graphRange[1], 100) y_values = origF(x_values) plt.plot(x_values, y_values, label='Original Function') diffF = lambdify(xsym, tangentLine, "numpy") y_tang_values = diffF(x_values) plt.plot(x_values, y_tang_values, label='Tangent Line') plt.plot(point_of_interest, origF(point_of_interest), 'ro', label='Point of Interest') plt.xlabel('x') plt.ylabel('y') plt.title('Graph of Original Function and Tangent Line') plt.legend() plt.show()
说明
- 方案1适用于任何x范围,通过强制数值化避免
Subs问题; - 方案2更简洁,利用绘图范围特性简化函数,减少SymPy的复杂表达式处理开销。
内容的提问来源于stack exchange,提问作者M. Twombley
相关产品推荐
相关产品推荐

