Python函数图像绘制全攻略:从NumPy向量化到Matplotlib高级可视化

Python函数图像绘制全攻略:从NumPy向量化到Matplotlib高级可视化 1. 项目概述为什么用Python画函数图是门必修课如果你刚开始学编程或者刚接触Python可能会觉得“画函数图像”这事儿离你很远是数学老师或者科研人员才需要干的。但作为一个写了十几年代码的老码农我得告诉你这几乎是每个用Python处理数据、做分析、搞算法的人迟早都要掌握的核心技能。它远不止是画条线那么简单。想想看你写了个算法怎么知道它算得对不对你怎么向老板或者同事直观地展示数据的变化趋势你怎么验证一个数学模型是否贴合实际情况答案往往就是画出来看看。Python在这方面的能力尤其是配合Matplotlib、NumPy这些库强大到让你可以轻松地把脑海里的数学公式变成屏幕上清晰、美观、甚至可以直接放进报告里的图表。这比Excel手动描点高效得多也比MATLAB更灵活、更开源。从热搜词也能看出来大家关心的不仅仅是“画”而是“怎么画好”。softmax函数图像、python绘制500hpa天气图、tensor数据如何绘制图像这些词背后都是具体的、有挑战性的应用场景。今天我就以“用Python绘制函数图像”为引子带你从零开始不仅学会画一条正弦波更要搞懂背后的原理、工具的选择以及那些新手最容易踩进去的坑。我会假设你是个有一定Python基础比如知道列表、循环、导包但对科学计算和绘图还不太熟悉的朋友咱们一步步来。2. 核心工具链解析NumPy与Matplotlib的黄金组合要画函数图你得有两样东西数据和画布。在Python的世界里这分别对应着NumPy和Matplotlib。它们俩就像螺丝刀和螺丝分开也能用但合在一起才是干活的神器。2.1 NumPy高效生成函数数据的引擎为什么非得用NumPy我用个简单的对比你就明白了。假设你要画一个从0到10间隔0.1的正弦函数图像。纯Python写法低效import math x_points [] y_points [] current_x 0 while current_x 10: x_points.append(current_x) y_points.append(math.sin(current_x)) current_x 0.1这段代码逻辑清晰但效率是硬伤。它用了Python原生的list和循环每次循环都要调用append方法计算sin值。当数据点成千上万时速度会慢得让你怀疑人生。NumPy写法高效向量化import numpy as np x np.arange(0, 10, 0.1) # 生成数组 [0., 0.1, 0.2, ..., 9.9] y np.sin(x) # 对整个数组一次性进行sin计算看就两行。np.arange生成了一个均匀的数值数组np.sin直接对这个数组进行“向量化”操作一次性算出所有结果。背后的计算是用C语言实现的速度比Python循环快几十甚至上百倍。这就是NumPy的核心优势提供多维数组对象和一系列高效的数组操作函数。对于绘图来说我们需要的正是这种均匀、密集的采样点才能让曲线看起来光滑连续。np.linspace是另一个更常用的函数因为它能精确控制起点、终点和点的数量而不是步长。# 在0到2π之间均匀生成100个点 x np.linspace(0, 2*np.pi, 100) y np.sin(x)注意np.pi是NumPy提供的圆周率常数比你自己写3.1415926...更精确也更方便。养成使用这些科学常数的习惯。2.2 Matplotlib从数据到图形的画笔有了数据x, y接下来就需要一个“画师”把它画出来。Matplotlib就是Python绘图领域的“事实标准”功能极其强大从简单的折线图到复杂的3D曲面、动画几乎无所不能。它的设计哲学是分层级的最底层是Artist对象负责绘制线条、文本等元素上层是pyplot接口提供了一个类似MATLAB的简易状态机界面让我们能用很少的代码快速出图。最核心的模块是matplotlib.pyplot通常别名为plt。import matplotlib.pyplot as plt # 最简单的绘图 plt.plot(x, y) # 传入x和y数据 plt.show() # 显示图形plt.plot()是绘制折线图对于我们来说就是函数曲线的主要函数。plt.show()则会弹出一个窗口展示图形。在Jupyter Notebook中为了能内嵌显示图表通常会在开头加上一行魔法命令%matplotlib inline。但仅仅画出线是不够的。一个专业的图表需要标题、坐标轴标签、图例、合适的网格等等。这就是pyplot其他函数的作用plt.title(‘正弦函数’)添加图表标题。plt.xlabel(‘x轴’),plt.ylabel(‘y轴’)添加坐标轴标签。plt.grid(True)显示网格方便读数。plt.legend()显示图例需要先在plot函数中用label参数指定线条标签。实操心得很多新手会忘记plt.show()导致代码运行后什么也没出现。在脚本中plt.show()是阻塞的会打开一个窗口并等待你关闭它程序才会继续执行。在Notebook中如果没有%matplotlib inline也需要plt.show()来触发渲染。我建议在交互式环境如Jupyter中用inline在写独立脚本时用show()。3. 从零开始绘制你的第一个函数图像理论说再多不如动手做一遍。我们从一个完整的、可复现的例子开始我会详细解释每一行代码的意图和可能的变化。3.1 环境准备与库安装首先确保你的Python环境已经就绪。从热搜词python安装、vscode python环境配置能看出环境是很多人的第一道坎。我个人推荐使用Anaconda发行版来管理Python科学计算环境它集成了NumPy、Matplotlib等几百个常用库省去了手动安装的麻烦。如果你已经安装了标准的Python那么通过pip安装这两个库也非常简单pip install numpy matplotlib安装完成后可以在Python中导入测试import numpy as np import matplotlib.pyplot as plt print(np.__version__, plt.__version__) # 查看版本没有报错就说明环境OK了。3.2 基础绘图四步法我们以绘制一个衰减的正弦波常用于表示阻尼振动为例y e^(-x/5) * sin(x)。第一步准备数据这是最关键的一步决定了你画的是什么。import numpy as np import matplotlib.pyplot as plt # 生成x数据从0到20取200个点。点数越多曲线越光滑但计算量也越大。200是个不错的平衡点。 x np.linspace(0, 20, 200) # 计算对应的y值。注意NumPy的运算是元素级的element-wise。 # np.exp()是指数函数np.sin()是正弦函数。 y np.exp(-x / 5) * np.sin(x)这里np.linspace(0, 20, 200)创建了一个包含200个元素的数组这些数均匀分布在0到20之间。用这个数组作为自变量x再通过函数关系计算出因变量y。整个过程是向量化的高效且简洁。第二步创建图形与坐标轴虽然直接plt.plot(x, y)也能画但更规范、更灵活的做法是使用“面向对象”的接口。这在你需要绘制多个子图时尤其有用。# fig代表整个图形窗口ax代表图形中的一个坐标轴子图 fig, ax plt.subplots(figsize(8, 5)) # figsize设置图形宽高单位是英寸plt.subplots()是一个非常实用的函数它一次性创建了一个图形Figure和一个或多个坐标轴Axes。figsize(8,5)指定了图形窗口的尺寸8英寸宽5英寸高你可以根据显示或出版需求调整。第三步绘制并美化现在在创建好的坐标轴ax上作画。# 绘制曲线并设置线条样式。‘b-’代表蓝色实线linewidth设置线宽label用于图例。 ax.plot(x, y, ‘b-’, linewidth2, label‘y e^(-x/5) * sin(x)’) # 设置标题和坐标轴标签 ax.set_title(‘衰减正弦波示例’, fontsize14) ax.set_xlabel(‘时间 (s)’, fontsize12) ax.set_ylabel(‘振幅’, fontsize12) # 显示网格使用浅灰色虚线透明度0.7 ax.grid(True, linestyle‘--’, alpha0.7) # 显示图例loc‘upper right’表示放在右上角 ax.legend(loc‘upper right’) # 设置坐标轴显示范围让图形更美观 ax.set_xlim([0, 20]) ax.set_ylim([-1.2, 1.2])这一步是美学的核心。linewidth改变线条粗细label为曲线命名供图例使用set_title、set_xlabel、set_ylabel让图表信息完整grid增加可读性set_xlim/ylim可以手动聚焦到关键区域避免自动缩放导致图形留白过多或细节被压缩。第四步显示与保存# 自动调整子图参数使标签、标题等不重叠 plt.tight_layout() # 显示图形 plt.show() # 如果需要保存为图片文件如用于报告使用fig.savefig # fig.savefig(‘damped_sine_wave.png’, dpi300, bbox_inches‘tight’)plt.tight_layout()是一个小技巧它能自动调整子图、标签、标题之间的间距避免它们相互重叠让排版更紧凑美观。plt.show()则在屏幕上渲染出最终结果。保存图片时dpi参数控制分辨率 dots per inch每英寸点数300是印刷品的常用标准网络分享用150左右即可。bbox_inches‘tight’会裁剪掉图形周围多余的空白区域。运行以上所有代码你就能得到一个清晰、专业的衰减正弦波图像。这四步法是绘制几乎所有函数图像的基础模板。4. 进阶技巧让函数图像更具表现力画出一条线只是开始。在实际工作中我们经常需要对比多个函数、处理不连续点、填充区域或者进行更复杂的定制。4.1 绘制多个函数与样式控制对比是分析的核心。比如我们想同时画出sin(x)、cos(x)和sin(x)*cos(x)。x np.linspace(-2*np.pi, 2*np.pi, 400) y1 np.sin(x) y2 np.cos(x) y3 np.sin(x) * np.cos(x) fig, ax plt.subplots(figsize(10, 6)) # 绘制三条曲线分别指定颜色、线型和标签 # ‘r-’ 红色实线‘g--’ 绿色虚线‘b:’ 蓝色点线 ax.plot(x, y1, ‘r-’, linewidth1.5, label‘sin(x)’) ax.plot(x, y2, ‘g--’, linewidth2, label‘cos(x)’) ax.plot(x, y3, ‘b:’, linewidth2.5, label‘sin(x)*cos(x)’) ax.set_title(‘三角函数对比’, fontsize16) ax.set_xlabel(‘x’, fontsize14) ax.set_ylabel(‘y’, fontsize14) ax.grid(True, alpha0.3) ax.legend(loc‘best’) # ‘best’自动选择最佳位置 ax.axhline(y0, color‘k’, linestyle‘-’, linewidth0.5) # 绘制黑色水平基准线 ax.axvline(x0, color‘k’, linestyle‘-’, linewidth0.5) # 绘制黑色垂直基准线 plt.tight_layout() plt.show()这里的关键点样式字符串如‘r-’是Matplotlib的快捷语法。第一个字符是颜色r红g绿b蓝k黑y黄等第二个字符是线型-实线--虚线:点线-.点划线。你也可以用更明确的参数color‘red’, linestyle‘solid’。loc‘best’让Matplotlib自动寻找图例放置的最佳位置避免遮挡关键数据。axhline/axvline用于绘制平行于坐标轴的直线常用于绘制基准线如y0让零点位置一目了然。4.2 处理特殊函数与不连续点不是所有函数都像正弦波那么“友好”。比如分段函数、有垂直渐近线的函数如tan(x)或者在某些点无定义的函数直接画可能会出问题。示例绘制分段函数def piecewise_func(x): “”“定义一个分段函数当x0时yx^2当x0时ysin(x)”“” # 使用np.where进行条件判断和赋值这是向量化操作的关键 return np.where(x 0, x**2, np.sin(x)) x np.linspace(-5, 5, 1000) y piecewise_func(x) fig, ax plt.subplots() ax.plot(x, y, ‘b-’, linewidth2) ax.scatter([0], [0], color‘red’, s50, zorder5) # 用散点标出分段点(0,0)zorder控制绘制层级 ax.grid(True) ax.set_title(‘分段函数示例’) plt.show()np.where(condition, x, y)是处理分段函数的利器。它检查condition为True时取x的值为False时取y的值。整个操作依然是向量化的效率极高。示例绘制正切函数处理渐近线直接绘制tan(x)在奇点如π/2附近会因值趋于无穷大而导致图形变形。x np.linspace(-1.5*np.pi, 1.5*np.pi, 2000) y np.tan(x) # 方法将y值过大的点屏蔽掉设为NaN这样Matplotlib就不会绘制它们 y_filtered y.copy() y_filtered[np.abs(y) 20] np.nan # 当|y|20时认为接近无穷大设为NaN fig, ax plt.subplots(figsize(10, 6)) ax.plot(x, y_filtered, ‘b-’, linewidth1.5, label‘tan(x)’) # 用虚线标出渐近线位置 asymptotes [ -np.pi/2, np.pi/2] # -90度和90度位置 for asym in asymptotes: ax.axvline(xasym, color‘red’, linestyle‘:’, linewidth1, alpha0.7) ax.set_ylim([-10, 10]) # 手动限制y轴范围避免因NaN点导致的自动缩放问题 ax.set_title(‘正切函数屏蔽无穷大点’) ax.grid(True, alpha0.3) ax.legend() plt.tight_layout() plt.show()这里的技巧是数据清洗。通过将过大的值设置为np.nanNot a Numberplot函数在遇到NaN时会自动断开线条从而避免了从正无穷“连线”到负无穷的难看直线。同时手动设置set_ylim可以确保图形在合理的范围内显示。4.3 填充区域与子图绘制有时我们需要突出函数与坐标轴之间的面积或者比较多个相关图形。这时就需要填充和子图功能。填充函数与坐标轴之间的区域x np.linspace(0, 4*np.pi, 500) y np.sin(x) fig, ax plt.subplots() ax.plot(x, y, ‘b-’, linewidth2) # 填充y0的区域颜色为浅蓝色透明度0.3 ax.fill_between(x, y, where(y 0), color‘lightblue’, alpha0.3, label‘y0区域’) # 填充y0的区域颜色为浅红色透明度0.3 ax.fill_between(x, y, where(y 0), color‘lightcoral’, alpha0.3, label‘y0区域’) ax.set_title(‘正弦函数区域填充’) ax.legend() ax.grid(True, alpha0.3) plt.show()ax.fill_between(x, y1, y2, wherecondition)是一个非常强大的函数。它填充y1和y2之间的区域默认y20即x轴。where参数接受一个布尔数组只填充条件为True的区域。alpha参数控制透明度让被填充区域不会完全遮盖后面的网格或曲线。创建多子图对比子图Subplot允许你在一个图形窗口中并排显示多个坐标轴非常适合对比分析。# 定义四个不同的函数 funcs [np.sin, np.cos, np.tan, lambda x: np.exp(-x)*np.sin(x)] titles [‘正弦函数 sin(x)’, ‘余弦函数 cos(x)’, ‘正切函数 tan(x)’, ‘衰减正弦波’] x_shared np.linspace(-np.pi, np.pi, 300) fig, axes plt.subplots(2, 2, figsize(12, 8)) # 创建2行2列共4个子图 axes axes.flatten() # 将2x2的axes数组展平为1维方便循环 for i, (ax, func, title) in enumerate(zip(axes, funcs, titles)): y func(x_shared) if i 2: # 对正切函数做特殊处理 y_filtered y.copy() y_filtered[np.abs(y) 5] np.nan y y_filtered ax.plot(x_shared, y, ‘b-’, linewidth1.5) ax.set_title(title, fontsize12) ax.grid(True, alpha0.3) ax.set_xlim([-np.pi, np.pi]) if i ! 2: # 正切函数不限制y轴其他限制在[-1.2, 1.2] ax.set_ylim([-1.2, 1.2]) plt.suptitle(‘常见三角函数与衰减波对比’, fontsize16) # 为整个图形添加总标题 plt.tight_layout() plt.show()关键点plt.subplots(2, 2)返回一个图形对象fig和一个2x2的坐标轴数组axes。axes.flatten()将二维数组转换为一维列表这样可以用for i, ax in enumerate(axes)来遍历每一个子图。在每个子图ax上独立进行绘图和设置就像操作单个图一样。plt.suptitle()用于设置整个图形的总标题。plt.tight_layout()在这里尤为重要它能自动调整多个子图之间的间距防止标题、标签互相重叠。5. 实战复杂函数可视化与3D曲面图当我们掌握了基础就可以挑战更复杂的可视化任务比如参数方程、极坐标图甚至是三维曲面。5.1 参数方程与极坐标绘图有些曲线用直角坐标x,y表示很复杂但用参数方程或极坐标表示却很简单。比如绘制一个心形线。参数方程绘制心形线心形线的参数方程为x 16 sin³(t), y 13 cos(t) - 5 cos(2t) - 2 cos(3t) - cos(4t)t np.linspace(0, 2*np.pi, 1000) # 参数t x 16 * (np.sin(t) ** 3) y 13 * np.cos(t) - 5 * np.cos(2*t) - 2 * np.cos(3*t) - np.cos(4*t) fig, ax plt.subplots(figsize(7, 7)) ax.plot(x, y, ‘r-’, linewidth3) ax.fill(x, y, ‘pink’, alpha0.6) # 填充心形内部 ax.set_title(‘心形线 (参数方程)’, fontsize15) ax.set_aspect(‘equal’) # 关键设置纵横比为相等否则图形会被拉伸变形 ax.grid(True, alpha0.3) plt.show()这里的关键是ax.set_aspect(‘equal’)。对于参数方程或任何希望保持图形原始比例的情况这个命令强制x轴和y轴的刻度单位长度相等防止圆被画成椭圆心形被压扁。极坐标绘图对于像玫瑰线r a * cos(kθ)这样的图形极坐标系更直观。Matplotlib提供了极坐标子图。# 创建极坐标子图 fig, ax plt.subplots(subplot_kw{‘projection’: ‘polar’}, figsize(7, 7)) theta np.linspace(0, 2*np.pi, 500) k 5 # 花瓣数量 r np.cos(k * theta) # 四叶玫瑰线 ax.plot(theta, r, ‘m-’, linewidth2.5) ax.set_title(‘极坐标下的玫瑰线 r cos(5θ)’, fontsize14, pad20) ax.grid(True) plt.show()通过subplot_kw{‘projection’: ‘polar’}参数我们创建了一个极坐标系的坐标轴。绘图时第一个参数是角度theta弧度制第二个参数是半径r。5.2 绘制3D函数曲面对于二元函数 z f(x, y)我们需要三维曲面图。这需要用到Matplotlib的3D工具包。from mpl_toolkits.mplot3d import Axes3D # 导入3D绘图工具 # 定义二元函数例如一个鞍面z x^2 - y^2 def saddle_surface(x, y): return x**2 - y**2 # 生成网格数据 x np.linspace(-2, 2, 50) y np.linspace(-2, 2, 50) X, Y np.meshgrid(x, y) # 关键将一维数组转换为二维网格 Z saddle_surface(X, Y) # 创建3D图形 fig plt.figure(figsize(10, 8)) ax fig.add_subplot(111, projection‘3d’) # 添加一个3D子图 # 绘制曲面图 # cmap指定颜色映射‘viridis’是一种感知均匀的色图适合表示高度 surf ax.plot_surface(X, Y, Z, cmap‘viridis’, edgecolor‘none’, alpha0.9) # 添加颜色条表示Z值的大小 fig.colorbar(surf, axax, shrink0.5, aspect10, label‘Z value’) ax.set_title(‘3D曲面鞍面 z x^2 - y^2’, fontsize14) ax.set_xlabel(‘X轴’) ax.set_ylabel(‘Y轴’) ax.set_zlabel(‘Z轴’) # 调整视角 ax.view_init(elev25, azim45) # elev是仰角azim是方位角 plt.tight_layout() plt.show()核心难点与解释np.meshgrid这是3D绘图中最容易出错的一步。np.linspace生成的是两个一维数组x和y。np.meshgrid(x, y)会返回两个二维数组X和Y它们共同定义了整个x-y平面上的网格点。X的每一行都是x的副本Y的每一列都是y的副本。这样对于网格上的每一个点(X[i,j], Y[i,j])我们都能计算出一个对应的Z[i,j]。plot_surface用于绘制3D曲面。cmap参数非常重要它通过颜色变化来直观展示Z值的高低。edgecolor‘none’可以去掉网格线让曲面看起来更光滑。fig.colorbar为曲面添加一个颜色条将颜色映射回具体的Z值。view_init控制3D图形的观察角度。elev是仰角从水平面向上看的角度azim是方位角绕z轴旋转的角度。多调整这两个参数可以找到最能展示曲面特征的角度。实操心得3D绘图对计算资源要求稍高网格点太多比如linspace的第三个参数太大会导致绘图缓慢甚至卡顿。通常50-100个点已经能获得不错的效果。如果函数计算本身很耗时可以考虑先用较粗的网格预览再用细网格生成最终图。6. 常见问题与排查技巧实录即使按照步骤操作你也可能会遇到一些“坑”。下面是我在多年使用中总结的一些典型问题及其解决方法。6.1 图形不显示或显示异常问题1代码运行了但没弹出图形窗口。原因A你可能在脚本中运行但忘记了plt.show()。在非交互环境如.py脚本中必须调用plt.show()来阻塞程序并显示窗口。原因B你可能在使用Jupyter Notebook但没有配置正确的后端。解决在Notebook的第一单元格运行%matplotlib inline静态内嵌或%matplotlib notebook交互式内嵌。或者在代码开头添加import matplotlib matplotlib.use(‘TkAgg’) # 或 ‘Qt5Agg’, ‘MacOSX’ 等指定一个GUI后端 import matplotlib.pyplot as plt原因C某些IDE如PyCharm的科学模式会自动渲染图形但有时需要手动开启。检查IDE的设置。问题2中文显示为方框乱码。Matplotlib默认字体不包含中文字符。解决添加以下代码设置中文字体。import matplotlib.pyplot as plt plt.rcParams[‘font.sans-serif’] [‘SimHei’, ‘Microsoft YaHei’, ‘DejaVu Sans’] # 指定默认字体 plt.rcParams[‘axes.unicode_minus’] False # 解决负号‘-’显示为方块的问题你需要确保系统中有这些字体SimHei是黑体Windows通常自带。Linux系统可能需要额外安装中文字体包。问题3图形窗口一闪而过。原因在脚本中plt.show()是阻塞的但脚本运行结束后进程终止窗口也随之关闭。解决如果你希望窗口保持打开可以在脚本末尾添加input(“按回车键退出...”)或者使用plt.show(blockTrue)这是默认行为。更常见的是将绘图和展示代码放在脚本最后确保plt.show()是最后执行的命令之一。6.2 图形美化与输出问题问题4保存的图片分辨率低或者有白边。原因默认的保存DPI分辨率是100可能不够。图形周围可能存在多余的空白区域。解决使用fig.savefig时指定参数。fig.savefig(‘my_plot.png’, dpi300, bbox_inches‘tight’, pad_inches0.1)dpi300提高输出分辨率。bbox_inches‘tight’自动计算并裁剪掉图形周围的空白。pad_inches0.1在裁剪后保留0.1英寸的内边距防止标签被裁掉。问题5线条太细、颜色太淡打印出来不清晰。原因屏幕显示和打印对对比度的要求不同。解决为打印或出版优化样式。使用更粗的线宽plt.plot(x, y, linewidth2.5)。使用对比度高的颜色组合避免使用浅黄、浅绿等。可以使用Matplotlib的“tableau”色彩循环或手动指定深色。考虑使用灰度模式plt.plot(x, y, color‘black’, linestyle‘-’)和plt.plot(x, y2, color‘0.5’, linestyle‘--’)0.5代表中灰色。增大字体plt.xlabel(‘X轴’, fontsize14)。6.3 性能与数据问题问题6绘制大量数据点时如10万个点图形卡顿保存慢。原因plt.plot会为每一个数据点创建图形元素数量巨大时内存和渲染压力大。解决降采样如果数据是来自传感器或模拟的密集采样可以每隔N个点取一个来画图。x_dense np.linspace(0, 10, 100000) y_dense np.sin(x_dense) stride 100 # 每隔100个点取一个 x_plot x_dense[::stride] y_plot y_dense[::stride] plt.plot(x_plot, y_plot)使用更高效的方法对于简单的散点图plt.scatter在大数据量下很慢可以考虑用plt.plot并设置标记样式或者使用ax.scatter的alpha参数并降低透明度。考虑其他库对于超大规模数据可视化可以探索Datashader用于渲染亿级点阵或Plotly交互式性能较好。问题7绘制含NaN或Inf值的数据时图形出现断裂或异常。原因Matplotlib在绘制时遇到非有限数NaN, Inf会中断线条。解决这正是我们之前用到的技巧。在绘图前清洗数据。y_clean np.array(y_raw) # y_raw是你的原始数据 y_clean[~np.isfinite(y_clean)] np.nan # 将所有非有限数替换为NaN plt.plot(x, y_clean)np.isfinite()函数会返回一个布尔数组对应位置如果是有限数即不是NaN, Inf, -Inf则为True。~是取反操作。这行代码的意思是将所有非有限数替换为NaNplot函数会自动在NaN处断开。问题8自定义函数太复杂向量化操作写不出来怎么办场景你的函数内部有复杂的逻辑判断、循环无法直接用NumPy的向量化函数表示。解决使用np.vectorize函数。它可以将一个接受标量输入、返回标量输出的Python函数“伪向量化”。注意它底层还是用循环并没有提升性能但让代码写法上更简洁。def my_complex_func(x): if x 0: return x**2 elif 0 x 10: return np.sin(x) np.log(x1) # 假设log(x1)在x0时安全 else: return np.exp(-x) # 向量化版本 vfunc np.vectorize(my_complex_func) x np.linspace(-5, 15, 200) y vfunc(x) # 现在可以传入数组了 plt.plot(x, y)对于真正追求性能的场景还是应该尽量用NumPy的原生函数和np.where等重写你的逻辑。绘图本身是一个探索和调试的过程。最好的学习方式就是不断尝试修改参数观察图形的变化。把上面这些代码示例复制到你的环境中逐个运行、修改你很快就能掌握用Python绘制函数图像的方方面面并把它变成你数据分析和科学计算中的得力工具。