Python - 在方法中使用dataframe的默认值

时间:2018-01-18 15:53:01

标签: python pandas

让我们说我有以下代码

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

有人可以解释为什么测试方法中定义的默认值不起作用吗?

2 个答案:

答案 0 :(得分:1)

这里发生的事情是三个棘手的Python属性的结果,很难记住:

  1. 名称是对象的引用,但与对象本身无关
  2. 可变和不可变对象以不同的方式处理链式引用[1]
  3. "在"中读取模块定义时,将创建模块的全局命名空间。 [2]
  4. 定义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/

    [2] https://docs.python.org/3/tutorial/classes.html

答案 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