python - 使用 *(星号)导入与作为 python 中的命名空间导入

标签 python namespaces

我知道在 python 中使用 import * 是一种不好的形式,而且我不打算养成它的习惯。然而,我最近遇到了一些我不理解的奇怪行为,想知道是否有人可以向我解释一下。

假设我有三个 python 脚本。第一个 first_script.py 包含:

MESSAGE = 'this is from the first script'

def print_message():
    print MESSAGE

if __name__ == '__main__':
    print_message()

显然运行这个脚本会给我MESSAGE 的内容。我有第二个脚本,名为 second_script.py,包括:

import first_script

first_script.MESSAGE = 'this is from the second script'

if __name__ == '__main__':
    first_script.print_message()

这种行为(打印这是来自第二个脚本)对我来说很有意义。我已导入 first_script.py,但覆盖了其命名空间内的变量,因此当我调用 print_message() 时,我得到了该变量的新内容。

但是,我还有third_script.py,包括:

from first_script import *

MESSAGE = 'this is from the third script'

if __name__ == '__main__':
    print MESSAGE
    print_message()

产生的第一行是可以理解的,但第二行对我来说没有意义。我的直觉是,因为我已经通过第一行中的 * 导入到我的主命名空间中,所以我有一个全局变量 称为MESSAGES。然后在第二行中我覆盖 MESSAGES。那么为什么该函数(从第一个脚本导入)会产生 OLD 输出,特别是考虑到 Second_script.py 的输出。有什么想法吗?

最佳答案

import modulefrom module import smthfrom module import * 可以有不同的用例。

更简单:

import tools

加载tools模块并在本地命名空间(也称为tools)中添加对其的引用。之后,您可以通过在工具引用前面添加 tools 来访问任何工具引用,例如 tools.var1

变体:

import tools as sloot

完全相同,但您使用别名来访问模块中的引用(例如:sloot.var1)。它主要用于具有众所周知的别名的模块,例如 import numpy as np

另一种方式

from tools import foo

直接从当前命名空间的tools模块导入一些符号。这意味着您只能使用指定的符号,而无需对其进行限定。一个很好的用例是,您可以从具有相同功能的不同模块导入符号。例如

try:
    from mod1 import foo
except ImportError:
    from mod2 import foo

...
foo()      # actually calls foo from mod1 if available else foo from mod2

这通常用作可移植性技巧。

危险:

from tools import *

这是一个常见的习惯用法,但如果模块没有记录它,可能不会达到您的预期。事实上,它从模块导入所有公共(public)符号,默认情况下所有没有开头 _ 的符号可能包含不需要的东西。此外,模块可以声明一个特殊变量__all__,它被假定声明公共(public)接口(interface),在这种情况下,只有__all__中包含的符号才会被导入。

示例:

mod.py

__all__ = ['foo', 'bar']

def baz(x):
    return x * 2

def foo():
    return baz('FOO')

def bar():
    return baz('BAR')

您可以使用(假设 mod.py 可以访问)

from mod import *

print(foo())    # should print FOOFOO

# ERROR HERE
x = baz("test") # will choke with NameError: baz is not defined

同时

import mod

print(mod.baz("test"))     # will display as expected testtest

因此,如果 tools 模块的文档声明它是安全的并列出了实际导入的符号,则应该仅使用 from tools import *

关于python - 使用 *(星号)导入与作为 python 中的命名空间导入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26767300/

相关文章:

使用它的两个实例时出现 Python_textinput 问题

python - 使用 numpy 索引元组

python - Pandas:将行附加到列中具有多索引的DataFrame

python - 如何在不使用用户名、密码或 PAT token 的情况下对 azure devops api 进行身份验证

c++ - 正确使用枚举元素

python - "from __future__ import..."对最新版本的 Python 有影响吗?

c# - 在哪种情况下 c++/c# 命名空间方法比 Java 方法更好?

ruby-on-rails - Rails 方式 - 命名空间

php - 类与插件框架冲突 - PHP/Wordpress

objective-c - namespace 冲突真的是 Objective-C 中的一个问题吗?