Python 通过引用传递数据帧

Python 通过引用传递数据帧,python,pandas,dataframe,pass-by-reference,immutability,Python,Pandas,Dataframe,Pass By Reference,Immutability,我的问题是关于熊猫数据帧通过引用传递时的不变性。考虑下面的代码: import pandas as pd def foo(df1, df2): df1['B'] = 1 df1 = df1.join(df2['C'], how='inner') return() def main(argv = None): # Create DataFrames. df1 = pd.DataFrame(range(0,10,2), columns=['A'])

我的问题是关于熊猫数据帧通过引用传递时的不变性。考虑下面的代码:

import pandas as pd

def foo(df1, df2):

    df1['B'] = 1
    df1 = df1.join(df2['C'], how='inner')

    return()

def main(argv = None):

    # Create DataFrames. 
    df1 = pd.DataFrame(range(0,10,2), columns=['A'])
    df2 = pd.DataFrame(range(1,11,2), columns=['C'])

    foo(df1, df2)    # Pass df1 and df2 by reference.

    print df1

    return(0)

if __name__ == '__main__':
    status = main()
    sys.exit(status)
输出是

   A  B  
0  0  1
1  2  1
2  4  1
3  6  1
4  8  1
而不是

   A  B  C
0  0  1  1
1  2  1  3
2  4  1  5
3  6  1  7
4  8  1  9
事实上,如果foo被定义为

def foo(df1, df2):

    df1 = df1.join(df2['C'], how='inner')
    df1['B'] = 1

    return()
(即,在另一个语句之前的“join”语句)则输出为

   A    
0  0 
1  2 
2  4 
3  6 
4  8

我很好奇为什么会这样。如果您有任何见解,我们将不胜感激。

问题在于这一行:

df1 = df1.join(df2['C'], how='inner')
df1.join(df2['C'],how='inner')
返回一个新的数据帧。在这一行之后,
df1
不再引用与参数相同的数据帧,而是引用一个新的数据帧,因为它已被重新分配给新的结果。第一个数据帧继续存在,未经修改。这不是一个真正的问题,只是python和大多数其他语言的一般工作方式


有些函数有一个
inplace
参数,可以执行您想要的操作,但是join操作没有。如果需要修改数据帧,则必须返回此新数据帧,并在函数外部重新分配它。

问题是因为这一行:

df1 = df1.join(df2['C'], how='inner')
df1.join(df2['C'],how='inner')
返回一个新的数据帧。在这一行之后,
df1
不再引用与参数相同的数据帧,而是引用一个新的数据帧,因为它已被重新分配给新的结果。第一个数据帧继续存在,未经修改。这不是一个真正的问题,只是python和大多数其他语言的一般工作方式


有些函数有一个
inplace
参数,可以执行您想要的操作,但是join操作没有。如果需要修改数据帧,则必须返回此新数据帧,并在函数外部重新分配它。

Python没有“按值传递”与“按引用传递”之比——只有两种

如果您将函数更改为

def foo(df1, df2):

    res = df1.join(df2['C'], how='inner')
    res['B'] = 1

    return res
然后,函数中的
df1
df2
将绑定到您发送的对象。
join
(在本例中是一个新对象)的结果绑定到名称
res
。您可以在不影响任何其他对象或绑定的情况下操作并返回它

在您的呼叫代码中,您可以只编写

print foo(df1, df2)

Python没有按值传递和按引用传递,只有

如果您将函数更改为

def foo(df1, df2):

    res = df1.join(df2['C'], how='inner')
    res['B'] = 1

    return res
然后,函数中的
df1
df2
将绑定到您发送的对象。
join
(在本例中是一个新对象)的结果绑定到名称
res
。您可以在不影响任何其他对象或绑定的情况下操作并返回它

在您的呼叫代码中,您可以只编写

print foo(df1, df2)

顺便说一句,return不是一个函数,它只是一个语句,所以不需要在它后面加括号。这是我所知道的关于Python名称如何工作的最好的讨论。一旦你明白了这一点,你就会明白这种行为。谢谢@chthonicdaemon!顺便说一句,return不是一个函数,它只是一个语句,所以不需要在它后面加括号。这是我所知道的关于Python名称如何工作的最好的讨论。一旦你明白了这一点,你就会明白这种行为。谢谢@chthonicdaemon!谢谢@Jezzamon。这很有道理。谢谢@Jezzamon。这是有道理的。