【问题标题】:accessing "module scope" vars访问“模块范围”变量
【发布时间】:2011-07-27 09:05:31
【问题描述】:

我目前正在学习 Python,我必须从事 Python 2.7 项目。

在模块本身的函数中访问“模块范围”变量对我来说有点困惑,我没有成功找到令人满意的方法。

到目前为止我的尝试:

方式一:

my_module.py

my_global_var = None

def my_func():
    global my_global_var
    my_global_var = 'something_else'

在这里,我认为混淆本地和“模块范围”变量可能很容易。

方式 2:

my_module.py

import my_module

my_global_var = None

def my_func():
    my_module.my_global_var = 'something_else'

在这里,“my_module”的名称在必要时不能像“way 1”那样容易更改。另外,将模块导入自身听起来很奇怪。

你会推荐什么?或者你会建议别的吗?谢谢。

【问题讨论】:

  • 不要使用Way 2,使用Way 1。 Python 作用域和赋值很有趣。从名称中读取值时,解释器将始终从最内部的范围向外搜索名称。当您为名称分配值时,它会在当前范围内执行此操作。这意味着如果您在没有 global 关键字的情况下分配给 my_global_var,那么您的模块将具有两个不同的 my_global_var,从嵌套范围分配点开始,在嵌套范围之外。全局语句只是告诉解释器将值分配给名称 my_global_varglobal 范围。

标签: python variables module scope coding-style


【解决方案1】:

您可能想阅读Python's namespaces。方法 1 是正确的,但通常是不必要的,永远不要使用 2。更简单的方法是只使用 dict(或类或其他对象):

my_globals = {'var': None}

def my_func():
    my_globals['var'] = 'something else'

赋值总是进入最内部的范围,并且总是首先搜索最内部的范围,因此需要全局关键字。在这种情况下,您没有分配名称,因此没有必要。

【讨论】:

  • 啊。因此可以在函数范围内修改 dict 值,但不能修改原始字符串值。 Python在这里似乎很违反直觉。无论如何,这很有效,完全符合我的需要。谢谢
  • 分配总是进入最里面的范围并且总是首先被搜索,因此需要global关键字。在这种情况下,您没有分配名称,因此没有必要(Python 将搜索最内层范围,而不是找到 my_globals 最终到达模块级范围。
  • 感谢您对此行为的详细解释。我明白了。
  • @FrostyZ 你可以不使用全局关键字修改任何可变对象。
  • 感谢您的回答。请问一个问题:所以只要你没有任何与字典同名的局部变量,使用字典就很好?这是否意味着依赖开发人员之间可能不受尊重的约定?我想防止与 one 全局变量发生名称冲突比防止与无限数量的全局变量发生冲突要好得多。但是,在使用变量之前明确声明 global 不是更好吗?
【解决方案2】:

当您绝对必须重新绑定全局变量时,方法 1 是正确的方法。但是,您应该问自己为什么要修改全局以及是否可以做一些更好的事情(例如将行为封装在一个类中)。

应避免将模块导入自身,因为它容易出错。如果模块也是一个脚本,你有时需要导入__main__,或者如果模块是包的一部分,你可能应该导入foo.my_module。简而言之,不要那样做。

【讨论】:

    【解决方案3】:

    在其内部导入模块可能会产生不必要的副作用(例如多次评估语句。)我建议使用“Way 1”和 pylint 之类的工具来帮助验证您的代码并执行常见做法。

    PyLint 位于:http://www.logilab.org/project/pylint

    【讨论】:

      【解决方案4】:

      完全避免设置全局变量。你可以很容易地用类创建新的命名空间,所以如果你必须使用类变量。

      对于任何严肃的事情,无论如何你都需要一个适当的类设计。

      【讨论】:

      • 感谢您的回答。我想创建一个单例,推荐的方法似乎只是创建一个模块(参见stackoverflow.com/questions/31875/…),所以在这种特殊情况下我宁愿避免使用一个类。
      • @FrostyZ - 我建议不要将模块用作单例,如果没有其他原因,它会使单元测试变得非常困难。见 stackoverflow.com/questions/31875/…>
      • 即使用于测试,一些单例似乎也可以接受(例如记录器)。见googletesting.blogspot.com/2008/08/…
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-10
      • 1970-01-01
      • 1970-01-01
      • 2012-06-09
      • 1970-01-01
      相关资源
      最近更新 更多