You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

绘制函数切线时出现'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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 09:07:32