Python3 模块
import 语法、模块查找路径、__name__ 属性、dir() 函数、标准模块与包。
import 语句
import module loads the whole module and you reach into it with module.name. This keeps namespaces explicit and avoids clashes; as gives a short alias.
import math
import random as rnd
print(math.sqrt(9))
print(math.pi)
print(rnd.randint(1, 3) in (1, 2, 3))
print(rnd.__name__)3.0
3.141592653589793
True
randomfrom … import 语句
from module import name pulls in just the names you need so you can use them unqualified. The trade-off is unclear provenance and possible clashes, so import sparingly.
from math import sqrt, pi
print(sqrt(16))
print(pi)
from collections import Counter
c = Counter('abracadabra')
print(c.most_common(2))4.0
3.141592653589793
[('a', 5), ('b', 2)]from … import * 语句
from module import * imports every public name. It makes the namespace unpredictable — you cannot tell what arrived or what it shadowed — so avoid it in production code.
ns = {}
exec('from math import *', ns)
names = sorted(k for k in ns if not k.startswith('__'))
print(len(names) > 20)
print('sqrt' in names, 'pi' in names)
print(names[:3])True
True True
['acos', 'acosh', 'asin']import * is only convenient for interactive exploration. If the module defines __all__, only the names listed there are imported.深入模块
A module is just a .py file whose name (minus extension) is the module name. Top-level code runs once on first import; later imports come from the sys.modules cache.
import sys
import json
print('json' in sys.modules)
print(json.__name__)
print(json.__file__.endswith('.py') or json.__file__.endswith('.pyc'))
print(len(sys.path) > 0)
print(type(sys.modules).__name__)True
json
True
True
dict__name__ 属性
Every module has __name__: the module name when imported, '__main__' when run as a script. That is exactly how if __name__ == '__main__': distinguishes the two cases.
print(__name__)
print(__name__ == '__main__')
import math
print(math.__name__)
print(math.__name__ == '__main__')
def main():
print('running as script')
if __name__ == '__main__':
main()__main__
True
math
False
running as scriptdir() 函数
dir(module) lists every name the module defines, sorted; with no argument it lists the current scope. It is the fastest way to explore an unfamiliar module.
import math
names = dir(math)
print(len(names) > 30)
print('sqrt' in names, 'pi' in names)
print([n for n in names if n.startswith('is')])
x = 1
print('x' in dir())True
True True
['isclose', 'isfinite', 'isinf', 'isnan', 'isqrt']
True标准模块
Python ships a standard library covering files, networking, text, dates and concurrency — importable with no install. Common ones: os, sys, json, re, datetime, collections, itertools, pathlib.
import os
import sys
import json
import re
import datetime
import collections
import itertools
import pathlib
mods = [os, sys, json, re, datetime, collections, itertools, pathlib]
for m in mods:
print(m.__name__, '->', m.__name__ in sys.modules)os -> True
sys -> True
json -> True
re -> True
datetime -> True
collections -> True
itertools -> True
pathlib -> True包
A package is a directory with an __init__.py, grouping related modules hierarchically. Importing pkg.mod first runs pkg/__init__.py, then loads the submodule.
# 目录结构:
# sound/
# __init__.py
# formats/
# __init__.py
# wavread.py
# wavwrite.py
import os
import tempfile
root = tempfile.mkdtemp()
pkg = os.path.join(root, 'sound')
os.makedirs(os.path.join(pkg, 'formats'))
for path in (pkg, os.path.join(pkg, 'formats')):
open(os.path.join(path, '__init__.py'), 'w').close()
print(sorted(os.listdir(pkg)))
print(os.path.exists(os.path.join(pkg, '__init__.py')))['__init__.py', 'formats']
True__init__.py be imported. Regular projects should still keep it for clarity and tooling compatibility.从一个包中导入 *
from pkg import * follows __all__ in the package's __init__.py: if defined, only the listed submodules come in; otherwise every already-loaded submodule does.
# sound/__init__.py 里写:
# __all__ = ["echo", "surround", "reverse"]
ns = {}
exec("__all__ = ['echo', 'surround', 'reverse']", ns)
print(ns['__all__'])
ns2 = {}
exec("from math import *", ns2)
print('sqrt' in ns2, 'log' in ns2)['echo', 'surround', 'reverse']
True Trueimport 语句
import 模块名 把整个模块加载进来,通过 模块名.名字 访问其内容。这样命名空间清晰,也避免与自己的变量重名。可以用 as 起别名。
import math
import random as rnd
print(math.sqrt(9))
print(math.pi)
print(rnd.randint(1, 3) in (1, 2, 3))
print(rnd.__name__)3.0
3.141592653589793
True
randomfrom … import 语句
from 模块 import 名字 只导入需要的名字,之后可以直接用,不必加模块前缀。缺点是来源不明确,容易与本地变量冲突,所以不宜一次导入太多。
from math import sqrt, pi
print(sqrt(16))
print(pi)
from collections import Counter
c = Counter('abracadabra')
print(c.most_common(2))4.0
3.141592653589793
[('a', 5), ('b', 2)]from … import * 语句
from 模块 import * 导入模块里所有不以下划线开头的名字。它会让命名空间变得不可控 —— 你不知道到底进来了什么,也不知道覆盖了谁,生产代码里应避免。
ns = {}
exec('from math import *', ns)
names = sorted(k for k in ns if not k.startswith('__'))
print(len(names) > 20)
print('sqrt' in names, 'pi' in names)
print(names[:3])True
True True
['acos', 'acosh', 'asin']import * 只在交互式探索时方便。若模块定义了 __all__,import * 只导入 __all__ 里列出的名字。深入模块
模块就是一个 .py 文件,文件名去掉 .py 就是模块名。模块内的顶层代码在第一次被导入时执行一次,之后从 sys.modules 缓存直接取用。
import sys
import json
print('json' in sys.modules)
print(json.__name__)
print(json.__file__.endswith('.py') or json.__file__.endswith('.pyc'))
print(len(sys.path) > 0)
print(type(sys.modules).__name__)True
json
True
True
dict__name__ 属性
每个模块都有 __name__:被别的代码导入时它等于模块名,被当作脚本直接运行时它等于 '__main__'。这就是 if __name__ == '__main__': 能区分两种场景的原理。
print(__name__)
print(__name__ == '__main__')
import math
print(math.__name__)
print(math.__name__ == '__main__')
def main():
print('running as script')
if __name__ == '__main__':
main()__main__
True
math
False
running as scriptdir() 函数
dir(模块) 返回该模块定义的所有名字(排序后的字符串列表);不带参数时返回当前作用域的名字。它是探索陌生模块最快的方式。
import math
names = dir(math)
print(len(names) > 30)
print('sqrt' in names, 'pi' in names)
print([n for n in names if n.startswith('is')])
x = 1
print('x' in dir())True
True True
['isclose', 'isfinite', 'isinf', 'isnan', 'isqrt']
True标准模块
Python 自带「标准库」,涵盖文件、网络、文本、日期、并发等常见需求,无需安装即可 import。常用的有 os、sys、json、re、datetime、collections、itertools、pathlib。
import os
import sys
import json
import re
import datetime
import collections
import itertools
import pathlib
mods = [os, sys, json, re, datetime, collections, itertools, pathlib]
for m in mods:
print(m.__name__, '->', m.__name__ in sys.modules)os -> True
sys -> True
json -> True
re -> True
datetime -> True
collections -> True
itertools -> True
pathlib -> True包
包是带 __init__.py 的目录,用来把一组相关模块组织成层级结构。导入 pkg.mod 时,Python 先执行 pkg/__init__.py,再加载子模块。
# 目录结构:
# sound/
# __init__.py
# formats/
# __init__.py
# wavread.py
# wavwrite.py
import os
import tempfile
root = tempfile.mkdtemp()
pkg = os.path.join(root, 'sound')
os.makedirs(os.path.join(pkg, 'formats'))
for path in (pkg, os.path.join(pkg, 'formats')):
open(os.path.join(path, '__init__.py'), 'w').close()
print(sorted(os.listdir(pkg)))
print(os.path.exists(os.path.join(pkg, '__init__.py')))['__init__.py', 'formats']
True__init__.py 的目录也能被导入。但常规项目仍建议保留 __init__.py,语义更清晰、工具兼容更好。从一个包中导入 *
from 包 import * 的行为由包的 __init__.py 里的 __all__ 决定:写了 __all__ 就只导入列出的子模块,没写则导入所有已加载的子模块。
# sound/__init__.py 里写:
# __all__ = ["echo", "surround", "reverse"]
ns = {}
exec("__all__ = ['echo', 'surround', 'reverse']", ns)
print(ns['__all__'])
ns2 = {}
exec("from math import *", ns2)
print('sqrt' in ns2, 'log' in ns2)['echo', 'surround', 'reverse']
True True