Python全局变量精神错乱

Ank*_*nkh 13 python

您有三个文件:main.py,second.py和common.py

common.py

#!/usr/bin/python
GLOBAL_ONE = "Frank"
Run Code Online (Sandbox Code Playgroud)

main.py

#!/usr/bin/python
from common import *
from second import secondTest

if __name__ == "__main__":
    global GLOBAL_ONE
    print GLOBAL_ONE #Prints "Frank"
    GLOBAL_ONE = "Bob"
    print GLOBAL_ONE #Prints "Bob"

    secondTest()

    print GLOBAL_ONE #Prints "Bob"
Run Code Online (Sandbox Code Playgroud)

second.py

#!/usr/bin/python
from common import *

def secondTest():
    global GLOBAL_ONE
    print GLOBAL_ONE #Prints "Frank"
Run Code Online (Sandbox Code Playgroud)

为什么secondTest不使用其调用程序的全局变量?如果事实上并非如此,那么称之为"全球性"的东西有什么意义呢?

为了获得secondTest(或我从main调用的任何外部函数)来识别和使用正确的变量,我缺少什么?

nkr*_*rkv 11

global对于这个模块而言意味着全局,而不是整个程序.当你这样做

from lala import *
Run Code Online (Sandbox Code Playgroud)

您添加的所有定义lala当地人给这个模块.

所以在你的情况下你得到两份副本 GLOBAL_ONE


Way*_*ner 5

第一个也很明显的问题是为什么?

在某些情况下,全局变量是必要/有用的,但实际上很少.

您的问题在于命名空间.将common导入second.py时,GLOBAL_ONE来自该命名空间.导入secondTest时,它仍然GLOBAL_ONE从common.py 引用.

然而,你真正的问题在于设计.我想不出一个单一的逻辑很好的理由去实现一个全局变量这种方式.全局变量在Python中是一项棘手的业务,因为没有常量变量这样的东西.但是,惯例是当你想在Python中保持一些常量时,你可以命名它WITH_ALL_CAPS.人机工程学:

somevar = MY_GLOBAL_VAR  # good!
MY_GLOBAL_VAR = somevar  # What? You "can't" assign to a constant! Bad!
Run Code Online (Sandbox Code Playgroud)

做这样的事情有很多原因:

earth = 6e24
def badfunction():
    global earth
    earth += 1e5
print '%.2e' % earth
Run Code Online (Sandbox Code Playgroud)

可怕

当然,如果您只是将其作为理解名称空间和global调用的练习,请继续.

如果没有,全局变量是A Bad Thing™的一些原因是:

  • 命名空间污染
  • 功能集成 - 您希望将功能划分为区域
  • 功能性副作用 - 当您编写修改全局变量的函数时,balance或者您或其他人正在重用您的函数并且不考虑这一点时会发生什么?如果你在计算账户余额,突然间你要么太多,要么不够.像这样的虫子很难找到.

如果你有一个需要值的函数,你应该将该值作为参数传递,除非你有一个非常好的理由.一个原因是拥有PI的全局 - 取决于您可能想要的精度需求3.14,或者您可能想要它3.14159265......但这是一个全局有意义的案例.可能只有少数或两个真实案例可以正确使用全局变量.其中一个案例是游戏编程中的常量.导入pygame.locals并使用KP_UP比记住响应该事件的整数值更容易.这些是规则的例外.

并且(至少在pygame中)这些常量存储在一个单独的文件中 - 仅用于常量.任何需要这些常量的模块都会导入所述常量.

编程时,编写函数将问题分解为可管理的块.优选地,功能应该做件事,并且没有副作用.这意味着诸如calculatetime()之类的函数应该计算时间.它可能不应该读取包含时间的文件,并禁止它应该做一些事情,比如在某个地方时间.它可以返回时间,并在需要时获取参数 - 这些都是函数要做的好的,可接受的事情.函数是您(函数的程序员)和使用该函数的任何人(包括您)之间的一种契约.访问和更改全局变量违反了该合同,因为该函数可以以未定义或预期的方式修改外部数据.当我使用该calculatetime()函数时,我希望它会计算时间并可能返回它,而不是修改响应我刚刚导入的模块时间的全局变量时间.

修改全局变量会破坏合同以及程序所采取的操作之间的逻辑区别.他们可以在您的程序中引入错误.它们使升级和修改功能变得困难.当你使用全局变量作为变量而不是常数时,死亡尖尖的牙齿等待着你!