【问题标题】:scope of imported variables导入变量的范围
【发布时间】:2021-06-01 20:36:18
【问题描述】:

我在 python3.8 脚本中遇到了一种情况,在从外部文件导入一堆变量后,在某些函数中可以正常访问它们,而在其他函数中则不能。例如。在文件tm_constants.py 中定义了一个常量min_time_n_clicks,并带有一个简单的声明,

min_time_n_clicks=10

请原谅这不是一个可重复的示例,因为完整的代码很长,它试图展示我所遇到的:在一个函数函数 check_scope 我可以使用 from tm_constants import * 访问变量,而另一个函数check_for_limiting 看不到它们 - 它命中了

UnboundLocalError: local variable 'min_time_n_clicks' referenced before assignment

为什么会这样?我从不使用 del 等删除变量,在我使用的 pycharm 调试器中,即使在有问题的函数范围内,也可以看到和评估有问题的变量 (min_time_n_clicks)。使用点符号访问是否是首选方法,如果是,为什么?

from tm_constants import *
import tm_constants

def check_scope():

    print(f'ok: {min_time_n_clicks}')
    print(f'ok: {tm_constants.min_time_n_clicks}')

def check_for_limiting():
    print(tm_constants.min_time_n_clicks)
    tm_constants.min_time_n_clicks = 0  # ok 
    print(min_time_n_clicks)
    min_time_n_clicks = 0 # not ok !!!

【问题讨论】:

  • 我看不出问题出在哪里,如果没有对模块 tm_constants 的最小定义,我无法重现该问题。
  • 我不知道你是如何得到一个 UnboundLocalError 而没有分配给函数中的名称的。
  • 如果tm_constants.pytmp.py 定义如图所示(加上调用check_scope()check_for_limiting(None)),python3 tmp.py 不会产生UnboundLocalError
  • @chepner 是的,我过度编辑了我的函数,原版。有一些任务。代码太长,我无法完整添加,并不意味着是可重现的示例
  • 仍然没有错误。但是,如果您尝试在赋值之前打印 global min_time_n_clicks 的值,则会收到错误消息。 presense 将名称标记为本地的分配,而不是运行时的实际分配。也就是说,不能在同一个作用域内使用同名的全局和局部。

标签: python import global python-3.8


【解决方案1】:

这将产生一个UnboundLocalError

def check_for_limiting(browser):
    print(min_time_n_clicks)
    min_time_n_clicks = 0

编译函数定义时,解析器根据赋值将min_time_n_clicks标记为局部变量。这意味着函数范围内名称的所有 使用指的是局部变量,即使是在赋值之前 发生的那些使用。即使在运行时无法达到分配也是如此:

def check_for_limiting(browser):
    print(min_time_n_clicks)  # Still raises an UnboundLocalError
    if False:
        min_time_n_clicks = 0

如果您的意图是分配给全局变量,则需要使用global 将名称标记为全局:

def check_for_limiting(browser):
    global min_time_n_clicks

    print(min_time_n_clicks)
    min_time_n_clicks = 0

点分访问没有问题,因为在这种情况下没有名为min_time_n_clicks 的变量;只有全局名称tm_constants 引用了一个具有名为min_time_n_clicks属性 的对象。进一步注意,直接分配给min_time_n_clicks不会更改tm_constants.min_time_n_clicks 的值,因为它们是对同一对象的两个不同引用。更改一个引用不会更改另一个引用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-10
    相关资源
    最近更新 更多