我见过使用的一种技术,包括在标准库中,是使用import module as _module或from module import var as _var,即将导入的模块/变量分配给以下划线开头的名称。
其结果是,其他代码遵循通常的Python约定,将这些成员视为私有成员。这甚至适用于不查看__all__的代码,例如IPython的autocomplete函数。
来自Python 3.3的random模块的示例:from warnings import warn as _warn
from types import MethodType as _MethodType, BuiltinMethodType as _BuiltinMethodType
from math import log as _log, exp as _exp, pi as _pi, e as _e, ceil as _ceil
from math import sqrt as _sqrt, acos as _acos, cos as _cos, sin as _sin
from os import urandom as _urandom
from collections.abc import Set as _Set, Sequence as _Sequence
from hashlib import sha512 as _sha512
另一种技术是在函数范围内执行导入,以便它们成为局部变量:"""Some module"""
# imports conventionally go here
def some_function(arg):
"Do something with arg."
import re # Regular expressions solve everything
...
这样做的主要原因是它实际上是懒惰的,延迟了模块依赖项的导入,直到它们被实际使用。假设模块中的一个函数依赖于一个特定的大型库。导入文件顶部的库意味着导入模块将加载整个库。这样,导入模块就可以很快,而且只有真正调用该函数的客户机代码才会产生加载库的成本。此外,如果依赖关系库不可用,则不需要依赖特性的客户端代码仍然可以导入模块并调用其他函数。缺点是使用函数级导入会模糊代码的依赖关系。
来自Python 3.3的示例os.py:def get_exec_path(env=None):
"""[...]"""
# Use a local import instead of a global import to limit the number of
# modules loaded at startup: the os module is always loaded at startup by
# Python. It may also avoid a bootstrap issue.
import warnings