在Python中使用全局变量?

时间:2017-07-03 04:35:07

标签: python pandas dataframe scope

我无法在其他函数中引用原始数据帧,即print_df_in_a_function()。有人可以告诉我在这里犯的错误吗?

在致电None时显示print_df_in_a_function()

import numpy as np
import pandas as pd

df1 = None

def main():
    df1 = pd.DataFrame(np.array([['a', 5, 9],
                                 ['b', 4, 61],
                                 ['c', 24, 9]]),
                                 columns=['name', 'attr1', 'attr2'])

    print(df1)
    print_df_in_a_function()

def print_df_in_a_function():
    print(df1)

if __name__ == '__main__':
    main()

3 个答案:

答案 0 :(得分:2)

问题是df1内的print_df_in_a_function解析为全球 df1,而不是df1 本地main。这是因为Python具有词法作用域而不是动态作用域。来自wikipedia

  

范围界定的一个根本区别是"程序的一部分"   手段。在具有词法范围的语言中(也称为静态范围),   名称解析取决于源代码中的位置和   词汇上下文,由命名变量或的位置定义   功能已定义。相比之下,在具有动态范围的语言中   名称解析取决于名称时的程序状态   遇到的是由执行上下文或调用确定的   上下文。在实践中,对于词法范围,变量的定义是   通过搜索其包含的块或函数解决,然后如果那样   无法搜索外部包含块,依此类推,而使用   查询调用函数的动态范围,然后是函数   它调用了调用函数,等等,进行调用   叠加。[4]当然,在这两个规则中,我们首先寻找一个本地   变量的定义。

如果Python确实使用动态作用域,它可以按预期工作。相反,由于词法范围,我们会看到这种行为:

In [1]: import numpy as np
   ...: import pandas as pd
   ...:
   ...: df1 = None
   ...:
   ...: def main():
   ...:     df1 = pd.DataFrame(np.array([['a', 5, 9],
   ...:                                  ['b', 4, 61],
   ...:                                  ['c', 24, 9]]),
   ...:                                  columns=['name', 'attr1', 'attr2'])
   ...:
   ...:     print(df1)
   ...:     print_df_in_a_function()
   ...:
   ...: def print_df_in_a_function():
   ...:     print(df1)
   ...:
   ...: if __name__ == '__main__':
   ...:     main()
   ...:
  name attr1 attr2
0    a     5     9
1    b     4    61
2    c    24     9
None

请注意,如果我们移动print_df_in_a_function的定义,则名称会解析为df1内的main

In [3]: import numpy as np
   ...: import pandas as pd
   ...:
   ...: df1 = None
   ...:
   ...: def main():
   ...:     def print_df_in_a_function():
   ...:         print(df1)
   ...:     df1 = pd.DataFrame(np.array([['a', 5, 9],
   ...:                                  ['b', 4, 61],
   ...:                                  ['c', 24, 9]]),
   ...:                                  columns=['name', 'attr1', 'attr2'])
   ...:
   ...:     print(df1)
   ...:     print_df_in_a_function()
   ...:
   ...: if __name__ == '__main__':
   ...:     main()
   ...:
  name attr1 attr2
0    a     5     9
1    b     4    61
2    c    24     9
  name attr1 attr2
0    a     5     9
1    b     4    61
2    c    24     9

因为在尝试解析名称时,Python首先检查本地范围(print_df_in_a_function的本地范围)。然后,如果它没有找到它,它会检查任何包含的范围。在这种情况下,main的范围有df1,因此名称解析就此结束。但是,如果您删除df1中的名称main,它仍会找到全局df1

In [5]: import numpy as np
   ...: import pandas as pd
   ...:
   ...: df1 = None
   ...:
   ...: def main():
   ...:     df1 = pd.DataFrame(np.array([['a', 5, 9],
   ...:                                  ['b', 4, 61],
   ...:                                  ['c', 24, 9]]),
   ...:                                  columns=['name', 'attr1', 'attr2'])
   ...:
   ...:     print(df1)
   ...:     del df1
   ...:     print_df_in_a_function()
   ...:
   ...: def print_df_in_a_function():
   ...:     print(df1)
   ...:
   ...: if __name__ == '__main__':
   ...:     main()
   ...:
  name attr1 attr2
0    a     5     9
1    b     4    61
2    c    24     9
None

答案 1 :(得分:0)

我采用了一个更简单的示例,global指令解决了这个问题。

df1 = None

def main():
    global df1 #This is the magic line that references the global variable
    df1 = 1
    print(df1)
    print_df_in_a_function()

def print_df_in_a_function():
    print(df1)

main()

您的代码将是:

import numpy as np
import pandas as pd

df1 = None

def main():
    global df1
    df1 = pd.DataFrame(np.array([['a', 5, 9],
                                 ['b', 4, 61],
                                 ['c', 24, 9]]),
                                 columns=['name', 'attr1', 'attr2'])

    print(df1)
    print_df_in_a_function()

def print_df_in_a_function():
    print(df1)

if __name__ == '__main__':
    main()

答案 2 :(得分:0)

为此,您需要了解变量范围的工作原理。看看这个!

def my_func():
    index3 =5000
    print(index3)

index3=10;
print(index3)
my_func()

输出:

10
5000

注意:即使有两个index3,您可能会认为它们是相同的。但他们不是

my_func中的index3是一个局部变量。虽然程序中的那个(不在函数中的那个)index3是不同的!那么在上面的代码中发生的是第一个print(index3)在我的代码中打印index3(不在任​​何函数中......只是在我的程序中)然后调用my_func()并在my_func()中打印(index3)打印本地变量index3

看看这个!

def my_func():
    print(index3)

index3=10;
print(index3)
my_func()

输出:

10
10

现在两次看到index3都是相同的10这意味着它会打印全局变量两次。

现在看:

def my_func():
    index3 =index3+1

index3=10;
print(index3)
my_func()

输出:

10
Traceback (most recent call last):
  File "/home/mr/func.py", line 6, in <module>
    my_func()
  File "/home/mr/func.py", line 2, in my_func
    index3 =index3+1
UnboundLocalError: local variable 'index3' referenced before assignment

为什么?

因为这个index3 =index3+1所以当它看到一个index3 =它会创建一个局部变量。所以index3 = 0表示将0赋给局部变量。

但是index3 = index3 + 1会让人感到困惑!它认为

等你想让我将局部变量index3指定为局部变量index3 + 1吗?但你还没有宣布它!

def my_func():
    global index3
    index3 =index3+1
    print(index3)

index3=10
print(index3)
my_func()
print(index3)

输出:

10
11
11

现在它在函数中获取全局值并且它会发生变化。所以index3由函数改变。

注意:使用全局变量是错误的编码实践。

def getIndex3():
    return index3

def my_func():
    index3 = getIndex3()
    index3 =index3+1
    print(index3)

index3=10
print(index3)
my_func()
print(index3)

现在输出:

10
11
10

所以在你的情况下。

def print_df_in_a_function():
    print(df1)

这也解决了程序中的df1=None(全局位于顶部)。并不代表你的主要df1

但是,您可以通过将df1在主中)传递到您的

来实现您的目标
print_df_in_a_function(df1)

现在发生的事情是df1具有值(您的数据帧)将传递给您的print_df_in_a_function(df1):,现在您可以打印该值。像这样,

import numpy as np
import pandas as pd

df1 = None

def main():
    df1 = pd.DataFrame(np.array([['a', 5, 9],
                                 ['b', 4, 61],
                                 ['c', 24, 9]]),
                                 columns=['name', 'attr1', 'attr2'])

    print(df1)
    print_df_in_a_function(df1)

def print_df_in_a_function(df1):
    print(df1)

if __name__ == '__main__':
    main()

输出:

  name attr1 attr2
0    a     5     9
1    b     4    61
2    c    24     9
  name attr1 attr2
0    a     5     9
1    b     4    61
2    c    24     9
>>>