让我们说我有以下代码
df1 = ['a']
df2 = ['a']
def some_method():
global df1
global df2
df1 = pd.DataFrame(Some populated dataframe...)
df2 = pd.DataFrame(Some populated dataframe...)
def test(my_df=df1):
print(my_df)
在以下场景中,当没有参数调用test()时,df1输出[' a']。当df1 / df2以params
传入时将打印出来some_method()
test() # Prints out ['a']
test(df1) # Works as expected
test(df2) # Works as expected
有人可以解释为什么测试方法中定义的默认值不起作用吗?
答案 0 :(得分:1)
这里发生的事情是三个棘手的Python属性的结果,很难记住:
定义test()
时,my_df
绑定到df1
引用的当前全局对象,在您的情况下为['a']
。调用some_method()
时,会将全局名称df1
的引用更改为您的数据框,但my_df
已绑定到上一个df1
后面的对象({{ 1}})。它不受['a']
引用本身的约束。
简化说明:
df1
kbball建议重新安排,这有效,因为它定义a = 1
b = a
a = 3
print(a)
>>> 3
print(b)
>>> 1
并在定义some_method()
之前运行它,这意味着在test()
定义期间,全局test()
现在引用数据帧。和以前一样,df1
指向my_df=df1
引用后面的对象,但现在已经更改为数据框,因此df1
将打印出来。
要查看此操作,请使用已发布的当前代码,但要添加到测试中:
test()
然后,您的解决方案是重新安排代码,以便在调用print(df1) # will print out ['a']
some_method() # changes object references of global names df1, df2
print(df1) # will print out dataframe
test() # Prints out ['a']
test(df1) # Works as expected
test(df2) # Works as expected
后定义test()
(您不需要kbball包含的返回),或者,您可以确保{ test中的{1}}每次运行时都会引用当前的全局名称some_method()
:
df1
我知道这是一个很长的解释,但我希望它能为你解决这个问题。这是一个不稳定的问题。
[1] https://jeffknupp.com/blog/2012/11/13/is-python-callbyvalue-or-callbyreference-neither/
答案 1 :(得分:0)
我认为你只需要做一些重新安排:
import pandas as pd
import numpy as np
df1 = ['a']
def some_method():
global df1
df1 = pd.DataFrame(np.random.randint(0,100, size=(10, 4)), columns=list('ABCD'))
return df1
some_method()
def test(my_df=df1):
print(my_df)
test()
#output
A B C D
0 95 83 33 92
1 22 68 87 99
2 61 37 11 51
3 18 76 77 47
4 1 9 38 21
5 27 87 75 56
6 55 95 62 98
7 78 49 93 48
8 83 54 40 23
9 2 82 3 57