Python 模块化

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

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

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

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

 
 
 
 

猜你喜欢

转载自www.cnblogs.com/xpc51/p/11916876.html