【问题标题】:Python "import" scopePython“导入”范围
【发布时间】:2011-03-07 13:44:22
【问题描述】:

我正在处理一些为我自动生成的 python 代码。我想避免手动编辑这些 python 文件,因此这个问题/问题:

foo.py:

def foo():
  print "foo"

boo.py:

def boo():
  foo.foo()    # <-- global name 'foo' not defined
  print "boo"

bar.py:

import foo
import boo
def bar():
  boo.boo()
  print "bar"

执行:

python.exe bar.py

给出boo 没有找到foo 的错误。但是 bar 正在同时导入 fooboofoo 不应该自动提供给boo 吗?

有没有办法做到这一点?如前所述,boo.py 是为我自动生成的,我想避免将 import foo 添加到 boo.py

谢谢。

【问题讨论】:

    标签: python import


    【解决方案1】:

    没有。如果您希望fooboo 中可用,则需要在boo 中导入它。 bar 中的 import foo 仅使 foobar 模块中可用。

    一般来说,Python 中的import 语句有点像变量定义。你其实可以这样想:精神上的替换

    import boo
    

    boo = __import__('boo')
    

    __import__ 是 Python 解释器的内置函数,它可以导入一个模块,或者在现有模块已被导入时查找对现有模块的引用,然后返回该引用)

    任何自动生成boo.py 的东西都做错了。它应该在该文件中的某处添加import foo。您可以通过在bar.py 中执行此操作来解决它:

    import foo
    import boo
    boo.foo = foo
    

    但你真的不应该这样做。 (我赞同 Alex Martelli 所说的这种事情是一个巨大的黑客)

    【讨论】:

    • 好的。谢谢。我会等待更多的时间让其他人加入。如果有人有什么技巧。否则 - 我必须做我该做的!
    • K.我们现在将手动将 import foo 添加到这些 py 文件中并稍后修复该工具。我有时讨厌python的这种“严格性”,但随着时间的推移,我明白了——这通常是“正确的方式”。谢谢。
    【解决方案2】:

    你必须在 boo 中导入 foo

    boo.py

    import foo
    
    def boo():
      foo.foo()    # <-- global name 'foo' not defined
      print "boo"
    

    bar.py

    import boo
    
    def bar():
      boo.boo()
      print "bar"
    

    【讨论】:

    • 循环导入表示设计错误。
    • 当代码耦合太紧时,解决问题会很痛苦……重构是唯一的解决方案;)这就是我喜欢 python 的原因:)
    • @drevicko,谢谢,我一定是在 6 年前误读了这个帖子。要么,要么只是我的题外话,这也是可信的......;)
    【解决方案3】:

    每个模块都有自己的命名空间。所以为了让 boo.py 从外部模块中看到某些东西,boo.py 必须自己导入它。

    可以编写一种语言,其中命名空间按照您期望的方式堆叠:这称为动态范围。一些语言,如原始 lisp、早期版本的 perl、postscript 等确实使用(或支持)动态范围。

    大多数语言都使用词法作用域。事实证明,这是一种更好的语言工作方式:这样一个模块可以根据自己的代码推断它是如何工作的,而不必担心它是如何被调用的。

    有关更多详细信息,请参阅本文:http://en.wikipedia.org/wiki/Scope_%28programming%29

    【讨论】:

      【解决方案4】:

      但是 bar 正在同时导入 foo 和 boo。 foo 不应该是自动的 可以嘘吗?

      不应该:import 与任何其他绑定名称的方式一样,将该名称绑定在单个特定范围内,而不是“在您可能想要的所有范围内”。

      有没有办法做到这一点?如前所述 boo.py 是自动生成的 我和我想避免添加 import foo 到boo.py

      有一个非常糟糕的 hack —— 我不想忍受它(我宁愿把精力投入到让 boo.py 修复的完全损坏的代码生成器上——如果它有这么大的错误由于缺少一个关键的必要进口,它还有什么其他可怕的东西?!),但是,嘿,这不是我的葬礼......;-)

      bar.py开始...:

      import foo
      import boo
      import __builtin__
      __builtin__.foo = foo
      

      通过这种方式,您使标识符 foo 成为“虚假的、人为的内置名称”(可在每个范围内使用的唯一名称,除非被名字 在更近的范围内)指的是模块foo

      推荐的过程,只是构建boo.py的代码生成器中可怕的、明显的错误的临时解决方法。 修复这个错误,这样你就可以尽快退出这个 hack!

      【讨论】:

      • 好的。我会要求这些人手动将“import foo”添加到所有这些 py 文件中。我稍后会修复这个 .py 生成工具。谢谢。
      • @AlexMartelli 我遇到了这个 hack,就我的目的而言,它已经足够好了。但我仍然对将名称放入__builtin__ 的所有含义感到困惑。除了名称冲突的明显问题之外,还有其他一些值得注意的陷阱吗?
      【解决方案5】:

      你可以使用 importlib 模块 一旦一个模块被导入它就不能被重新导入, 尝试使用 import module_name import importlib

      importlib.reload(module_name)

      但是你需要先导入那个模块(module_name),然后还要导入lib。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-08-03
        • 2023-04-09
        • 2012-06-13
        • 2021-04-30
        • 2011-06-14
        • 2010-09-12
        • 2022-10-15
        相关资源
        最近更新 更多