请求优化Python 2.7动态进度条代码(仅用标准库)
Python 2.7 动态进度条代码精简优化
问题概述
我为调试应用开发了一个动态进度条函数,功能符合预期,但需要帮助精简代码以提升效率。该代码基于Python 2.7.15,仅能使用标准库,无法引入tkinter等第三方模块。当前代码通过3种分支处理进度条填充与百分比文本的叠加逻辑,希望能优化简化这段代码。
原代码
def progress_bar(current_value, **kwargs): top_left_border = u'\u2554'.encode('utf-8') top_right_border = u'\u2557'.encode('utf-8') bottom_left_border = u'\u255A'.encode('utf-8') bottom_right_border = u'\u255D'.encode('utf-8') horizontal_border = u'\u2550'.encode('utf-8') vertical_border = u'\u2551'.encode('utf-8') color_border = '\33[38;5;3m' color_fg = '\33[38;5;4m' color_bg = '\33[48;5;4m' color_inverted_fg = '\33[38;5;0m' color_end = '\33[0m' b_val = int(current_value) b_width = 50 b_max = 100 b_min = 0 for k, v in kwargs.items(): if k.lower() == 'width': b_width = v elif k.lower() == 'max': b_max = v elif k.lower() == 'min': b_min = v elif k.lower() == 'fg': if 0 <= v <= 255: color_fg = '\33[38;5;{}m'.format(v) elif k.lower() == 'bg': if 0 <= v <= 255: color_bg = '\33[48;5;{}m'.format(v) elif k.lower() == 'reverse': if 0 <= v <= 255: color_inverted_fg = '\33[38;5;{}m'.format(v) elif k.lower() == 'border': if 0 <= v <= 255: color_border = '\33[38;5;{}m'.format(v) if b_min >= b_max: print color('Minimum value cannot be greater than or equal to maximum value.', 'red') return if b_val < b_min: b_val = b_min if b_val > b_max: b_val = b_max if b_width < 10: b_width = 10 # top border print color_border + top_left_border + horizontal_border * (b_width - 2) + top_right_border + color_end # progress bar fill count, percentage string and starting position of string fill_cnt = int(round(float(b_val - b_min) / (b_max - b_min) * (b_width - 2))) # filled spaces fill_pct = str(int(round((float(b_val - b_min) / (b_max - b_min)) * 100))) + '%' # % string pct_pos = int(round((b_width - 2) / 2) - round((len(fill_pct) / 2) - 1)) # start position of % # build the percentage bar string & percentage text b_bar = color_border + vertical_border + color_end if fill_cnt >= pct_pos: # if filled bar position ends after start of text num_dig = pct_pos - 1 # number of spaces before text b_bar += color_bg + ' ' * num_dig + color_end if fill_cnt < pct_pos + len(fill_pct): # if filled bar ends within text block num_dig = fill_cnt - pct_pos + 1 # how many digits of text are filled b_bar += color_bg + color_inverted_fg + fill_pct[:num_dig] + color_end b_bar += color_fg + fill_pct[num_dig:] + color_end # unfilled text digits after num_dig = (b_width - 2) - (pct_pos + len(fill_pct) - 1) # blank spaces after text b_bar += color_fg + ' ' * num_dig + color_border + vertical_border + color_end else: # if the filled bar position ends after the end of text b_bar += color_bg + color_inverted_fg + fill_pct + color_end # percentage text num_dig = fill_cnt - (pct_pos + len(fill_pct) - 1) # filled bar positions after end of text b_bar += color_bg + ' ' * num_dig + color_end num_dig = (b_width - 2) - fill_cnt # number of blanks after filled bar b_bar += color_fg + ' ' * num_dig + color_border + vertical_border + color_end else: # if the filled bar position end before start of text b_bar += color_bg + ' ' * fill_cnt + color_end # filled bar spaces num_dig = pct_pos - fill_cnt - 1 # blanks after fill & before start of text b_bar += color_fg + ' ' * num_dig + fill_pct + color_end num_dig = (b_width - 2) - (pct_pos + len(fill_pct) - 1) # blanks after end of text b_bar += color_fg + ' ' * num_dig + color_border + vertical_border + color_end print b_bar # bottom border print color_border + bottom_left_border + horizontal_border * (b_width - 2) + bottom_right_border + color_end
使用说明
调用方式:progress_bar(value, **kwargs)
可选参数说明:
width=50:进度条整体宽度(最小值10)max=100:进度的最大值min=0:进度的最小值fg:未填充区域及未被覆盖文本的前景色索引(范围0-255)bg:填充区域的背景色索引(范围0-255)reverse:被填充区域覆盖的文本的前景色索引(范围0-255)border:进度条边框的颜色索引(范围0-255)
精简优化后的代码
def progress_bar(current_value, **kwargs): # 边框字符统一管理,一次性编码避免重复操作 borders = { 'tl': u'\u2554'.encode('utf-8'), 'tr': u'\u2557'.encode('utf-8'), 'bl': u'\u255A'.encode('utf-8'), 'br': u'\u255D'.encode('utf-8'), 'h': u'\u2550'.encode('utf-8'), 'v': u'\u2551'.encode('utf-8') } # 颜色配置默认值 colors = { 'border': '\33[38;5;3m', 'fg': '\33[38;5;4m', 'bg': '\33[48;5;4m', 'reverse_fg': '\33[38;5;0m', 'end': '\33[0m' } # 参数默认值 params = { 'width': 50, 'max': 100, 'min': 0 } # 批量处理传入参数 for k, v in kwargs.items(): k_lower = k.lower() if k_lower in params: params[k_lower] = v elif k_lower in ['fg', 'bg', 'reverse', 'border']: if 0 <= v <= 255: color_key = 'reverse_fg' if k_lower == 'reverse' else k_lower # 根据参数类型选择前景/背景色控制码 code_type = 38 if k_lower != 'bg' else 48 colors[color_key] = '\33[{};5;{}m'.format(code_type, v) # 解构参数,简化后续调用 b_val = int(current_value) b_width, b_max, b_min = params['width'], params['max'], params['min'] bar_inner_width = b_width - 2 # 参数校验与修正 if b_min >= b_max: print '\33[38;5;1mMinimum value cannot be greater than or equal to maximum value.\33[0m' return b_val = max(b_min, min(b_val, b_max)) b_width = max(10, b_width) # 计算核心进度值,避免重复计算 progress_ratio = float(b_val - b_min) / (b_max - b_min) fill_cnt = int(round(progress_ratio * bar_inner_width)) fill_pct = '{}%'.format(int(round(progress_ratio * 100))) # 简化文本居中计算,用整数除法更稳定 pct_start = (bar_inner_width - len(fill_pct)) // 2 text_len = len(fill_pct) # 构建进度条内部内容,拆分逻辑减少分支 inner_parts = [] # 添加已填充区域 if fill_cnt > 0: inner_parts.append(colors['bg'] + ' ' * fill_cnt + colors['end']) # 处理文本与填充的叠加关系 text_filled = max(0, min(fill_cnt - pct_start, text_len)) text_unfilled = text_len - text_filled if fill_cnt >= pct_start: # 填充覆盖了部分或全部文本 if text_filled > 0: inner_parts.append(colors['bg'] + colors['reverse_fg'] + fill_pct[:text_filled] + colors['end']) if text_unfilled > 0: inner_parts.append(colors['fg'] + fill_pct[text_filled:] + colors['end']) # 添加剩余空白区域 remaining = bar_inner_width - fill_cnt if remaining > 0: inner_parts.append(colors['fg'] + ' ' * remaining + colors['end']) else: # 填充未到达文本区域 inner_parts.append(colors['fg'] + ' ' * (pct_start - fill_cnt) + colors['end']) inner_parts.append(colors['fg'] + fill_pct + colors['end']) remaining = bar_inner_width - (pct_start + text_len) if remaining > 0: inner_parts.append(colors['fg'] + ' ' * remaining + colors['end']) # 拼接完整进度条行 bar_line = (colors['border'] + borders['v'] + colors['end'] + ''.join(inner_parts) + colors['border'] + borders['v'] + colors['end']) # 打印完整进度条 print colors['border'] + borders['tl'] + borders['h'] * bar_inner_width + borders['tr'] + colors['end'] print bar_line print colors['border'] + borders['bl'] + borders['h'] * bar_inner_width + borders['br'] + colors['end']
优化要点说明
- 配置结构化:用字典统一管理边框字符、颜色和参数默认值,替代零散变量,提升代码可读性和维护性。
- 简化参数处理:通过字典键匹配替代多分支
if-elif,减少冗余代码。 - 合并重复计算:提前计算
progress_ratio,避免多次重复计算进度占比,提升运行效率。 - 消除嵌套分支:将进度条填充、文本展示拆分为独立逻辑块拼接,原有的三层分支嵌套简化为两层,逻辑更清晰。
- 简化边界校验:用
max/min函数一行完成值的边界修正,替代多分支if判断。 - 优化居中计算:用整数除法
//替代多次round操作,结果更稳定且代码更简洁。
内容的提问来源于stack exchange,提问作者Kryo
相关产品推荐
相关产品推荐

