函数调用拼接DataFrames报错:局部变量'df_all'未赋值即引用
解决局部变量'df_all'引用前未赋值的问题
你碰到的这个错误,核心原因是变量作用域的问题:虽然你在全局作用域定义了df_all,但在save_data函数内部尝试给它赋值时,Python默认会把它当成一个新的局部变量,而你在pd.concat里先引用了这个还没创建的局部变量,自然就报错了。
修正方案1:正确使用全局变量
只需要在save_data函数开头明确声明要使用全局的df_all,同时调整concat的顺序(让新数据追加到末尾,符合你的预期):
import pandas as pd import numpy as np from IPython.display import display, HTML # 初始化全局的df_all df_all = pd.DataFrame() def save_data(df): global df_all # 关键:告诉Python我们要用全局作用域的df_all # 调整顺序,把新数据追加到现有数据的末尾 df_all = pd.concat([df_all, df], axis=0) display(df_all) return df_all def opt(): df = pd.DataFrame(np.random.randn(1, 4), columns=list('ABCD')) display(df) save_data(df) # 循环执行3次 for i in range(3): opt() display(df_all)
为什么要加global df_all?
- 当你在函数内部给一个变量赋值时,Python默认会将其视为局部变量。如果没有这行声明,函数里的
df_all和全局的df_all是两个完全不同的变量,而你在赋值前就引用了这个局部变量,就会触发"referenced before assignment"的错误。
另外注意pd.concat的顺序:你原来的写法是把新数据放在前面,循环3次后数据顺序会是倒序的(第3次生成的行在最上面),调整顺序后就能按循环顺序保存数据了。
修正方案2:避免全局变量(更推荐)
全局变量容易导致代码耦合度高、不易维护,我们可以通过参数传递的方式来实现需求:
import pandas as pd import numpy as np from IPython.display import display, HTML def save_data(df, df_all): # 直接传入df_all,更新后返回 df_all = pd.concat([df_all, df], axis=0) display(df_all) return df_all def opt(df_all): df = pd.DataFrame(np.random.randn(1, 4), columns=list('ABCD')) display(df) # 调用save_data并接收更新后的df_all df_all = save_data(df, df_all) return df_all # 初始化df_all,循环中不断更新它 df_all = pd.DataFrame() for i in range(3): df_all = opt(df_all) display(df_all)
这种方式把df_all作为参数在函数间传递,每个函数只负责自己的逻辑,代码更清晰,也不会出现作用域混淆的问题。
内容的提问来源于stack exchange,提问作者Samir Alhejaj
相关产品推荐
相关产品推荐

