模块和包

本文参考:https://www.cnblogs.com/Eva-J/articles/7292109.html

一、模块
一、几种模块的使用方式
  1. import 模块名(推荐)
    使用时:模块名.函数
  2. import 模块名 as 新名字(推荐)
    使用时:新名字.函数
  3. from 模块名 import 函数名(只使用较少函数且函数名不容易混的时候用)
    导入模块中的特定函数,使用时不用再加模块名
  4. from 模块名 import *
    导入模块中的全部函数,使用时不用再加模块名
    如果在模块文件中加一行 : __all__ = [‘函数名1’,‘函数名2’ ]
    那么使用from 模块名 import *时只会导入 __all__ 列表中内容
二、一些细节
  1. 代码中多次导入同一模块,实际真正导入的次数只有1次
    在这里插入图片描述
import my_module
import my_module
import my_module
import my_module
import sys
print(sys.modules.keys())

# output:
in my_module!  # 实际上只导入了一次
# 最后导入了自定义模块 my_module
dict_keys(['builtins', 'sys', '_frozen_importlib', '_imp', '_warnings', '_thread', '_weakref', '_frozen_importlib_external', '_io', 'marshal', 'nt', 'winreg', 'zipimport', 'encodings', 'codecs', '_codecs', 'encodings.aliases', 'encodings.utf_8', '_signal', '__main__', 'encodings.latin_1', 'io', 'abc', '_weakrefset', 'site', 'os', 'errno', 'stat', '_stat', 'ntpath', 'genericpath', 'os.path', '_collections_abc', '_sitebuiltins', 'sysconfig', '_bootlocale', '_locale', 'encodings.gbk', '_codecs_cn', '_multibytecodec', 'types', 'functools', '_functools', 'collections', 'operator', '_operator', 'keyword', 'heapq', '_heapq', 'itertools', 'reprlib', '_collections', 'weakref', 'collections.abc', 'importlib', 'importlib._bootstrap', 'importlib._bootstrap_external', 'warnings', 'importlib.util', 'importlib.abc', 'importlib.machinery', 'contextlib', 'mpl_toolkits', 'google', 'sphinxcontrib', 'zope', 'sitecustomize', 'matplotlib', 'atexit', 'distutils', 'distutils.version', 're', 'enum', 'sre_compile', '_sre', 'sre_parse', 'sre_constants', 'copyreg', 'inspect', 'ast', '_ast', 'dis', 'opcode', '_opcode', 'linecache', 'tokenize', 'token', 'locale', 'logging', 'time', 'traceback', 'string', '_string', 'threading', 'pathlib', 'fnmatch', 'posixpath', 'urllib', 'urllib.parse', 'pprint', 'shutil', 'zlib', 'bz2', '_compression', '_bz2', 'lzma', '_lzma', 'subprocess', 'signal', 'msvcrt', '_winapi', 'tempfile', 'random', 'math', 'hashlib', '_hashlib', '_blake2', '_sha3', 'bisect', '_bisect', '_random', 'matplotlib.cbook', 'glob', 'gzip', 'struct', '_struct', 'numbers', 'numpy', '__future__', 'numpy._globals', 'numpy.__config__', 'numpy.version', 'numpy._distributor_init', 'ctypes', '_ctypes', 'ctypes._endian', 'numpy.core', 'numpy.core.info', 'numpy.core.multiarray', 'numpy.core.overrides', 'datetime', '_datetime', 'numpy.core._multiarray_umath', 'numpy.compat', 'numpy.compat._inspect', 'numpy.compat.py3k', 'numpy.core.umath', 'numpy.core.numerictypes', 'numpy.core._string_helpers', 'numpy.core._type_aliases', 'numpy.core._dtype', 'numpy.core.numeric', 'numpy.core._internal', 'platform', 'pickle', '_compat_pickle', '_pickle', 'numpy.core.fromnumeric', 'numpy.core._methods', 'numpy.core.arrayprint', 'numpy.core.defchararray', 'numpy.core.records', 'numpy.core.memmap', 'numpy.core.function_base', 'numpy.core.machar', 'numpy.core.getlimits', 'numpy.core.shape_base', 'numpy.core.einsumfunc', 'numpy.core._add_newdocs', 'numpy.core._multiarray_tests', 'numpy.core._dtype_ctypes', 'numpy._pytesttester', 'numpy.lib', 'numpy.lib.info', 'numpy.lib.type_check', 'numpy.lib.ufunclike', 'numpy.lib.index_tricks', 'numpy.matrixlib', 'numpy.matrixlib.defmatrix', 'numpy.linalg', 'numpy.linalg.info', 'numpy.linalg.linalg', 'numpy.lib.twodim_base', 'numpy.linalg.lapack_lite', 'numpy.linalg._umath_linalg', 'numpy.lib.function_base', 'numpy.lib.utils', 'numpy.lib.histograms', 'numpy.lib.stride_tricks', 'numpy.lib.mixins', 'numpy.lib.nanfunctions', 'numpy.lib.shape_base', 'numpy.lib.scimath', 'numpy.lib.polynomial', 'numpy.lib.arraysetops', 'numpy.lib.npyio', 'numpy.lib.format', 'numpy.lib._datasource', 'numpy.lib._iotools', 'numpy.lib.financial', 'decimal', '_decimal', 'numpy.lib.arrayterator', 'numpy.lib.arraypad', 'numpy.lib._version', 'numpy.fft', 'numpy.fft.info', 'numpy.fft.fftpack', 'numpy.fft.fftpack_lite', 'numpy.fft.helper', 'numpy.polynomial', 'numpy.polynomial.polynomial', 'numpy.polynomial.polyutils', 'numpy.polynomial._polybase', 'numpy.polynomial.chebyshev', 'numpy.polynomial.legendre', 'numpy.polynomial.hermite', 'numpy.polynomial.hermite_e', 'numpy.polynomial.laguerre', 'numpy.random', 'numpy.random.mtrand', 'cython_runtime', 'mtrand', 'numpy.ctypeslib', 'numpy.ma', 'numpy.ma.core', 'textwrap', 'numpy.ma.extras', 'numpy.testing', 'unittest', 'unittest.result', 'unittest.util', 'unittest.case', 'difflib', 'unittest.suite', 'unittest.loader', 'unittest.main', 'argparse', 'copy', 'gettext', 'unittest.runner', 'unittest.signals', 'numpy.testing._private', 'numpy.testing._private.utils', 'gc', 'numpy.testing._private.decorators', 'numpy.testing._private.nosetester', 'matplotlib.cbook.deprecation', 'matplotlib.rcsetup', 'matplotlib.fontconfig_pattern', 'pyparsing', 'matplotlib.colors', 'matplotlib._color_data', 'cycler', 'six', 'six.moves', 'matplotlib._version', 'json', 'json.decoder', 'json.scanner', '_json', 'json.encoder', 'matplotlib.ft2font', 'dateutil', 'dateutil._version', 'kiwisolver', 'socket', '_socket', 'selectors', 'select', 'my_module'])

原因:sys.modules中包含当前已经加载的模块,sys.modules是一个字典,内部包含模块名与模块对象的映射,该字典决定了导入模块时是否需要重新导入。如果python发现某一模块已经被导入了,就不会再次导入同一模块。

  1. 在一行导入多个模块在一行导入同一模块的多个函数(不推荐使用)
import sys, os, my_module
from sys import argv,exit
  1. 推荐的模块导入方式与顺序
    在程序的开头用import导入,每行导入一个模块
    导入顺序
    1.内置模块
    2.扩展模块(需要使用pip另外安装的模块)
    3.自定义模块
import sys
import time

import numpy as np
import tensorflow as tf

import my_module
  1. __name__==’__main__'
    我们可以通过模块的全局变量__name__来查看模块名
    模块作为主程序运行时:__name__等于’__main__’
    当做模块导入时:__name__等于模块名
    作用:用来控制.py文件在不同的应用场景下执行不同的逻辑
    if __name__==’__main__’:
    在这里插入图片描述
  2. dir()函数
    dir()函数是用来查找模块中定义的名字,返回一个有序字符串列表
import my_module
dir(my_module)

如果没有参数,dir()列举出当前定义的名字
dir()不会列举出内建函数或者变量的名字,它们都被定义到了标准模块builtin中,可以列举出它们

import builtins
dir(builtins)
  1. 模块的搜索路径
    模块查找的顺序是:内存中已经加载的模块 - > 内置模块 -> sys.path路径中包含的模块
    sys.path的初始化的值来自于:

The directory containing the input script (or the current directory when no file is specified).
PYTHONPATH (a list of directory names, with the same syntax as the shell variable PATH).
The installation-dependent default.

需要特别注意的是:我们自定义的模块名不应该与系统内置模块重名。虽然每次都说,但是仍然会有人不停的犯错

在初始化后,python程序可以修改sys.path,路径放到前面的优先于标准库被加载。

import sys
sys.path.append('/a/b/c/d')
sys.path.insert(0,'/x/y/z') #排在前的目录,优先被搜索

注意:搜索时按照sys.path中从左到右的顺序查找,位于前的优先被查找,sys.path中还可能包含.zip归档文件和.egg文件,python会把.zip归档文件当成一个目录去处理。

#首先制作归档文件:zip module.zip foo.py bar.py

import sys
sys.path.append('module.zip')
import foo,bar

#也可以使用zip中目录结构的具体位置
sys.path.append('module.zip/lib/python')

#windows下的路径不加r开头,会语法错误
sys.path.insert(0,r'C:\Users\Administrator\PycharmProjects\a')

至于.egg文件是由setuptools创建的包,这是按照第三方python库和扩展时使用的一种常见格式,.egg文件实际上只是添加了额外元数据(如版本号,依赖项等)的.zip文件。

需要强调的一点是:只能从.zip文件中导入.py,.pyc等文件。使用C编写的共享库和扩展块无法直接从.zip文件中加载(此时setuptools等打包系统有时能提供一种规避方法),且从.zip中加载文件不会创建.pyc或者.pyo文件,因此一定要事先创建他们,来避免加载模块是性能下降。

#官网链接:https://docs.python.org/3/tutorial/modules.html#the-module-search-path
搜索路径:
当一个命名为my_module的模块被导入时
解释器首先会从内建模块中寻找该名字
找不到,则去sys.path中找该名字

sys.path从以下位置初始化
执行文件所在的当前目录
PTYHONPATH(包含一系列目录名,与shell变量PATH语法一样)
依赖安装时默认指定的

注意:在支持软连接的文件系统中,执行脚本所在的目录是在软连接之后被计算的,换句话说,包含软连接的目录不会被添加到模块的搜索路径中

在初始化后,我们也可以在python程序中修改sys.path,执行文件所在的路径默认是sys.path的第一个目录,在所有标准库路径的前面。这意味着,当前目录是优先于标准库目录的,需要强调的是:我们自定义的模块名不要跟python标准库的模块名重复,除非你是故意的,傻叉。

二、包

包是一种通过“.模块名”来组织python模块名称空间的方式。

  1. 无论是import形式还是from…import形式,凡是在导入语句中(而不是在使用时)遇到带点的,都要第一时间提高警觉:这是关于包才有的导入语法
  2. 包是目录级的(文件夹级),文件夹是用来组成py文件(包的本质就是一个包含__init__.py文件的目录)
  3. import导入文件时,产生名称空间中的名字来源于文件,import 包,产生的名称空间的名字同样来源于文件,即包下的__init__.py,导入包本质就是在导入该文件(非常重要!!)

强调
4. 在python3中,即使包下没有__init__.py文件,import 包仍然不会报错,而在python2中,包下一定要有该文件,否则import 包报错

注意事项
  1. 关于包的导入也有 import 和 from … import …两种,无论是哪种,无论在什么位置,在导入时都必须遵循一个原则:凡是在导入时带点的,点的左边都必须是一个包, 否则非法。可以带一连串的点,但都必须遵循这个原则。
  2. 对于导入后,在使用时就没有这种限制了,点的左边可以是包,模块,函数,类(它们都可以用点的方式调用自己的属性)。
  3. from … import … 这里from后面导入的模块,必须是一个不带点的,否则会有语法错误,如:from a import b.c是错误的语法。
  4. 不管是哪种方式,只要是第一次导入包或者是包的任何其他部分,都会依次执行包下的__init__.py文件,这个文件可以为空,但是也可以存放一些初始化包的代码
  5. 特别需要注意的是:可以用import导入内置或者第三方模块(已经在sys.path中),但是要绝对避免使用import来导入自定义包的子模块(没有在sys.path中),应该使用from… import …的绝对或者相对导入,且包的相对导入只能用from的形式。
绝对导入和相对导入
  1. 绝对导入
  2. 相对导入
单独导入包
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值