python中全局变量如何在函数中进行修改

2020-05-19  本文已影响0人  jayhe

最近在将之前写的脚本迁移到python,脚本中需要根据入参来对变量进行赋值,然后再另外一个函数中会用到这个值;按照Objective-C的思维就定义了变量写了脚本,结果跟我的认知不大一样

示范代码

#!/usr/bin/python3
# coding=UTF-8
import shutil
import sys
import os

config = ''
buildEnv =''

def envInit():
    buildEnv = sys.argv[1]
    if buildEnv == 'test':
        config = 'Test
        print(config)
    else:
        config = 'Release'
        print(config)
        
def package():
    cmd = 'config %s' %(config)
    print(cmd)

def exportIpa():
    envInit()
    package()


exportIpa()

问题分析
这里就是变量的作用域问题了,现象上是函数内部的config是局部变量了,而不是我们预期的修改了全局变量config的值

小白就去查了下python的命名空间
python命名空间

python使用命名空间记录变量。python中的命名空间就像是一个dict,key是变量的名字,value是变量的值。

python中,每个函数都有一个自己的命名空间,叫做local namespace,它记录了函数的变量。

python中,每个module有一个自己的命名空间,叫做global namespace,它记录了module的变量,包括 functions, classes 和其它imported modules,还有 module级别的 变量和常量。
还有一个build-in 命名空间,可以被任意模块访问,这个build-in命名空间中包含了build-in function 和 exceptions。

当python中的某段代码要访问一个变量x时,python会在所有的命名空间中寻找这个变量,查找的顺序为:

local namespace - 指的是当前函数或者当前类方法。如果在当前函数中找到了变量,停止搜索
global namespace - 指的是当前的模块。如果在当前模块中找到了变量,停止搜索
build-in namespace - 如果在之前两个namespace中都找不到变量x,python会假设x是build-in的函数或者变量。如果x不是内置函数或者变量,python会报错NameError。

对于闭包来说,这里有一点区别,如果在local namespace中找不到变量的话,还会去父函数的local namespace中找变量。

我们在函数中打印他的locals()

def envInit():
    buildEnv = sys.argv[1]
    if buildEnv == 'test':
        config = 'Test'
        print(config)
        print(locals())
    else:
        config = 'Release'
        print(config)

输出:{'buildEnv': 'test', 'config': 'Test'},果然config是作为envInit函数的局部变量了。这也就是为啥修改了它的值,另外的函数中去输出发现还是初始的值了。

解决方法
既然是命名空间问题,那么我们又想在函数中对全局变量进行修改,同时又避免命名歧义的问题,用global来告诉解释器该变量是全局的。

def envInit():
    global config
    buildEnv = sys.argv[1]
    if buildEnv == 'test':
        config = 'Test'
        print(config)
        print(locals())
        print(globals())
    else:
        config = 'Release'
        print(config)

输出:

# python3 export_ipa.py test
Test
{'buildEnv': 'test'} #函数的局部变量
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x10a2c27b8>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'export_ipa.py', '__cached__': None, 'shutil': <module 'shutil' from '/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.7/lib/python3.7/shutil.py'>, 'sys': <module 'sys' (built-in)>, 'os': <module 'os' from '/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.7/lib/python3.7/os.py'>, 
'config': 'Test', 
'buildEnv': '', 
'envInit': <function envInit at 0x10a2441e0>, 'package': <function package at 0x10a4d2c80>, 'exportIpa': <function exportIpa at 0x10a4d2d08>} # 全局变量
config Test # 输出结果符合预期

可以看到config变量的歧义解决了,在globals变量里;

参考文档

上一篇 下一篇

猜你喜欢

热点阅读