python学习笔记(四)python中的模块

 

目录

(一)何为模块

(二)编写第一个模块

(三)import语句

(四)模块搜索路径

自建模块的存放位置

模块内部私有名称

(五)python的作用域的相关规则


 

主要内容

  • 定义模块
  • 编写第一个自己的模块
  • 使用import语句
  • 修改模块搜索路径
  • 让名称归模块私有
  • 导入标准库和第三方模块
  • 理解Python的作用域规则和命名空间

 

python语言如果没有众多的作为支撑的话,那python作为一门编程语言存在意义也不大了。正是多种多样的标准库和诸多第三方库的存在,才让python具有了强大的功能。

模块、包和库的作用基本都是相同的,都是为了实现代码的重复利用,提高代码效率。区别是从模块到包再到库,代码数量越多,实现的功能越强大。当然,也会有一些管理工具。这里先简单了解一下模块。

(一)何为模块

模块(module)用于组织较大的Python项目,Python标准库被拆分为多个模块,以便更易于管理。

模块是一个包含代码的文件,其中定义了一组Python函数或其他对象,而且模块的名称来自文件名。

模块通常包含Python源代码,但也可以是经过编译的C或C++对象文件。经过编译的模块和Python源代码模块的用法是一样的。

模块不仅可以将相互关联的Python对象归并成组,还有助于避免命名冲突(name-clash)问题。因为Python采用了命名空间(namespace)的机制,所以使用模块名可以同时保留两个reverse函数。命名空间本质上就是标识符的字典,可用于代码块、函数、类、模块等。

 

(二)编写第一个模块

我们将通过编写一个简单的模块来了解模块。

首先新建一个mymath.py文件,注意将文件保存在可执行文件所在的目录中。我的文件目录是D:\python37,通过下面的IDLE编辑器窗口也可以看到。

选择File>New Windows菜单,输入以下代码:

python学习笔记(四)python中的模块_第1张图片

以上我们便简单定义了一个模块,这个模块只是定义了pi常数和新建一个函数。

下面我们需要在我们的代码中使用这个模块,需要注意的是,使用前一定要导入模块,如果未进行import语句导入,Python解释器会进行报错:

>>> pi
Traceback (most recent call last):
  File "", line 1, in 
    pi
NameError: name 'pi' is not defined
>>> area(3)
Traceback (most recent call last):
  File "", line 1, in 
    area(3)
NameError: name 'area' is not defined

也就是说,Python没有内置常量pi和函数area。我们将模块导入之后:

>>> import mymath
>>> pi
Traceback (most recent call last):
  File "", line 1, in 
    pi
NameError: name 'pi' is not defined
>>> area(3)
Traceback (most recent call last):
  File "", line 1, in 
    area(3)
NameError: name 'area' is not defined

结果Python解释器也报错了,这是因为Python解释器不知到变量pi和area函数在哪个模块里面,有可能其他的模块也有相同命名的函数和常量,为了解决这个问题,我们需要在常量和函数之前,加上模块名称。这种访问方式常常被称为限定名称(qualification),即变量pi是受mymath模块限定的。也可以将pi成为mymath的属性。代码如下:

>>> mymath.pi
3.14
>>> mymath.area(3)
28.259999999999998

模块中的对象可以直接访问同一模块内定义的其他对象,不需要带上模块名称。函数mymath.area访问常量mymath.pi时,只需要用pi即可。

还可以要求从模块中导入指定的对象名称,这样在使用时就不需要带上模块名称了。例如:

>>> from mymath import pi
>>> pi
3.14

模块不仅是在交互式Python shell中需要用到。模块还可以被导入脚本文件,或者其他模块中,只要在代码文件的开头输入合适的import语句即可。从本事上来说,对于Python,交互式会话和脚本也被认为是模块。总结如下:

  • 模块是定义Python对象的文件。
  • 假定模块文件的名称是modulename.py,那么模块的Python名称就是modulename。
  • 通过import modulename语句,即可导入名为modulename的模块。该导入语句执行完毕后,模块modulename中定义的对象就能以modulename.objectname的格式被访问了。
  • 通过from modulename import objectname语句,可以将模块中的指定对象名称直接导入代码。该语句使得代码无需带modulename前缀即可直接访问objectname,这在导入某个频繁使用的对象名称时会很有用。

可以通过dir()函数查看模块的方法:

>>> import os
>>> dir(os)
['DirEntry', 'F_OK', 'MutableMapping', 'O_APPEND', 'O_BINARY', 'O_CREAT', 'O_EXCL', 'O_NOINHERIT', 'O_RANDOM', 'O_RDONLY', 'O_RDWR', 'O_SEQUENTIAL', 'O_SHORT_LIVED', 'O_TEMPORARY', 'O_TEXT', 'O_TRUNC', 'O_WRONLY', 'P_DETACH', 'P_NOWAIT', 'P_NOWAITO', 'P_OVERLAY', 'P_WAIT', 'PathLike', 'R_OK', 'SEEK_CUR', 'SEEK_END', 'SEEK_SET', 'TMP_MAX', 'W_OK', 'X_OK', '_Environ', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_execvpe', '_exists', '_exit', '_fspath', '_get_exports_list', '_putenv', '_unsetenv', '_wrap_close', 'abc', 'abort', 'access', 'altsep', 'chdir', 'chmod', 'close', 'closerange', 'cpu_count', 'curdir', 'defpath', 'device_encoding', 'devnull', 'dup', 'dup2', 'environ', 'error', 'execl', 'execle', 'execlp', 'execlpe', 'execv', 'execve', 'execvp', 'execvpe', 'extsep', 'fdopen', 'fsdecode', 'fsencode', 'fspath', 'fstat', 'fsync', 'ftruncate', 'get_exec_path', 'get_handle_inheritable', 'get_inheritable', 'get_terminal_size', 'getcwd', 'getcwdb', 'getenv', 'getlogin', 'getpid', 'getppid', 'isatty', 'kill', 'linesep', 'link', 'listdir', 'lseek', 'lstat', 'makedirs', 'mkdir', 'name', 'open', 'pardir', 'path', 'pathsep', 'pipe', 'popen', 'putenv', 'read', 'readlink', 'remove', 'removedirs', 'rename', 'renames', 'replace', 'rmdir', 'scandir', 'sep', 'set_handle_inheritable', 'set_inheritable', 'spawnl', 'spawnle', 'spawnv', 'spawnve', 'st', 'startfile', 'stat', 'stat_result', 'statvfs_result', 'strerror', 'supports_bytes_environ', 'supports_dir_fd', 'supports_effective_ids', 'supports_fd', 'supports_follow_symlinks', 'symlink', 'sys', 'system', 'terminal_size', 'times', 'times_result', 'truncate', 'umask', 'uname_result', 'unlink', 'urandom', 'utime', 'waitpid', 'walk', 'write']

(三)import语句

import语句有3种格式,最基本的格式就是:

# 第一种,最基本的格式
import modulename

这时会搜索给定名称的Python模块,解析模块内容并使之进入可用状态。发起导入的代码可以使用模块中的内容,但是引用模块中的对象名称时仍必须带有模块名前缀。如果未找到指定名称的模块,就会报错。

第二种:

# 第二种,允许指定模块中的名称,将其显式的导入代码中
from modulename import name1, name2, name3, ...

这些name1、name2等modulename中的对象名称,就可供发起导入的代码使用了。在import语句之后的代码,可以直接使用name1、name2等名称,不需要再带上模块名前缀了。

 

# 第三种
from modulename import *

“ * ”代表模块modulename中所有导出(exported)的对象名称。

 

(四)模块搜索路径

Python搜索模块的确切路径是在一个名为path的变量中定义的,可以通过模块sys访问path变量。

>>> import sys
>>> sys.path
['', 'D:\\python37\\Lib\\idlelib', 'D:\\python37\\python37.zip', 'D:\\python37\\DLLs', 'D:\\python37\\lib', 'D:\\python37', 'C:\\Users\\name\\AppData\\Roaming\\Python\\Python37\\site-packages', 'D:\\python37\\lib\\site-packages']

显示的位置取决于当前的系统配置。不管具体内容是什么,该字符串给出的是一个目录列表。当准备执行import语句时,Python将按顺序遍历该目录列表,并采用第一个满足import需求的模块。如果搜索路径中找不到合适的模块,则会引发ImportError异常。

自建模块的存放位置

为确保程序可以使用自己编写的模块,有以下三种方式:

  • 将自己的模块放入Python的常规模块搜索路径中去;
  • 将Python程序要用到的全部模块,都和程序放在同一目录中;
  • 新建目录用于保存自己的模块,并修改sys.path变量,使之包含该新建目录。

 

模块内部私有名称

模块中下划线开头的标识符不能用from module import *导入,所以将所有内部对象名称(即不允许模块外部访问的名称)都以下划线开头,既可以保证from module import *只引入用户需要访问的名称。

但是,也可以通过from module import _g语句,只导入_g变量,后面的代码就可以访问_g变量。

 

(五)python的作用域的相关规则

 

这里的核心概念是命名空间(namespace)。Python中的命名空间是从标识符到对象的映射,也就是Python如何跟踪变量和标识符是否活动以及指向什么。

如果刚刚接触Python,可以先不去了解这些。

Python 的名字查找规则是按照 local -> enclosing functions -> global -> built-in 的顺序由内而外查找,并选择最近的一个。

关于作用域规则,这里要先有一个概念,后续的学习中我们再逐步理解它。

 

 

参考:

  1. https://www.jianshu.com/p/276578774069

你可能感兴趣的:(python学习笔记)