Python 使用pandas.apply()时在赋值前引用的局部变量

Python 使用pandas.apply()时在赋值前引用的局部变量,python,pandas,Python,Pandas,我有一个奇怪的范围问题。以下代码是Jupyter笔记本中的一个单元格。我已在相关检查()中分配了p1\u总值和p2\u总值。然后,在后面的correlation\u check()中,定义了项目值(行),并最终应用于数据帧 当我运行这段代码时,我得到一个unbundLocalError,表示分配之前引用了p1\u total\u value。如果我将全局p1_总值添加到项目值(行),它会告诉我p1_总值未定义。在correlation\u check()中,pandas.apply()似乎发生在

我有一个奇怪的范围问题。以下代码是Jupyter笔记本中的一个单元格。我已在
相关检查()中分配了
p1\u总值
p2\u总值
。然后,在后面的
correlation\u check()
中,定义了
项目值(行)
,并最终应用于数据帧

当我运行这段代码时,我得到一个unbundLocalError,表示分配之前引用了
p1\u total\u value
。如果我将
全局p1_总值
添加到
项目值(行)
,它会告诉我
p1_总值
未定义。在
correlation\u check()
中,pandas.apply()似乎发生在它前面的代码之前


请在函数外分配
p1_总值
,然后在函数内分配
全局p1_总值

扩展juanpa的注释,您可以将
p1_总值
p2_总值
声明为内部函数的
非局部

def相关性检查(游戏):
...
p1_总_值=0
p2\u总值=0
...
def项目_值(行):
非局部p1_总值,p2_总值
如果在第行中“播放”。操作:
项目名称=row.Action.split('played')[1]
gen=圆形(压缩*int(行生成))
项目行=计算值[计算值.标题==项目名称]
value=int(项目行[f'value Gen{Gen}']
如果int(row.Player)==1:
p1_总_值+=值
其他:
p2_总_值+=值
游戏=游戏。应用(项目值,轴=1)

原始答案(无效) 此原始答案从技术上消除了错误,但不会修改外部副本

尝试将
p1\u总值
p2\u总值
作为
args
传递:

def项目值(行、p1总值、p2总值):
如果在第行中“播放”。操作:
项目名称=row.Action.split('played')[1]
gen=圆形(压缩*int(行生成))
项目行=计算值[计算值.标题==项目名称]
value=int(项目行[f'value Gen{Gen}']
如果int(row.Player)==1:
p1_总_值+=值
其他:p2_总值+=值
游戏=游戏。应用(项目值,参数=(p1总值,p2总值),轴=1)

您应该用两个条目的列表替换p1_total_值和p2_total_值。这样,您可以修改函数中的列表成员,这将起作用。这就消除了名称空间问题。同样的技巧也可以应用到最后的分数上

        
    total_value = [0,0]
    
    p1_final_score = game.iloc[-2].Action
    p2_final_score = game.iloc[-1].Action
        

    def project_value(row):
        
        if 'played' in row.Action:
            project_name = row.Action.split('played ')[1]
            gen = round(compression * int(row.Generation))
            project_row = calculated_values[calculated_values.Title == project_name]
            value = int(project_row[f'Value Gen{gen}'])
            
            if int(row.Player) == 1:
                total_value[0] += value
            else:
                total_value[1] += value
            
    game = game.apply(project_value, axis=1)

我在帖子中提到,我试过了,但收到一个错误,
var
未定义。你有没有试过将它作为一个包含所有这些函数的类中的属性?我没有;虽然它是一个没有任何现有oop的长文档,所以我不确定仅仅为这一个小问题添加任何oop是否有意义。不过,总的来说,这是一个可行的解决方案。我想你知道他并不是字面上的意思
var
。他指的是您试图更改的变量。@TimRoberts是的。我建议您用两个条目的列表替换
p1\u total\u value
p2\u total\u value
。这样,您可以修改函数中的列表成员,这将起作用。这样就消除了名称空间问题。请使用
非本地
statement@TimRoberts列出两个条目非常有效。虽然我很欣赏一种解决方案,但您是否知道,即使我在内部函数中使用了
Global
,为什么内部函数也看不到在外部函数中分配的变量?我猜想pandas.apply()。@juanpa.arrivillaga一定是有某种特殊性,导致了与使用全局语句相同的错误。它说问题中的变量没有定义。不,没有。你到底在哪里做什么?您需要执行
非局部p1\u总值,p2\u总值
无法工作的
项目值的第一行。它更改了局部变量,但局部副本与外部副本没有连接。我没有足够的代表对此进行投票,但这是我正在使用的解决方案。虽然对于
p1_final_score
p2_final_score
是不必要的,因为它们在内部函数中不可访问。你真的应该使用
非本地
,这有点像黑客。@juanpa.arrivillaga我不同意。通过
非本地
泄漏值是一种黑客行为,主要是因为Python的命名空间规则有点不透明。它们一点也不不透明。赋值始终是默认本地的,除非您使用
全局
非本地
方向。您的方法依赖于运行时的隐式命名空间解析,使用
非本地
将在编译时解决此问题,如果这些名称没有封闭范围,甚至无法编译代码
        
    total_value = [0,0]
    
    p1_final_score = game.iloc[-2].Action
    p2_final_score = game.iloc[-1].Action
        

    def project_value(row):
        
        if 'played' in row.Action:
            project_name = row.Action.split('played ')[1]
            gen = round(compression * int(row.Generation))
            project_row = calculated_values[calculated_values.Title == project_name]
            value = int(project_row[f'Value Gen{gen}'])
            
            if int(row.Player) == 1:
                total_value[0] += value
            else:
                total_value[1] += value
            
    game = game.apply(project_value, axis=1)