Python Tutorial——模块

news2025/1/21 18:46:45

如果你从Python解释器中退出,并且再次进入,你会发现你以前定义的函数和变量都已经丢失了。所以,如果你想写一个在某种程度上更长的程序,使用一个文本编辑器来准备解释器的输入会使情况有所好转,并且使用文件代替输入来执行它。这就是被熟知的创建一个脚本。随着你的程序变的更长时,你或许想把它分割成几个文件,这样便于维护。你或许想在几个程序里面使用一个常用的函数,而不用把它的定义拷贝到每一个程序里面。

为了支持这些,Python有一个方式来把定义放到一个文件里,并且在一个脚本里或解释器的一个交互实例中使用它们。这样的一个文件叫做模块,一个模块里面的定义可以被导入到其它模块里面或主模块里面(在顶级以计算器方式执行的脚本里面访问的变量集合)。

一个模块就是一个包含Python定义和语句的文件。文件名就是模块名加上后缀.py。在一个模块里面,模块的名字(一个字符串)可以使用全局变量__name__获得。例如,使用你喜爱的文本编辑器在当前的目录里面来创建一个fibo.py的文件,包含一些内容:

然后进入Python解释器,使用下面的命令导入这个模块:

这样做并没有把直接定义在fibo中的函数名称写入到当前符号表里,只是把模块fibo的名字写到了那里。

可以使用模块名称来访问函数:

如果你打算经常使用一个函数,你可以把它赋给一个本地的名称:

6.1 更多有关模块

模块可以包含可执行语句和函数定义。这些语句是打算用来初始化模块的。这些语句只有在模块第一次被导入到其它地方的时候会被执行。

每一个模块有它自己的私有符号表,它被定义在模块里的所有函数用作全局符号表。因此,一个模块的设计者可以在模块里使用全局变量而不用担心会和用户的全局变量产出意外的冲突。换句话来说,如果你知道你正在干什么,你可以触及模块里面的全局变量,使用和以前引用模块函数相同的标记法,modname.itemname。

模块可以引入其它模块。把所有的导入语句放到模块的开始是一种习惯,但不要求非得这样做。被导入模块的名称被放入到引入模块的全局符号表里。

有一个导入语句的变体可以把一个模块里的名称直接导入到另一个模块的符号表里面。例如:

这样不会引入模块的名称,这些导入的内容被放到本地符号表(所以在示例中,fibo没有定义)。

甚至由一个变体可以引入一个模块定义的所有名称:

这将引入所有除了以下划线开头的名称。大多数情况,Python程序员不使用这样的功能,因为它引入了一个不知道的名称集合到解释器里,可能会隐藏掉你已经定义的一些东西。

注意,一般来说,从一个模块或包里面引入所有的名称在实践中是不被赞成的,因为它经常造成可读性差的代码。然而,在交互式会话里可以使用它来节省输入。

注意,出于效率的原因,在一个会话里,每个模块只会被引入一次。如果你改变了你的模块,你必须重新启动解释器,或者如果你想交互测试的仅仅是一个模块,可以使用imp.reload(),例如:import imp; imp.reload(modulename)。

6.1.1 把模块作为脚本执行

当你以下面方式执行Python模块时:

模块里面的代码将会被执行,就好像你引入它一样,但是会把__name__设置为__main__。那就意味着把这些代码添加到模块的尾部:

你可以把文件当作脚本和可导入模块来使用,因为解析命令行的代码只有在模块作为主文件执行时才运行:

如果模块被导入,代码不执行:

这通常用来要么给模块提供一个方便的用户界面,或为了测试(把模块作为脚本运行,来执行一个测试单元)。

6.1.2 模块搜索路径

当一个名为spam的模块被导入时,解释器首先搜索具有这个名称的内建模块。如果没有找到,然后在sys.path这个变量指定的目录列表里面搜索一个名为spam.py的文件。sys.path从这些地方被初始化:

  • 包含输入脚本的目录(或当前目录)。
  • PYTHONPATH(一个目录名称的列表,和shell变量PATH的语法一样)。
  • 取决于安装时的默认值。

在初始化后,Python程序可以修改sys.path。包含正在运行的脚本的目录被放到了搜索路径的开始处,在标准库路径前面。这意味着那个目录里面的脚本会被加载而不是库目录里面的同名模块。这是一个错误除非替换被打算。

6.1.3 “编译”Python文件

作为一个对那些使用了许多标准模块的短的程序的启动时间的重要加速,如果在发现spam.py的目录里面已经存在一个叫spam.pyc的文件,这被假定包含模块spam的一个已按字节编译的版本。用来创建spam.pyc的spam.py的版本修改时间被记录在spam.pyc里面,并且.pyc文件会被忽略如果这两个时间不匹配。

通常,你不需要做任何事情来创建spam.pyc文件。无论什么时候spam.py文件被成功的编译,将会进行一次把编译好的版本写入到spam.pyc的尝试。如果这次尝试失败的话也不算是错误;如果由于任何原因这个文件没有被写完,结果spam.pyc文件被认为是非法的,并且在以后忽略它。spam.pyc文件的内容是平台独立的,所以一个Python模块目录可以被不同架构的机器共享。

一些对专家的提示:

  • 当Python的解释器以-O的标志被调用时,将产生优化的代码并存储在.pyo文件里面。优化器现在帮助不了太多;它仅仅移除assert语句。当-O使用时,所有的字节码都被优化;.pyc文件被忽略和.py文件被编译成优化的字节码。
  • 传递两个-O标志到Python的解释器(-OO)将使字节码编译器来执行优化,这种优化在一些特殊的情况下会导致程序出故障。当前只有文档字符串从字节码中被移除,产生更加压缩的.pyo文件。因为一些程序或许依赖使这些可用,你应该只有在你知道自己在做什么时再使用这个选项。
  • 一个程序从.pyc或.pyo文件读入并不比从.py文件读入运行的快很多;关于.pyc或.pyo文件惟一快的事情是它们被加载的速度。
  • 在命令行使用脚本名称运行脚本时,脚本的字节码从不写入.pyc或.pyo文件。因此,把一个脚本的大多数代码移到一个模块里面,产生一个较小的启动脚本并引入那个模块,可以减少一个脚本的启动时间。也可以在命令行直接命名一个.pyc或.pyo文件。
  • 在同一个模块里面有一个spam.pyc文件(或spam.pyo当-O使用时)而没有一个spam.py文件也是可能的。这可以用于以对逆向工程师有一定难度的形式来发布Python代码库。
  • compileall模块能为一个目录里面的所有模块创建.pyc文件(或.pyo文件当-O使用时)。

6.2 标准模块

Python有一个标准模块的库,在一个单独的文档中描述,Python库参考。一些模块被内建到解释器中;它们提供的访问操作不是语言的核心部分但是仍然被内建其中,要么是为了效率或提供访问操作系统原始的内容如系统调用。这些模块集是一个配置选项,它们也取决于底层的平台。例如,winreg模块只有Windows系统提供。一个特殊的模块应受到一些关注:sys,它被内建到每一个Python解释器中。变量sys.ps1和sys.ps2定义了用作主要和第二命令提示符的字符串:

这两个变量只定义在解释器处于交互模式时。

变量sys.path是一个字符串列表,决定了解释器的模块搜索路径。它使用环境变量PYTHONPATH的值进行初始化为一个默认的路径,或从一个内建默认值如果PYTHONPATH没有设置。你可以使用标准的列表操作修改它:

6.3 dir()函数

内建的函数dir()用来找出一个模块都定义了那些名称。它返回一个已排序的字符串列表:

没有参数的话,dir()列出当前你已经定义的名称:

注意,它列出所有类型的名称:变量,模块,函数等。

dir()并不列出内建的函数和变量的名称。如果你想列出那些名称,它们都定义在标准的模块buildins里面:

6.4 包

包是使用点模块名称来构建Python模块命名空间的一种方式。例如,模块名称A.B表明一个名称为B的子模块在一个名称为A的包里面。就像模块的使用使不同模块的作者不用再担心彼此的全局变量名称,点模块名称的使用使多模块包(像NumPy或Python镜像库)的作者不用再担心彼此的模块名称。

假定你想设计一些模块来统一的处理声音文件和声音数据。有许多不同格式的声音文件,所以或许你需要创建和维护一个持续增长的模块集合在多种不同格式的文件之间进行转换。或许也想在声音数据上执行多种不同的操作,所以除此之外你将写一个永远没有头的模块流来执行这些操作。这是一个可能的包结构:

当引入这个包,Python通过sys.path上的目录来搜索查找包子目录。

__init__.py文件是必须的,它使Python把这些目录作为包含包来对待;这样就阻止了稍后发生在模块搜索路径上的一个具有普通名称的目录无意中隐藏了合法模块。在最简单的情况下,__init__.py可能仅是一个空的文件,但是它也能为包执行初始化代码或设置__all__变量,稍后描述。

包的用户可以从包里面单个的导入模块,例如:

这加载子模块sound.effects.echo。必须使用全名来引用它:

一个导入子模块的可选方式是:

这也加载子模块echo,并且使它不带包前缀也可以使用,所以它能按如下方式使用:

另一种变体是用来直接导入期望的函数或变量:

加载子模块echo,并且使它的函数echofilter()直接可以使用:

注意,当使用from package import item时,item要么是包的子模块(或子包),或者是包里定义的一些其它名称,像函数,类或者变量。import语句首先测试item是否定义在包里;如果没有,就假定它是一个模块并且尝试去加载它。如果没有成功的找到它,一个ImportError异常被激发。

反之,当使用像import item.subitem.subsubitem这样的语法时,除了最后一项的其它项都必须是一个包;最后一项可以是一个模块或一个包,但不能是定义在前一项里面的一个类或函数或变量。

6.4.1 从一个包里导入*

当用户写下from sound.effects import *是会发生什么?理论上讲,一个人希望这以某种方式走出文件系统,找出哪些子模出现在块包里存,并且全部导入它们。这可能花费较长的时间,并且正在导入的子模块可能有不希望的副作用,这个副作用应该只有在这个子模块被显式导入时才发生。

唯一的解决方案就是包的作者提供一个显示的包的索引。import语句使用下面的约定:如果一个包的__init__.py代码定义了一个名为__all__的列表,它被认为是应该导入的模块名称的列表当遇到from package import *时。这取决于包的作者来保持这个列表是最新的当一个包的新的版本被发布时。包的作者们也可以决定不支持它,如果他们没有看到import * from他们的包的使用。例如,文件sounds/effects/__init__.py可能包含下面的代码:

这将意味着from sound.effects import *将导入sound包的三个命名的子模块。

如果__all__没有定义,语句from sound.effects import *并不从sound.effects包里导入所有的子模块到当前的命名空间里;它仅仅确认包sound.effects已经被导入(可能的运行__init__.py里面的任何初始化代码)并且导入包里定义的任何名称。这包含通过__init__.py定义的任何名称(和显式加载的子模块)。这也包括通过上一个import语句被显式加载的包的任何子模块。考虑下面的代码:

在这个例子里,当from...import语句被执行时,模块echo和surround被导入到当前的命名空间,因为它们定义在sound.effects包里。(当__all__被定义时这也起作用。)

当使用import *时,虽然遵从确定的模式,确定的模块被设计为只输出名称,在生产代码里它仍然被认为是坏的实践。

记住,使用from Package import specific_submodule没有错误。事实上,这是建议的写法,除非正在导入的模块需要使用来自不同包的具有相同名称的子模块。

6.4.2 内置包的引用

当包被结构化到子包里(就像例子中的sound包),你可以使用绝对的imports来引用兄弟包的模块。例如,如果模块sound.filters.vocoder需要使用包sound.effects里面的echo模块,可以使用from sound.effects import echo。

你也可以写相对的imports,使用import语句的from module import name形式。这些imports使用前导点(句点儿)来指示在相对import里面包含的当前的和父亲的包。从surround模块,你可以这样使用:

注意,相对imports是基于当前模块的名称。因为主模块的名称总是"__main__",打算用作Python应用程序的主模块的那些模块必须总是使用绝对imports。

多个目录里的包

包多支持一个特别的属性,__path__。它被初始化为一个包含包的__init__.py文件的目录的名称的列表在那个文件里的代码被执行之前。这个变量可以被改变,这样做影响将来对包里的模块和子包的搜索。

当然,这个特性也不常用,它可以被用于扩展一个包里的模块集合。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/90100.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

最简单的方式实现Zotero文件同步+坚果云在多台电脑设备之间

应用场景: 放假回家,只带了笔记本搞科研的好童靴,发现实验室台式机的zotero中的PDF没办法在笔记本上读取。于是探索了一下午如何不重新在网页上保存下载台式机中的PDF,轻松获取异地的文献。 方式一: 氪金付费zotero…

参数估计与假设检验

推断统计:研究如何利用样本数据来推断总体特征 描述统计:描述一组数据的特征 参数估计:利用样本信息估计总体特征 假设检验:利用样本信息判断对总体的假设是否成立 一.参数估计 就是对于总体指标的估计 估计:根据…

免费l2接口有多少种类型?

免费l2接口是一个预先定义的函数,它的目的是让开发人员和开发人员无需访问源代码,也无需访问源代码,也无需理解其内部工作。免费l2接口有多少种类型? 有四种类型的股票l2接口: RPC:通过处理(或任务)共享的数据缓冲区…

SpringBoot整合RabbitMQ实现死信队列

文章目录概念介绍什么是死信死信队列应用工程搭建环境说明搭建步骤实现死信准备Exchange&Queue监听死信队列方式一——消费者拒绝&否认方式二——超过消息TTL方式三——超过队列长度限制代码仓库前面一文通过 Java整合RabbitMQ实现生产消费(7种通讯方式&…

Spark的运行模式介绍

Spark的运行模式 本地模式(Local) 一般用做测试,测试代码的逻辑是否正确 本地模式,只启动一个Driver进程,没有Executor进程的,所有Task都运行在Driver进程中 集群模式 (Cluster) 一…

医疗挂号网站

开发工具(eclipse/idea/vscode等): 数据库(sqlite/mysql/sqlserver等): 功能模块(请用文字描述,至少200字): 管理员功能: 1、管理挂号须知、帮助信息 2、增删改查资讯类型、健康资讯信息 3、增删改查医生职称信息、医生…

装载问题 ——回溯法(Java)

装载问题 ——回溯法(Java) 文章目录装载问题 ——回溯法(Java)1、 问题描述1.1 装载问题1.2 转换问题2、算法设计2.1 可行性约束函数2.2 上界函数2.3 解空间树2.4 剪枝函数2.5 算法设计3、程序代码4、参考资料1、 问题描述 有一…

Hadoop安装准备

虚拟机的安装 配置了静态IP地址(192.168.1.100) 关闭与禁用了防火墙 安装了vim编辑器 虚拟机克隆 克隆出master虚拟机 以同样的步骤克隆出slave1和slave2 虚拟机配置 配置master虚拟机 启动虚拟机 设置主机名 命令:hostname…

C#语言和面向对象OOP

1、【重点面试题】面向对象的三大特性 封装 :隐藏对象的属性,并实现细节(方法),对外提供接口, public全局,protected子类,internal同集,隐藏private 同类,pub…

英文文章写作|文献管理|​​​​​​​阅读文献|引用文献|国内文章

目录 英文文章写作 1.阅读10篇文献,总结100个常用句型和常用短语 2.找3-5篇技术路线和统计方法与你的课题接近的文章,精读 3.针对论文的每一部分,尤其是某种具体方法、要讨论的某一具体方面,各找5-8 篇文献阅读,充…

使用HTMLTestRunner.py生成测试报告

1、如何收集测试结果? 使用第三方封装好类HTMLTestRunner.py生成HTML测试报告 # encoding:utf-8 import unittest import time from HTMLTestRunner import HTMLTestRunner class MyTestCase(unittest.TestCase): # 每条用例初始化 def setUp(s…

大数据技术之Spark基础解析

大数据技术之Spark基础解析 第1章 Spark概述 1.1什么是Spark 什么是Spark? 大数据的电花火石。 Spark类似于MapReduce的低延迟的交互式计算框架。 Spark是UC Berkeley AMPLab开发的是一种计算框架,分布式资源工作交由集群管理软件(Mesos、YARN&am…

Unity Addressables资源管理 打包路径设置

1.全局路径设置窗口的菜单位置 或 2.窗口界面 初始: Local:本地路径 Remote:远程路径 build指资源包生成位置 Load指资源包加载路径 BuildTarget:一个路径变量 Built-In 是内置默认的本地路径EditorHosted 则是编辑器和【托管服务】一起使…

零代码是什么?

上有国家层面的数字中国,数字经济的顶层规划,下有信息化飞速发展让组织、个人都深切体会到了信息技术带给生活的便利,如今信息化技术领域热度很高的低代码(LowCode)和零代码(No-Code)又开始进入…

太强了,GitHub白嫖的SpringCloud微服务进阶宝典,啃完吊打面试官

前言 自 2014 年起,微服务技术一直火热至今。随着越来越完善的微服务技术栈的发布,以及越来越多的微服务项目实际的落地和上线,使用 Java 技术栈的企业应该都在尝试或者已经落地了各自的微服务项目。同时,通过招聘网站的信息和每…

C# CallerMemberName,CallerFilePath,CallerLineNumber的使用

总目录 文章目录总目录前言一、作用二、使用1.案例三、使用场景总结前言 本文主要介绍CallerMemberName,CallerFilePath,CallerLineNumber的使用。 一、作用 本文将介绍的三个特性作用如下: CallerMemberName 允许获取方法调用方的方法或属…

基于STM32与PCA9685制作四足机器人(代码开源)

前言:本文为手把手教学基于STM32的四足机器人项目——JDY-31蓝牙控制,特别地,本次项目采用的是STM32作为MCU。四足机器人的支架为3D打印件,SG90舵机驱动机器人实现姿态运动。借助PCA9685舵机驱动板实现12路PWM波控制,更…

基于java+springboot+mybatis+vue+mysql的留守儿童爱心网站

项目介绍 随着留守儿童爱心管理的不断发展,留守儿童爱心网站在现实生活中的使用和普及,留守儿童爱心管理成为近年内出现的一个热门话题,并且能够成为大众广为认可和接受的行为和选择。设计留守儿童爱心网站的目的就是借助计算机让复杂的管理…

[附源码]Node.js计算机毕业设计二手图书回收销售网站Express

项目运行 环境配置: Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术: Express框架 Node.js Vue 等等组成,B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境:最好是Nodejs最新版,我…

程序调试:日常经验总结(一)

程序调试:日常经验总结一:如何快速的去查询一个类甚至是一个jar包中的class文件?二:如何快速找到本地项目编译之后的字节码文件三:本地启动小实例绑定同一个端口时候发生的报错。一:如何快速的去查询一个类…