python中的内置globals()函数实例详解

作者:

文章目录
  • globals() 是Python的标准内置函数,用于返回当前模块中定义的全局变量的字典(包含所有的全局变量、函数、类、导入的模块),其中键是变量名,值是变量的值。字典可进行修改,修改后会随之反映到全局变量上。对于函数内的代码,返回的为在定义函数时确定的该字典,无论在哪里调用都保持不变。globals是特殊场景的解决方案,如动态批量处理全局变量/函数(eg:配置加载)、调试时快速排查全局状态问题、框架/库的底层实现,且有完善的封装和文档。缺点:可读性差,命名冲突、作用域误区、线程不安全、性能损耗、破坏封装重点:非必要不使用,优先使用字典/类进行替代,使用时做好校验、锁和注释。
  • 核心价值是动态操作全局命名空间,由于操作的是全局状态,使用时需要谨慎。1、批量处理配置变量、根据配置变量名读取对应的值 config0= 10 config1 = 30 config2 = “INFO” # 变量名来自外部(如配置文件、用户输入) config_keys = [“config0”, “config1”, “config2″] # 动态读取所有配置 for key in config_keys: if key in globals(): print(f”{key}: {globals()[key]}”) 运行结果: 2、批量初始化编码前,无法预知所有的变量名或需要生成大量相似的变量名,需要通过代码逻辑批量生成全局变量 3、函数内部修改全局变量编码需要时,则需要使用,此处不进行举例说明了。
  • globals()直接操作全局命名空间,滥用会导致代码可读性、可维护性大幅下降,甚至引发隐藏bug1、严重降低代码可读性与可维护性动态操作的变量/函数名是字符串,IDE无法自动补全、跳转,代码审查时难以追踪变量的定义/修改位置,后期维护成本高,如下图所示: 上方globals()里面变量/函数内容很多,某个变量随时可能被其他方法更改,当出现问题时,排查很困难。下方单独使用var_dict很清晰能知道变量是在哪里来的,在哪里修改的。2、易引发命名冲突与意外覆盖全局命名空间包含模块顶层定义的变量、函数、类等,globals()动态创建/修改变量,若名称与已有重复,则会静默覆盖原有对象。在程序中,如不小心覆盖内置函数,在访问中可能会遇到报错,如下所示 在程序中,如多处动态给某个变量赋值,则会造成功能错误 如上所示,本身天津和重庆都有叫张三的,结果由于程序后面进行了覆盖,只保留了最后的值。这种在程序中也不存在语法错误,在排查bug时会比较麻烦建议:动态命名时加前缀,避免与内置名、已有变量重名操作赋值前,先校验是否为已有变量3、globals()作用区域理解存在误区python中的几种作用域可详见:https://www.jb51.net/python/344628qyu.htm很多人会误以为globals()可以获取到外层函数作用域,实际是未搞清楚外层函数的变量的作用域为嵌套作用域,不会影响全局变量。嵌套函数想访问外层函数变量,需要使用nonlocal或local(),而非globals() 4、多线程时,存在线程安全问题多线程同时通过globals()读写全局变量时,同时修改一个变量,会导致数据不一致。 count = 0 def increment(): for _ in range(100000): globals()[“count”] += 1 t1 = threading.Thread(target=increment) t2 = threading.Thread(target=increment) t1.start() t2.start() t1.join() t2.join() print(count) 运行结果是200000,但是实际结果是随机,如下 可以通过加锁的形式,访问全局变量从而保证结果的正确性。 def increment(): for _ in range(100000): while threading.Lock(): globals()[“count”] += 1 5、性能损耗:尤其频繁操作globals返回的字典,字典的键查找/赋值比直接访问变量要慢,尤其在频繁操作时会累积性能损耗。建议循环中需要频繁操作局部变量时,先将赋值给局部变量,操作完成后再赋值给全局变量 到此这篇关于python中的内置globals()详解的文章就介绍到这了,更多相关python内置globals()内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客! 您可能感兴趣的文章: python内置函数globals()的实现代码 Python 内置函数globals()和locals()对比详解 Python基础教程之内置函数locals()和globals()用法分析 python中的内置globals()函数实例详解 Python3中的globals()函数用法及说明
  • 目录
    • 一、基本情况
    • 二、常用场景实例
    • 三、使用注意事项

    最近在看一段代码时,发现作者使用globals()来应对无法确定变量名的情况,故此对该函数进行了详细的了解。

    globals() 是Python的标准内置函数,用于返回当前模块中定义的全局变量的字典(包含所有的全局变量、函数、类、导入的模块),其中键是变量名,值是变量的值。字典可进行修改,修改后会随之反映到全局变量上。对于函数内的代码,返回的为在定义函数时确定的该字典,无论在哪里调用都保持不变。
    globals是特殊场景的解决方案,如动态批量处理全局变量/函数(eg:配置加载)、调试时快速排查全局状态问题、框架/库的底层实现,且有完善的封装和文档。
    缺点:可读性差,命名冲突、作用域误区、线程不安全、性能损耗、破坏封装
    重点:非必要不使用,优先使用字典/类进行替代,使用时做好校验、锁和注释。

    核心价值是动态操作全局命名空间,由于操作的是全局状态,使用时需要谨慎。
    1、批量处理配置变量、根据配置变量名读取对应的值

    config0= 10
    config1 = 30
    config2 = "INFO"
    # 变量名来自外部(如配置文件、用户输入)
    config_keys = ["config0", "config1", "config2"]
    # 动态读取所有配置
    for key in config_keys:
        if key in globals():
            print(f"{key}: {globals()[key]}")

    运行结果:

    2、批量初始化
    编码前,无法预知所有的变量名或需要生成大量相似的变量名,需要通过代码逻辑批量生成全局变量

    3、函数内部修改全局变量
    编码需要时,则需要使用,此处不进行举例说明了。

    globals()直接操作全局命名空间,滥用会导致代码可读性、可维护性大幅下降,甚至引发隐藏bug
    1、严重降低代码可读性与可维护性
    动态操作的变量/函数名是字符串,IDE无法自动补全、跳转,代码审查时难以追踪变量的定义/修改位置,后期维护成本高,如下图所示:

    上方globals()里面变量/函数内容很多,某个变量随时可能被其他方法更改,当出现问题时,排查很困难。下方单独使用var_dict很清晰能知道变量是在哪里来的,在哪里修改的。
    2、易引发命名冲突与意外覆盖
    全局命名空间包含模块顶层定义的变量、函数、类等,globals()动态创建/修改变量,若名称与已有重复,则会静默覆盖原有对象。
    在程序中,如不小心覆盖内置函数,在访问中可能会遇到报错,如下所示

    在程序中,如多处动态给某个变量赋值,则会造成功能错误

    如上所示,本身天津和重庆都有叫张三的,结果由于程序后面进行了覆盖,只保留了最后的值。这种在程序中也不存在语法错误,在排查bug时会比较麻烦
    建议:动态命名时加前缀,避免与内置名、已有变量重名
    操作赋值前,先校验是否为已有变量

    3、globals()作用区域理解存在误区
    python中的几种作用域可详见:https://www.jb51.net/python/344628qyu.htm
    很多人会误以为globals()可以获取到外层函数作用域,实际是未搞清楚外层函数的变量的作用域为嵌套作用域,不会影响全局变量。嵌套函数想访问外层函数变量,需要使用nonlocal或local(),而非globals()

    4、多线程时,存在线程安全问题
    多线程同时通过globals()读写全局变量时,同时修改一个变量,会导致数据不一致。

    count = 0
    def increment():
        for _ in range(100000):
            globals()["count"] += 1
    t1 = threading.Thread(target=increment)
    t2 = threading.Thread(target=increment)
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    print(count)

    运行结果是200000,但是实际结果是随机,如下

    可以通过加锁的形式,访问全局变量从而保证结果的正确性。

    def increment():
        for _ in range(100000):
            while threading.Lock():
                globals()["count"] += 1
    

    5、性能损耗:尤其频繁操作
    globals返回的字典,字典的键查找/赋值比直接访问变量要慢,尤其在频繁操作时会累积性能损耗。
    建议循环中需要频繁操作局部变量时,先将赋值给局部变量,操作完成后再赋值给全局变量

    到此这篇关于python中的内置globals()详解的文章就介绍到这了,更多相关python内置globals()内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!

    您可能感兴趣的文章:

    • python内置函数globals()的实现代码
    • Python 内置函数globals()和locals()对比详解
    • Python基础教程之内置函数locals()和globals()用法分析
    • python中的内置globals()函数实例详解
    • Python3中的globals()函数用法及说明

    站内搜索