Python 在导入_uinit__uuu.py中的所有内容时排除模块
问题 考虑以下布局:Python 在导入_uinit__uuu.py中的所有内容时排除模块,python,python-import,Python,Python Import,问题 考虑以下布局: package/ main.py math_helpers/ mymath.py __init__.py mymath.py包含: import math def foo(): pass from .mymath import * 在main.py中,我希望能够使用mymath.py中的代码,如下所示: import math_helpers math_helpers.foo() 为此,包含以下内容: imp
package/
main.py
math_helpers/
mymath.py
__init__.py
mymath.py
包含:
import math
def foo():
pass
from .mymath import *
在main.py
中,我希望能够使用mymath.py
中的代码,如下所示:
import math_helpers
math_helpers.foo()
为此,包含以下内容:
import math
def foo():
pass
from .mymath import *
但是,在mymath.py
中导入的模块现在位于math\u helpers
命名空间中,例如math\u helpers.math
可以访问
当前方法
我在mymath.py
的末尾添加了以下内容
import types
__all__ = [name for name, thing in globals().items()
if not (name.startswith('_') or isinstance(thing, types.ModuleType))]
这似乎是可行的,但这是正确的方法吗?一方面,有很多很好的理由不进行star导入,但另一方面,python适用于同意的成年人
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。您的方法是正确的,完成后可以进一步清理命名空间:
import types
__all__ = [name for name, thing in globals().items()
if not (name.startswith('_') or isinstance(thing, types.ModuleType))]
del types
虽然不太推荐,但您也可以直接从模块中清理元素,这样它们就不会出现。如果您需要在模块中定义的函数中使用它们,这将是一个问题,因为每个函数对象都有一个绑定到其父模块的\uuuu dict\uuu
引用。但是,如果只导入math\u helpers
以调用math\u helpers.foo()
,并且不需要在模块中的其他位置对其进行持久引用,则只需在末尾取消链接即可:
del math_helpers
长版本
模块导入在模块的\uuu dict\uuu
名称空间中运行模块的代码。在顶级绑定的任何名称,无论是通过类定义、函数定义、直接赋值还是其他方式,都存在于该词典中。有时,需要清理中间变量,正如我建议的那样,使用类型
假设您的模块如下所示:
测试模块.py
import math
import numpy as np
def x(n):
return math.sqrt(n)
class A(np.ndarray):
pass
import types
__all__ = [name for name, thing in globals().items()
if not (name.startswith('_') or isinstance(thing, types.ModuleType))]
value = 1
def x():
return value
from a import x
value = 2
在这种情况下,\uuuuuu all\uuuuuu
将是['x','A']
。但是,模块本身将包含以下名称:“数学”、“np”、“x”、“A”、“类型”、“全部”
如果最后运行deltypes
,它将从名称空间中删除该名称。显然,这是安全的,因为一旦构建了\uuuuu all\uuuuu
,就不会在任何地方引用类型
类似地,如果您想通过添加delnp
来删除np
,也可以。类A
完全由模块代码末尾构造,因此它不需要全局名称np
来引用其父类
数学方面则不然。如果要在模块代码末尾执行del math
,则函数x
将不起作用。如果导入模块,您可以看到x.\uuuu globals\uuuuuu
是模块的\uuuu dict\uuuuu
:
import test_module
test_module.__dict__ is test_module.x.__globals__
如果从模块字典中删除math
,并调用test\u module.x
,您将获得
NameError: name 'math' is not defined
因此,在某些非常特殊的情况下,您可能能够清理mymath.py
的名称空间,但这不是推荐的方法,因为它仅适用于某些情况
总之,坚持使用\uuuuu all\uuuuu
一个相关的故事
有一次,我有两个模块实现了类似的功能,但针对不同类型的最终用户。有几个函数我想从模块a
复制到模块b
。问题是,我希望函数能够像在模块b
中定义的那样工作。不幸的是,它们依赖于a
中定义的常量<代码>b
定义了它自己的常量版本。例如:
a.py
import math
import numpy as np
def x(n):
return math.sqrt(n)
class A(np.ndarray):
pass
import types
__all__ = [name for name, thing in globals().items()
if not (name.startswith('_') or isinstance(thing, types.ModuleType))]
value = 1
def x():
return value
from a import x
value = 2
b.py
import math
import numpy as np
def x(n):
return math.sqrt(n)
class A(np.ndarray):
pass
import types
__all__ = [name for name, thing in globals().items()
if not (name.startswith('_') or isinstance(thing, types.ModuleType))]
value = 1
def x():
return value
from a import x
value = 2
我想要b.x
访问b.value
而不是a.value
。我通过将以下内容添加到b.py
(基于):
我为什么要告诉你这些?好的,您可以创建一个在名称空间中没有任何散乱名称的模块版本。不过,您将无法在函数中看到全局变量的更改。这只是将python推到正常使用之外的一个练习。我强烈不建议这样做,但这里有一个示例模块,它可以有效地冻结其\uuuu dict\uuuu
函数。它的成员与上面的test_module
相同,但在全局命名空间中没有模块:
import math
import numpy as np
def x(n):
return math.sqrt(n)
class A(np.ndarray):
pass
import functools, types, sys
def wrap(obj):
""" Written this way to be able to handle classes """
for name in dir(obj):
if name.startswith('_'):
continue
thing = getattr(obj, name)
if isinstance(thing, FunctionType) and thing.__module__ == __name__:
setattr(obj, name,
functools.update_wrapper(types.FunctionType(thing.func_code, d, thing.__name__, thing.__defaults__, thing.__closure__), thing)
getattt(obj, name).__kwdefaults__ = thing.__kwdefaults__
elif isinstance(thing, type) and thing.__module__ == __name__:
wrap(thing)
d = globals().copy()
wrap(sys.modules[__name__])
del d, wrap, sys, math, np, functools, types
所以,是的,请永远不要这样做!但是如果你这样做了,就把它放在一个实用类的某个地方。是的,这正是它的用途。在定义了\uuuu all\uuu
之后,别忘了做删除类型。希望它能增加你已经发现的东西。我知道导入*
是不受欢迎的,因为这样你就看不出名字是从哪里来的,但是把所有东西都放到数学助手中有什么问题呢?2.del类型是什么?3.我不理解“因为每个函数对象都有一个绑定到其父模块的\uuuu dict\uu.
的\uuuu globals\uuuuuuuuuuuuuuuuuuuu>引用”部分-谢谢!当我到达一个新的位置时,我会更新一个插图desktop@actual_panda. 把所有东西都放在数学助手中没有什么错。你在问题中提出的解决方案肯定是推荐的。对不起,如果我在漫谈中不清楚的话。为了回答你的其他问题,我添加了比你想知道的更多的漫无边际的内容。