首页 > 编程语言 > 详细

Python 模块化

时间:2019-12-09 13:36:36      阅读:90      评论:0      收藏:0      [点我收藏+]

一般来说,编程语言中,库、包、模块是同一种概念,是代码的组织方式。

Python中只有一种模块对象,但是为了模块化组织模块的便利,提供了一个概念——包!

模块(module):指的是Python的源代码文件。

包(package):是的是模块组织在一起的包名同名的目录及其相关文件。

导入语句

import 模块1,模块2:这是完全导入(导入不建议用逗号分隔写成一行,可以多个导入)

import……as……:模块别名

import语句

  1. 知道指定的模块,加载和初始化它,生成模块对象,找不到,抛出ImportError异常。
  2. 在import所在的作用域的局部命名空间中(比如在py文件和函数内导入的作用域就不同),增加名称和上一步创建的对象关联。

单独运行下面的例子,体会其区别

import functools
print(dir())
print(functools)
print(functools.wraps)#import的本质是找到它,单独加载它,初始化它,生成一个模块对象,在当前模块中增加名称。映射到模块对象中。

结果为:
[In, Out, _, __, ___, __builtin__, __builtins__, __doc__, __loader__, __name__, __package__, __spec__, _dh, _i, _i1, _i2, _i3, _i4, _ih, _ii, _iii, _oh, exit, functools, get_ipython, quit]
<module functools from f:\\Anaconda3\\lib\\functools.py>
<function wraps at 0x01C41E40>
可以看到模块加载到了当前文件中,加入了它的名称, 它的名称属于当前模块中了。
import os.path#导入os.path,os加入当前名词空间,而不是os.path,这样写还不如写import os
print(dir())
print(os)
print(os.path)#完成限定名词访问path

结果为:
[In, Out, _, __, ___, __builtin__, __builtins__, __doc__, __loader__, __name__, __package__, __spec__, _dh, _i, _i1, _i2, _i3, _i4, _i5, _ih, _ii, _iii, _oh, exit, functools, get_ipython, os, quit]
<module os from f:\\Anaconda3\\lib\\os.py>
<module ntpath from f:\\Anaconda3\\lib\\ntpath.py>
import os.path as osp#导入os.path并赋值给osp
print(dir())
print(osp)

结果为:
[In, Out, _, __, ___, __builtin__, __builtins__, __doc__, __loader__, __name__, __package__, __spec__, _dh, _i, _i1, _i2, _i3, _i4, _i5, _i6, _ih, _ii, _iii, _oh, exit, functools, get_ipython, os, osp, quit]
<module ntpath from f:\\Anaconda3\\lib\\ntpath.py>

总结:

导入顶级模块,其名称会加入到本地名词空间中,并绑定到其模块对象。

导入非顶级模块,只将其顶级模块名称加入到本地名词空间中,导入的模块必须使用完全限定名称来访问。

如果使用了as,as后的名称直接绑定到导入的模块对象,并将该名称加入到本地名词空间中。

from……import……部分导入

from……import……as……:别名

from pathlib import Path,PosixPath#在当前名词空间导入该模块指定的成员,两个类
print(dir())

结果为:
[In, Out, ‘Path‘, ‘PosixPath‘, _, __, ___, __builtin__, __builtins__, __doc__, __loader__, __name__, __package__, __spec__, _dh, _i, _i1, _ih, _ii, _iii, _oh, exit, get_ipython, quit]
from pathlib import * #在当前名词空间导入该模块所有公共成员(非下划线开头成员)或指定成员,不建议这样导入
print(dir())

结果为:
[In, Out, ‘Path‘, ‘PosixPath‘, ‘PurePath‘, ‘PurePosixPath‘, ‘PureWindowsPath‘, ‘WindowsPath‘, _, __, ___, __builtin__, __builtins__, __doc__, __loader__, __name__, __package__, __spec__, _dh, _i, _i1, _i2, _ih, _ii, _iii, _oh, exit, get_ipython, quit]
from functools import wraps as wr,partial #别名
print(dir())

结果为:
[In, Out, _, __, ___, __builtin__, __builtins__, __doc__, __loader__, __name__, __package__, __spec__, _dh, _i, _i1, _ih, _ii, _iii, _oh, exit, get_ipython, ‘partial‘, quit, ‘wr‘]
from os.path import exists#加载,初始化os,os.path模块,exists加入到本地名词空间并绑定

if exists("f:/xpc"):
    print("found")
else:
    print("not found")
    
print(dir())
print(exists)

import os #如果不导入后面就会报错

#下面四种方式获得同一个对象
print(os.path.exists) print(exists) print(os.path.__dict__["exists"]) print(getattr(os.path,"exists")) 结果为: found [In, Out, _, __, ___, __builtin__, __builtins__, __doc__, __loader__, __name__, __package__, __spec__, _dh, _i, _i1, _i2, _ih, _ii, _iii, _oh, exists, exit, get_ipython, quit] <function exists at 0x01393738> <function exists at 0x01393738> <function exists at 0x01393738> <function exists at 0x01393738> <function exists at 0x01393738>

总结:

找到from子句中指定的模块,加载并初始化它(注意不是导入)

对于import子句后的名称

  • 先查from子句导入的模块是否具有该名称的属性
  • 如果不是,则尝试导入该名称的子模块
  • 还没有找到,则抛出ImportError异常
  • 这个名称保存到本地名词空间中,如果有as子句,则使用as子句后的名称。
from pathlib import Path #导入类path
print(Path,id(Path))

import pathlib as p1#导入模块使用别名

print(dir())
print(p1)
print(p1.Path,id(p1.Path))#可以看出导入的名词path和p1.path是统一对象

结果为:
<class pathlib.Path> 25771056
[In, Out, Path, _, __, ___, __builtin__, __builtins__, __doc__, __loader__, __name__, __package__, __spec__, _dh, _i, _i1, _ih, _ii, _iii, _oh, exit, get_ipython, p1, quit]
<module pathlib from f:\\Anaconda3\\lib\\pathlib.py>
<class pathlib.Path> 25771056

自定义模块

自定义模块,.py文件就是一个模块。

#tst1.py文件
print("this is test1 module")


class A:
def showmodule(self):
print("{}.a = {}".format(self.__module__, self))
print(self.__class__.__name__)


a = A()
a.showmodule()
结果为: 

this is test1 module
__main__.a = <__main__.A object at 0x00000000026C5B48>
A

 
#test2.py文件
print("this is test2 module")

import test1
print(dir)

b = test1.A()
b.showmodule()

结果为:

this is test2 module
this is test1 module
test1.a = <test1.A object at 0x0000000001E95C88>
A
<built-in function dir>
test1.a = <test1.A object at 0x000000000058F308>
A

#test3
from test1 import A as cls

a = cls()
a.showmodule()

结果为:
this is test1 module
test1.a = <test1.A object at 0x00000000026B5D08>
A
test1.a = <test1.A object at 0x0000000001DF0188>
A

上面三个文件都在同一个目录下。可以看到各个模块都是独立运行的。

自定义模块命名规范

  1. 模块名就是文件名
  2. 模块名必须符合标识符的要求,是非数字开头的字母数字和下划线的组合,像test-module.py这样的文件名不能作为模块名。
  3. 不要使用系统模块名来避免冲突,除非你明确知道这个模块名的用途
  4. 通常模块名为全小写,下划线来分割。

模块搜索顺序

使用sys.path查看搜索顺序

import sys

for p in sys.path:
    print(p)

结果为:
F:\xpc
f:\Anaconda3\python37.zip
f:\Anaconda3\DLLs
f:\Anaconda3\lib
f:\Anaconda3

f:\Anaconda3\lib\site-packages
f:\Anaconda3\lib\site-packages\win32
f:\Anaconda3\lib\site-packages\win32\lib
f:\Anaconda3\lib\site-packages\Pythonwin
f:\Anaconda3\lib\site-packages\IPython\extensions
C:\Users\Administrator\.ipython

显示结果为,Python模块的路径搜索顺序

当加载一个模块的时候,需要从这些搜索路径中从前到后一次查找,并不搜索这些目录的子目录,搜索到模块就加载,搜索不到就抛异常。

路径可以为字典、zip文件、egg文件。

.egg文件,由setuptools库创建的包,第三方库常用的格式,添加了元数据(版本号、依赖项等)信息的zip文件。

路径顺序为:

程序主目录,程序运行的主程序脚本所在的目录。

Pythonpath目录,环境变量Pythonpath设置的目录也是搜索模块的路径。

标准库目录,Python自带的库模块所在目录。

sys.path可以被修改,追加新的目录。

模块的重复导入

print("this is test1 module")


class A:
    def showmodule(self):
        print("{}.a = {}".format(self.__module__, self))
        print(self.__class__.__name__)


a = A()
a.showmodule()

结果为:
this is test1 module
__main__.a = <__main__.A object at 0x0000000001E65B08>
A
import test1
print("local module")
import test1
import test1

结果为:
this is test1 module
test1.a = <test1.A object at 0x0000000001EB87C8>
A
local module

 

在上面的例子中导入几个test1。从运行的结果来看,不会产生重复导入的问题。

所有加载的模块都会记录在sys.modules中,sys.modules是存储已经加载过的所有模块的字典。

模块运行

__name__,每个模块都会定义一个__name__特殊变量来存储当前模块的名称,如果不指定,则默认源代码文件名,如果是包则有限定名。

import os.path
import sys

import test1

print("++++++++++++++++++++++++++++")
print(sys.modules["__main__"])
print(dir())

结果为:
++++++++++++++++++++++++++++
<module __main__ from C:/Users/Administrator/PycharmProjects/studytset/xpc1/test1.py>
[__builtins__, __cached__, __doc__, __file__, __loader__, __name__, __package__, __spec__, os, sys, test1]
++++++++++++++++++++++++++++
<module __main__ from C:/Users/Administrator/PycharmProjects/studytset/xpc1/test1.py>
[__annotations__, __builtins__, __cached__, __doc__, __file__, __loader__, __name__, __package__, __spec__, os, sys, test1]

 

解释器初始化的时候,会初始化sys.modules字典(保存已加载的模块),创建builtins(全局函数、常量)模块,__main__模块,sys模块,以及模块搜索路劲sys.path。

Python是脚本语言,任何一个脚本都可以直接执行,也可以作为模块被导入。

当从标准输入(命令行方式敲代码)、脚本(Python test.py)或交互式读取的时候,会将模块的__name__设置为__main__,模块的顶层代码就在__main__这个作用域中执行。顶层代码:模块中缩进最外层的代码。

如果import导入的,其__name__默认就是模块名。

#test1.py文件
import test2

结果为:

in import module

#test2.py文件
#判断模块是否以程序的方式运行
if __name__ =="__main__":
    print("in __mian__")#程序的方式运行的代码
else:
    print("in import module")#模块导入的方式运行的代码

结果为:
in __mian__

if __name__ == "__main__"用途

  1. 本模块的功能测试,对于非主模块,测试本模块内的函数,类。
  2. 避免主模块变更的副作用。顶层代码,没有封装,主模块使用时没有问题,但是,一旦有了新的主模块,老的主模块成了被导入模块,由于原来代码没有封装,一并执行了。

模块的属性

__file__:字符串,源文件路径

__cached__:字符串,编译后的字节码文件路径

__spec__:显示模块的规范。

__name__:模块名

__package__:当模块是包,同__name__;否则,可以设置为顶级模块的空字符串。

包是特殊的模块

Python模块支持目录吗?

实验

项目中新建一个目录m,使用下面的代码。

技术分享图片

 

import m
print(dir())
print(type(m))
print(m)

结果为:
[__annotations__, __builtins__, __cached__, __doc__, __file__, __loader__, __name__, __package__, __spec__, m]
<class module>
<module m (namespace)>

如果在m目录下再新建一个xpython文件,就可以导入。

技术分享图片

 

import m.x
print(dir())
print(type(m))
print(m.x)

结果为:

[‘__annotations__‘, ‘__builtins__‘, ‘__cached__‘, ‘__doc__‘, ‘__file__‘, ‘__loader__‘, ‘__name__‘, ‘__package__‘, ‘__spec__‘, ‘m‘]
<class ‘module‘>
<module ‘m.x‘ from ‘C:\\Users\\Administrator\\PycharmProjects\\studytset\\m\\x.py‘>

 

结果可以看到,可以导入目录,目录也是文件,所以可以导入,不过问题是,目录模块怎么写入代码?

为了解决这个问题,python要求在目录下建立一个特殊文件__init__.py,在其中写入代码。

技术分享图片

 

 在继续运行上面的test看看能不能打印出y.

技术分享图片

 

 

[__annotations__, __builtins__, __cached__, __doc__, __file__, __loader__, __name__, __package__, __spec__, m]
<class module>
<module m from C:\\Users\\Administrator\\PycharmProjects\\studytset\\m\\__init__.py>
123

结果可以看到,y打印出来了。

python中,目录可以 作为模块,这就是包,不过代码需要写在该目录下__init__.py中。

目录和packege区别就是package创建会默认创建一个__init__文件。

子模块

包目录下的py文件、子目录都是其子模块。注意的是__init__是包自己的,它不是子模块。

技术分享图片

 

 如上建立子模块目录和和文件,所有的py文件中就写一句话,print(__name__)

#注意查看模块的加载,当前名词空间
import m.m1.m2

print(dir())

import sys
print(sorted(filter(lambda x:x.startswith("m"),sys.modules.keys())))

删除__init__.py试一试,可以发现删除并不影响导入,但是这不是良好的习惯,请保留__init__.py文件。

 模块和包的总结

包能够更好地组织模块,尤其是大的模块代码行数很多,可以把它拆分成很多子模块,便于使用某些功能就加载相应的子模块。

包目录中__init__.py是在包第一次导入的时候就会执行,内容可以为空,也可以是用于该包初始化工作的代码,最好不要删除它(低版本不可删除)

导入子模块一定会加载父模块,但是导入父模块一定不会导入子模块。

包目录之间只能使用.号作为分隔符,表示模块及其子模块的层级关系。

模块也是封装,如同,类,函数,不过它能够封装变量,类,函数。

模块就是命名空间,其内部的顶层标识符,都是它的属性,可以通过__dict__或dir(module)查看。

包也是模块,但模块不一定是包,包是特殊的模块,是一种组织方式,它包含__path__属性。

问题

from json import encoder 之后,json.dump函数用不了,为什么?

import json.encoder之后呢?json.dump函数能用吗?

原因是from json import encoder之后,当前名次空间没有json,但是json模块已经加载过了,没有json的引用,无法使用dump函数。

import json.encoder也加载json模块,但是当前名词空间有json,因此可以调用。

绝对导入,相对导入

绝对导入

在import语句或者from导入模块,模块名称最前面不是以点开头的。

绝对导入总是去搜索模块搜索路径中找。

相对导入

只能在包内使用,且只能用在from语句中。

使用.点号,表示当前目录内。

..表示上一级目录

不要在顶层模块中使用相对导入。

举例a.b.c模块,c是模块,c的代码总,使用

from . import d #imports a.b.d

from .. import e #import a.e

from .d import x #a.b.d.x

form ..e import x #a.e.x

...三点表示上上一级。

使用下面结构的包,体会相对导入的使用。

技术分享图片

 

 测试一下有相对导入语句的模块,能够直接运行吗?

不能,很好理解,使用相对导入的模块就是为了内部互相的引用资源的,不是为了直接运行的,对于包来说,正确的使用方式还是在顶级模块中使用这些包。

访问控制

下划线开头的模块名

_或__开头的模块是否能够被导入呢?

创建文件名为_xyz.py或__xyz.py测试。

都可以成功的导入,因为它们都是合法标识符,就可以用作模块名。

应该注意使用*导入,下划线,双下导入导入是不会成功的。非要自己取也是可以导入的。

模块内的标识符

技术分享图片

 

 

#xyz.py
print(__name__)
A = 5
_B = 6
__C = 7

__my__ = 8

 

import xyz
import sys

print(sorted(sys.modules.keys()))
print(dir())

print(xyz.A,xyz._B,xyz.__C,xyz.__my__)

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

上面的例子可以看到,普通变量,保护变量,私有变量,特殊变量,都没有被隐藏,也就是说模块内没有私有的变量,在木块中定义不做特殊处理。

from语句

from xyz import A,_B as B,__C as C,__my__

import sys

print(sorted(sys.modules.keys()))
print(dir())

print(A,B,C,__my__)

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

依然可以使用form语句,访问所有变量。

from……import *和__all__

使用from……import *导入

from xyz import *

import sys

print(sorted(sys.modules.keys()))
print(dir())
print(locals()["A"])

A = 55

print(locals()["A"])

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

结果是仅仅导入了A,下划线开头的都没有导入。

使用__all__

__all__是一个列表,元素是字符串,每一个元素都是一个模块内的变量名。

#xyz.py
__all__ = ["X","Y"]

print(__name__)
A = 5
_B = 6
__C = 7

__my__ = 8

X = 10
Y = 20
#test.py
from xyz import *

import sys

print(sorted(sys.modules.keys()))
print(dir())
#print(locals()["A"])#KeyError: ‘A‘
print(locals()["X"])
print(locals()["Y"])

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

修改__all__列表,加入下划线开头变量,看看什么效果。

#xyz.py
__all__ = ["X","Y","__C","_B"]

print(__name__)
A = 5
_B = 6
__C = 7

__my__ = 8

X = 10
Y = 20
#test.py
from xyz import *

import sys

print(sorted(sys.modules.keys()))
print(dir())
#print(locals()["A"])#KeyError: ‘A‘
print(locals()["X"])
print(locals()["Y"])
print(locals()["_B"])
print(locals()["__C"])

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

可以看到,使用from xyz inport *导入__all__列表中的名称。

包和子模块

技术分享图片

 

技术分享图片

 

 

#__Init__.py

print(__name__)
X = 1


#M1.PY中

print(__name__)
y = 5

在test1中,如何访问m1.py中的变量

#方法1,直接导入m模块
import m.m1
print(m.m1.y)

结果为:
m
m.m1
5

#方法2,直接导入m.m1的属性y

from m.m1 import y
print(y)

结果为:
m
m.m1
5
#方法3,from m import *
#该方法导入后,无法看到子模m1,无法访问y
#在————init__。py增加__all__ = ["X","m1"],使用__all__提供导出的名称


from m import *
print(m1.y)

结果为:
现在还没有加__all__
m
Traceback (most recent call last):
  File "C:/Users/Administrator/PycharmProjects/studytset/xpc1/test1.py", line 7, in <module>
    print(m1.y)
NameError: name m1 is not defined
#__Init__.py
__all__ = ["X","m1"]#也可以写成元组
print(__name__)
X = 1

在__init__中,增加了结果就和上面一样了。
#__Init__.py
__all__ = ["X","m1"]
print(__name__)
X = 1


#方法4,不使用__all__
#在__init__.py增加from .import m1

from m import *
print(m1.y)

结果为:
m.m1
m
5

__init__.py中有什么变量,则使用from m import *加载什么变量,这依然符合模块的访问控制。

#__init__。py

print(__name__)
X = 1

from .m1 import y as _z
print(dir)

总结

一,使用from xyz import *导入

  1. 如果模块没有__all__,from xyz import *只导入非下划线开头的模块的变量,如果是包,子模块也不会导入,除非在__all__中设置,或__init__。py中使用相对导入。
  2. 如果模块有__all__,from xyz import *只导入__all__列表中指定的名称,哪怕这个名词是下划线开头的,或者是子模块。
  3. from xyz import *方式导入,使用简单,但是其副作用是导入大量不需要的变量,甚至有可能造成名称的冲突,而__all__可以控制被导入模块在这种导入方式下能够提供的变量名称,就是为了阻止from xyz import *导入过多的模块变量,从而避免冲突。因此,编写模块时,应该尽量加入__all__。

二、from module import name1,name2导入

这种方式的导入是明确的,哪怕是导入子模块,或者导入下划线开头的名称。

程序员可以有控制的导入名称和其对应的对象。

模块变量的修改

#xyz.py
print(__name__)

X = 10


#test1.py
import xyz

print(xyz.X)

#test2.py
import xyz

print(xyz.X)

xyz.X = 50

import test1

结果为:
xyz
10
50

模块对象是同一个,因此模块的变量也是同一个,对模块变量的修改,会影响所有使用者,除非万不得已,或明确知道自己在做什么,否则不要修改模块的变量。

前面学习的猴子补丁,也可以通过打补丁的方式,修改模块的变量,类,函数等内容。

 
 
 
 

Python 模块化

原文:https://www.cnblogs.com/xpc51/p/11916876.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!