如何修复Python中UnboundLocalError: 'Auto_field'未赋值即引用错误
错误原因分析
UnboundLocalError: local variable 'Auto_field' referenced before assignment 出现的核心原因是:
在update_chart函数的分支逻辑中,仅当选中特定类别时才定义对应变量(比如只有选「重電機器受注生産品」时才定义Auto_field),但后续构建field_0字典时直接引用了所有分支的变量——当选中其他类别时,未被赋值的变量就会触发未定义错误。
另外原代码还存在两处笔误:
- 全局变量名
産業用汎用産業用汎用電気機器計应改为産業用汎用_産業用汎用電気機器計 - 全局变量名
産業用汎用回転の駆動機器計应改为産業用汎用回転駆動機器計(对应else分支里的引用)
修复方案
方案1:提前初始化所有变量(快速修复)
在update_chart函数的分支判断前,先初始化所有需要用到的变量,确保无论走哪个分支,变量都有定义:
def update_chart(evt=None): global field_0 global data_item # 提前初始化所有可能用到的变量,避免未定义错误 Fridge_field = None Fridgebig_field = None Auto_field = None Construction_field = None IETotal_field = None Rotating_field = None if input_1.value == "民生用電気機器": Fridge_field = 民生用電気機器_電気冷蔵庫 Fridgebig_field = 民生用電気機器_電気冷蔵庫うち401L以上 elif input_1.value == "重電機器受注生産品": Auto_field = 重電機器受注生産品_自動車 Construction_field = 重電機器受注生産品_建設業 else: IETotal_field = 産業用汎用_産業用汎用電気機器計 Rotating_field = 産業用汎用回転駆動機器計 field_0 = { '電気冷蔵庫': Fridge_field , '電気冷蔵庫 うち401L以上': Fridgebig_field , '自動車': Auto_field , '建設業': Construction_field , '産業用汎用電気機器計': IETotal_field , '回転・駆動機器計': Rotating_field} # 后续代码保持不变...
同时修正全局变量的笔误:
# 修正后的全局变量定义 産業用汎用_産業用汎用電気機器計 = {'Industrial Equipment Total': 'JEESTOTL Index'} 産業用汎用回転駆動機器計 = {'Industrial Equipment - Rotating/driving equipment meter' :'JEESMREG Index'}
方案2:重构字段映射(更优雅的长期方案)
将类别与字段的映射关系统一整理成字典,避免分散的变量定义,同时让逻辑更清晰:
def chart_returns_different_country(bq): # 统一定义类别-字段的映射关系 category_field_map = { "民生用電気機器": { '電気冷蔵庫': {'House Appliance Refridgerator': 'JNESHQER Index'}, '電気冷蔵庫 うち401L以上': {'House Appliance Refridgerator Over 401 Litre':'JNESHQRO Index'} }, "重電機器受注生産品": { '自動車': {'Heavy Electric Equipment - Automobiles': 'JPCITOTL Index'}, '建設業': {'Heavy Electric Equipment - Construction':'JNHECONS Index'} }, "産業用汎用": { '産業用汎用電気機器計': {'Industrial Equipment Total': 'JEESTOTL Index'}, '回転・駆動機器計': {'Industrial Equipment - Rotating/driving equipment meter' :'JEESMREG Index'} } } count_list = list(category_field_map.keys()) # 默认加载第一个类别的字段作为初始选项 field_list = list(category_field_map[count_list[0]].keys()) input_1 = widgets.Dropdown(options = count_list, value = '民生用電気機器', description = 'Choose a country', style={'description_width': 'initial'}, layout=Layout(width='50%', height='40px') ) input_2 = widgets.Dropdown(options = field_list, value=field_list[0], description='機器') # 新增:当input_1切换时,动态更新input_2的选项 def update_field_options(evt): selected_category = input_1.value input_2.options = list(category_field_map[selected_category].keys()) input_2.value = input_2.options[0] input_1.observe(update_field_options, names='value', type='change') # 日期选择器代码保持不变... from datetime import date, datetime start_time = date(2020, 4, 30) input_3 = widgets.DatePicker(description='Choose start date', disabled=False, value=start_time) end_time = datetime.today() input_4 = widgets.DatePicker(description='Choose end date', disabled=False, value=end_time) # 图表初始化代码保持不变... fig = go.Figure() fig.update_traces(textfont_size=18, textangle=0, textposition ="outside", cliponaxis =False) fig.layout.xaxis.title.text = 'Date' fig.layout.yaxis.title.font.size=18 fig.update_layout(template ='plotly_dark',height=700) fig.update_layout(xaxis={'side':'bottom'}) fig.update_xaxes(tickfont_size=18, tickangle=0) fig.update_yaxes(tickfont_size=18) fig.update_layout(xaxis=dict(showgrid=False), yaxis=dict(showgrid=False)) fig = make_subplots(specs=[[{"secondary_y": True}]]) fig_w = go.FigureWidget(fig) def update_chart(evt=None): global field_0 global data_item selected_category = input_1.value selected_field = input_2.value # 直接从映射字典中获取对应字段,无需定义大量变量 selected_index = category_field_map[selected_category][selected_field] data_item = {'Value': bq.data.px_last(dates=bq.func.range(input_3.value, input_4.value),fill='NA',per='M')} global bql_request bql_request = bql.Request(list(selected_index.values()), data_item) df = bql.combined_df(bq.execute(bql_request)) df.index = df.index.map(dict(zip(selected_index.values(), selected_index.keys()))) df = df.reset_index() df = df.pivot(index='DATE', columns='ID', values='Value') df_plot = df.copy() df_plot.reset_index(inplace=True) df_plot.set_index('DATE', inplace=True) x = df_plot.index fig_w.data= [] for i in range(len(df_plot.columns.values)): if i == 0: fig_w.add_trace(go.Scatter(name= df_plot.columns.values[0], x= x, y= df_plot[df_plot.columns.values[0]], mode='lines', yaxis='y1'), secondary_y=False) else: try: fig_w.add_trace(go.Scatter(name=df_plot.columns.values[i], x= x, y= df_plot[df_plot.columns.values[i]], mode='lines', yaxis='y2'), secondary_y=True) except: pass y_label1 = df_plot.columns.values[0] + ' Scale' y_label2 = 'Others' fig_w.update_layout(yaxis = dict(title = y_label1), yaxis2 = dict(title = y_label2)) fig_w.layout.xaxis.title.text = 'Date' fig_w.update_xaxes(tickangle=45) fig_w.update_layout(template='plotly_dark', height=700, font_family="Arial", legend_font_size=16, font=dict( family="Arial", size=18, )) fig_w.update_layout(xaxis=dict(tickvals=x)) fig_w.for_each_xaxis(lambda x: x.update(showgrid=False)) fig_w.for_each_yaxis(lambda x: x.update(showgrid=False)) update_chart() input_1.observe(update_chart, names='value', type='change') input_2.observe(update_chart, names='value', type='change') input_3.observe(update_chart, names='value', type='change') input_4.observe(update_chart, names='value', type='change') # 重构bql_request的生成逻辑,遍历所有类别和字段 bql_request = [] for category in category_field_map: for field, index_map in category_field_map[category].items(): req = bql.Request(list(index_map.values()), data_item) bql_request.append(str(req)) return {'Chart': widgets.VBox([input_1, input_2, input_3, input_4, fig_w]), 'BQL Query': '\n'.join(bql_request)}
这个方案的优势:
- 消除了分散的变量定义,彻底避免未定义错误
- 实现了下拉框联动:选择不同类别时,字段下拉框自动更新对应选项
- 代码结构更清晰,后续新增类别或字段只需修改
category_field_map即可
额外注意事项
- 确保
date和datetime模块已导入,可在函数开头添加from datetime import date, datetime - 确保
widgets、go、make_subplots、bql等依赖已正确导入
内容的提问来源于stack exchange,提问作者HoangIta
相关产品推荐
相关产品推荐

