Jupyter Notebook,配合 ipywidgets 的 interact是什么?
4 2025-11-29 11:18
在 Jupyter Notebook 里,「ipywidgets 的 interact」可以一句话把任何 Python 函数变成“可交互小面板”:
函数里有哪些参数,它就自动给你生成一组滑动条 / 输入框;
你拖动滑动条,函数会立即被重新调用,输出(打印值、画图、甚至 3D 曲面)实时更新。
整个过程不需要写 HTML/JS,也无需 Dash 后端,只要浏览器里跑着 Notebook 就能用。
函数里有哪些参数,它就自动给你生成一组滑动条 / 输入框;
你拖动滑动条,函数会立即被重新调用,输出(打印值、画图、甚至 3D 曲面)实时更新。
整个过程不需要写 HTML/JS,也无需 Dash 后端,只要浏览器里跑着 Notebook 就能用。
下面给出最小可运行示例,并把它套到刚才的“三次多项式黎曼曲面”任务上,让你 30 秒内就能看到滑动条生效。
一、5 分钟上手 ipywidgets
-
安装(一次性)
pip install ipywidgetsJupyterLab 用户再执行:
jupyter labextension install @jupyter-widgets/jupyterlab-manager -
在 Notebook 新建一个 cell,输入:
Python
复制
import ipywidgets as wg
from IPython.display import display
import numpy as np
import matplotlib.pyplot as plt
def foo(a, b):
x = np.linspace(0, 2*np.pi, 200)
y = np.sin(a*x) * np.exp(-b*x)
plt.figure(figsize=(4,2))
plt.plot(x, y)
plt.show()
wg.interact(foo, a=wg.FloatSlider(1, 0, 5, 0.1),
b=wg.FloatSlider(0.3, 0, 1, 0.05));
运行后立刻得到两条滑动条:拖动 a/b,图实时重绘——这就是 interact。
二、把“三次黎曼曲面”搬进来
我们把前面的
下面代码直接粘进一个 Notebook cell 就能跑:
build_riemann_surface 原样拿过来,再用 interact 把 4 个系数映射成滑动条即可。下面代码直接粘进一个 Notebook cell 就能跑:
Python
复制
# Cell 1:导入
import numpy as np
import plotly.graph_objects as go
import ipywidgets as wg
from IPython.display import display
# 参数范围
RE_Z_RANGE = [-2, 2]
IM_Z_RANGE = [-2, 2]
N_GRID = 100 # 网格密度,笔记本上 100 足够流畅
HEIGHT_SCALE = 0.4
# Cell 2:求解函数(同前)
def solve_cubic(a3, a2, a1, a0, z):
if abs(a3) < 1e-14:
raise ValueError("a3==0")
p = np.array([1, a2/a3, a1/a3, a0/a3], dtype=complex)
roots = np.roots(p)
idx = np.argsort(np.angle(roots))
return roots[idx]
def build_riemann_surface(a3, a2, a1, a0):
x = np.linspace(*RE_Z_RANGE, N_GRID)
y = np.linspace(*IM_Z_RANGE, N_GRID)
X, Y = np.meshgrid(x, y)
Z = X + 1j*Y
W1, W2, W3 = [np.zeros_like(Z) for _ in range(3)]
for idx, z in np.ndenumerate(Z):
try:
w123 = solve_cubic(a3, a2, a1, a0, z)
W1[idx], W2[idx], W3[idx] = w123
except:
W1[idx], W2[idx], W3[idx] = np.nan, np.nan, np.nan
Z1 = W1.real + HEIGHT_SCALE*0
Z2 = W2.real + HEIGHT_SCALE*1
Z3 = W3.real + HEIGHT_SCALE*2
return X, Y, Z1, Z2, Z3
# Cell 3:绘图函数
surface_fig = None # 全局句柄,用来刷新
def plot_cubic_riemann(a3_r, a3_i, a2_r, a2_i,
a1_r, a1_i, a0_r, a0_i):
global surface_fig
a3 = complex(a3_r, a3_i)
a2 = complex(a2_r, a2_i)
a1 = complex(a1_r, a1_i)
a0 = complex(a0_r, a0_i)
X, Y, Z1, Z2, Z3 = build_riemann_surface(a3, a2, a1, a0)
traces = []
for k, Z in enumerate([Z1, Z2, Z3], 1):
traces.append(
go.Surface(x=X, y=Y, z=Z,
colorscale='Viridis',
showscale=False,
name=f'Leaf {k}')
)
if surface_fig is None: # 第一次画
surface_fig = go.FigureWidget(traces)
surface_fig.update_layout(
title='Cubic Riemann Surface',
scene=dict(xaxis_title='Re(z)',
yaxis_title='Im(z)',
zaxis_title='Re(w)')
)
display(surface_fig)
else: # 更新
with surface_fig.batch_update():
for i, tr in enumerate(traces):
surface_fig.data[i].x = tr.x
surface_fig.data[i].y = tr.y
surface_fig.data[i].z = tr.z
# Cell 4:一行 interact 搞定
wg.interact(
plot_cubic_riemann,
a3_r=wg.FloatSlider(1.0, -2, 2, 0.05, description='a3.r'),
a3_i=wg.FloatSlider(0.0, -2, 2, 0.05, description='a3.i'),
a2_r=wg.FloatSlider(0.0, -2, 2, 0.05, description='a2.r'),
a2_i=wg.FloatSlider(0.0, -2, 2, 0.05, description='a2.i'),
a1_r=wg.FloatSlider(0.0, -2, 2, 0.05, description='a1.r'),
a1_i=wg.FloatSlider(0.0, -2, 2, 0.05, description='a1.i'),
a0_r=wg.FloatSlider(0.0, -2, 2, 0.05, description='a0.r'),
a0_i=wg.FloatSlider(0.0, -2, 2, 0.05, description='a0.i')
);
运行 Cell 4 后,Notebook 会弹出 8 条滑动条(4 个系数各自的实部/虚部),
第一次自动绘制 Plotly 3D 曲面,以后每拖一下滑动条,Python 后台会重新跑
第一次自动绘制 Plotly 3D 曲面,以后每拖一下滑动条,Python 后台会重新跑
build_riemann_surface → 更新 FigureWidget.data,曲面实时刷新,完成真正的“占位演示”。三、常见坑
-
经典 Jupyter Notebook 与 JupyterLab 的 widgets 插件版本要对齐;
如果滑动条没出来,按提示执行:
jupyter nbextension enable --py widgetsnbextension -
网格密度 N_GRID 太大(>150)时,每次重算可能 0.3~0.5 s,体感会卡;
想更丝滑,可改用continuous_update=False,让滑动条松手后才刷新:
wg.FloatSlider(..., continuous_update=False) -
如果更喜欢 Matplotlib 的 3D 曲面,只要把
plot_cubic_riemann里的
go.Surface换成ax.plot_surface即可,interact 用法完全一样。
至此,你已经在 Jupyter Notebook 里用 ipywidgets 的 interact 实现了“拖动系数 → 黎曼曲面实时更新”的完整占位演示。
全部评论