如何让坐标绘图脚本支持小数且不触发格式校验错误?
问题与解决方案
问题概述
在Google Colab中实现的笛卡尔平面绘图脚本,支持用逗号分隔坐标(如(x,y), (x,y))连线、点分隔坐标(如(x,y). (x,y))断连,但无法兼容小数坐标——代码会混淆小数点和断连分隔符,且未正确解析浮点数,导致格式错误或无法正常绘图。
修改思路
核心是区分坐标内的小数点和断连用的点符号,同时替换不安全的eval解析方式:
- 用正则表达式识别断连分隔符:仅匹配
)后接.(可带空格)再接(的结构,避免误拆分坐标内的小数点 - 用正则提取坐标中的数值,显式转换为
float类型,确保整数和小数都能正确解析 - 移除
eval,改用更安全的字符串解析逻辑,避免代码注入风险
修改后的完整代码
# Import necessary libraries import plotly.graph_objects as go import ipywidgets as widgets from IPython.display import display, clear_output import re # 新增正则模块,用于解析输入 # 解析单个坐标字符串为(float, float)元组 def parse_point(point_str): # 匹配(x,y)格式,支持正负整数/小数 match = re.match(r'\s*\((-?\d+\.?\d*|-?\.\d+)\s*,\s*(-?\d+\.?\d*|-?\.\d+)\)\s*', point_str.strip()) if not match: raise ValueError("Invalid point format") x = float(match.group(1)) y = float(match.group(2)) return (x, y) # Function to plot points on a Cartesian plane def plot_points(points): try: # 用正则拆分断连的线段:匹配") . ("结构(可带任意空格) segment_strings = re.split(r'\)\s*\.\s*\(', points.strip()) # 处理首尾的括号:第一个 segment 开头可能有(,最后一个可能有) segment_strings[0] = segment_strings[0].lstrip('(') segment_strings[-1] = segment_strings[-1].rstrip(')') all_points = [] segments = [] # 解析每个线段的坐标 for seg_str in segment_strings: # 拆分当前线段内的所有坐标(逗号分隔) point_strings = [s.strip() for s in seg_str.split(',') if s.strip()] segment_points = [parse_point(f'({p})') for p in point_strings] segments.append(segment_points) all_points.extend(segment_points) # Extract x and y coordinates from all points x_values = [point[0] for point in all_points] y_values = [point[1] for point in all_points] # Create a new plotly figure fig = go.Figure() # Add a scatter trace for all points fig.add_trace(go.Scatter(x=x_values, y=y_values, mode='markers', name='Points')) # Add traces for the lines connecting the points in each segment start_idx = 0 for segment_points in segments: num_points = len(segment_points) if num_points > 1: # If segment has more than one point, add line connecting them end_idx = start_idx + num_points segment_x_values = x_values[start_idx:end_idx] segment_y_values = y_values[start_idx:end_idx] fig.add_trace(go.Scatter(x=segment_x_values, y=segment_y_values, mode='lines+markers', line=dict(color='blue', width=2), name='')) start_idx = end_idx # Update start index for the next segment # Update layout of the plot fig.update_layout(title='Points on Cartesian Plane', xaxis_title='X-Axis', yaxis_title='Y-Axis', xaxis=dict(range=[-99, 99], autorange=False), yaxis=dict(range=[-99, 99], autorange=False, showticklabels=False), showlegend=False, width=600, height=575) fig.show() except (ValueError, IndexError): # Display error message if there's a format error error_message.value = "格式错误,请输入正确格式:例如(1.5, 2).(3, 4.2), (5,6)" display(error_message) display(points_input) display(plot_button) # User input box for points points_input = widgets.Text(description="坐标:") # Error message display error_message = widgets.HTML(value="", layout=widgets.Layout(color='red')) # Plot button plot_button = widgets.Button(description="绘图") def on_plot_button_clicked(b): clear_output() error_message.value = "" plot_points(points_input.value) plot_button.on_click(on_plot_button_clicked) # Display the input box and plot button initially display(points_input) display(plot_button)
关键修改说明
- 正则拆分线段:使用
re.split(r'\)\s*\.\s*\(', points)精准匹配断连符号,仅当.出现在)和(之间(可带空格)时才作为线段分隔符,避免拆分坐标内的小数点 - 安全解析坐标:用
parse_point函数配合正则提取坐标数值,显式转换为float,支持整数(如(3,4))、正小数((1.5,2))、负小数((-0.5, -3.2))和纯小数((.5, .3)) - 错误处理优化:捕获
ValueError(坐标格式错误)和IndexError(空输入等),给出更清晰的中文提示
内容的提问来源于stack exchange,提问作者Ashton Raymer
相关产品推荐
相关产品推荐

