每天一小时python官方文档学习(七)————模块与包

6. 模块

模块是一个包含Python定义和语句的文件,实际上就是一个正常的.py文件。但是作用和普通需要运行的程序不一样,它实际上有点像函数。如果说函数实现了代码的重用,模块则是实现了函数的重用。我们如果想在不同的程序中使用同一个函数, 不必把这个函数复制到每一个程序中去,而是通过把函数写在一个模块中,然后程序通过导入模块就可以使用这个函数了。

模块文件名就是模块名后跟文件后缀 .py 。在一个模块内部,模块名(作为一个字符串)可以通过全局变量 __name__ 的值获得。例如,你可以在当前目录下创建一个名为 fibo.py 的文件,模块名即为fibo,而文件中含有以下内容:

# 斐波拉契数列模块def fib(n):    # 打印斐波拉契数列a, b = 0, 1while a < n:print(a, end=' ')a, b = b, a+bprint()def fib2(n):   # 返回斐波拉契数列的列表result = []a, b = 0, 1while a < n:result.append(a)a, b = b, a+breturn result

这个fibo.py文件就是所谓的模块文件,它里面就是两个函数,一个负责打印斐波拉契数列,另一个负责返回斐波拉契数列的列表。我们通过在Python解释器中输入import指令即可导入这个模块:

>>> import fibo

在当前的符号表中,这并不会直接进入到定义在 fibo 函数内的名称;它只是进入到模块名 fibo 中。你可以用模块名访问这些函数:

>>> fibo.fib(1000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
>>> fibo.fib2(100)
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
>>> fibo.__name__    #查看全局变量__name__,即显示模块名
'fibo'

除了直接访问和调用,把模块中函数赋值给一个局部变量也是可以的:

>>> fib = fibo.fib
>>> fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

6.1. 有关模块的更多信息

我们都知道,模块可以包含可执行的语句以及函数定义。这些语句通常是用于初始化模块的,它们仅在模块第一次import 语句中被导入时才执行(实际上,函数定义也是“被执行”的“语句”,模块级函数定义的执行在模块的全局符号表中输入该函数名)。

每个模块都有它自己的私有符号表,该表用作模块中定义的所有函数的全局符号表。因此,模块的作者可以在模块内使用全局变量,而不必担心与用户的全局变量发生意外冲突。

import 语句有一个变体,它可以把名字从(from)一个被调模块内直接导入(import)到现模块的符号表里。例如:

>>> from fibo import fib
>>> fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

这并不会把被调模块名引入到局部变量表里,因此在这个例子里,fibo 是未被定义的,fibo里面只有fib被导入了,fib2未被导入。如果想导入模块内定义的所有名称:

>>> from fibo import *
>>> fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

这会调入所有不以下划线_开头的名称。 在多数情况下,Python程序员都不会使用这个功能,因为它在解释器中引入了一组未知的名称,而它们很可能会覆盖一些你已经定义过的东西。注意通常情况下从一个模块或者包内调入 * 的做法是不太被接受的, 因为这通常会导致代码的可读性很差。不过,在交互式编译器中为了节省打字可以这么用。

最后,我们可以在模块名称后面加上 as,则跟在 as 之后的名称将直接绑定到所导入的模块,这通常用于给模块名提供一个缩写,则调用模块函数时不用写那么多字,例如import tensorflow as tfimport numpy as np等等。

6.1.1. 以脚本的方式执行模块

模块文件既然是.py文件,那当然也可以直接执行它,在Python解释器中输入:

>>> python fibo.py # 如果有参数则写在这里

模块里的代码会被执行。那直接执行和导入模块有什么区别呢?

区别就在于 __name__ 的值会不一样。上面我们看到,导入模块后,通过fibo.__name__我们能看到__name__的值为’fibo’即模块名;但是直接执行以后,__name__会被赋值为 "__main__"。 因此,我们可以通过条件判断语句,规定一些语句时只有直接执行模块时才有效的:

if __name__ == "__main__":# 直接执行模块时才会运行的语句,导入模块时不运行

6.1.2. 模块搜索路径

当一个模块被导入时,解释器会怎么样在电脑中寻找这个模块文件呢?
解释器首先寻找具有该名称的内置模块。如果没有找到,然后解释器从 sys.path 变量给出的目录列表里寻找文件。sys.path 初始有这些目录地址:

  • 包含输入脚本的目录(或者未指定文件时的当前目录)
  • PYTHONPATH (一个包含目录名称的列表,它和shell变量 PATH有一样的语法)
  • 取决于安装的默认设置

6.1.3. “编译过的”Python文件

为了加速模块载入,Python在 __pycache__ 目录里缓存了每个模块的编译后版本,名称为 module.version.pyc ,其中名称中的版本字段对编译文件的格式进行编码,它一般使用Python版本号。

6.2. 标准模块

Python附带了一个标准模块库,这些模块内置于解释器中,它们提供对不属于语言核心但仍然内置的操作的访问,以提高效率或提供对系统调用等操作系统原语的访问。标准库也是属于不要求全部记住,但是常用的应该有印象的知识,建议多查阅官方文档

这些模块的集合是一个配置选项,它也取决于底层平台。例如,winreg 模块只在Windows操作系统上提供。一个特别值得注意的模块 sys,它被内嵌到每一个Python解释器中。变量 sys.ps1 和 sys.ps2 定义用作主要和辅助提示的字符串,这两个变量只有在编译器是交互模式下才被定义,例如:

>>> import sys
>>> sys.ps1
'>>> '
>>> sys.ps2
'... '
>>> sys.ps1 = 'C> '
C> print('Yuck!')
Yuck!
C>

6.3. dir() 函数

内置函数 dir() 用于查找模块定义的名称,它返回一个排序过字符串列表,这个列表就包括所有类型的名称:变量,模块,函数,等等:

>>> import fibo, sys   # 先导入fibo和sys模块
>>> dir(fibo)   # 查找fibo模块
['__name__', 'fib', 'fib2']
>>> dir(sys)    # 查找sys模块
['__displayhook__', '__doc__', '__excepthook__', '__loader__', '__name__','__package__', '__stderr__', '__stdin__', '__stdout__','_clear_type_cache', '_current_frames', '_debugmallocstats', '_getframe','_home', '_mercurial', '_xoptions', 'abiflags', 'api_version', 'argv','base_exec_prefix', 'base_prefix', 'builtin_module_names', 'byteorder','call_tracing', 'callstats', 'copyright', 'displayhook','dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix','executable', 'exit', 'flags', 'float_info', 'float_repr_style','getcheckinterval', 'getdefaultencoding', 'getdlopenflags','getfilesystemencoding', 'getobjects', 'getprofile', 'getrecursionlimit','getrefcount', 'getsizeof', 'getswitchinterval', 'gettotalrefcount','gettrace', 'hash_info', 'hexversion', 'implementation', 'int_info','intern', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path','path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1','setcheckinterval', 'setdlopenflags', 'setprofile', 'setrecursionlimit','setswitchinterval', 'settrace', 'stderr', 'stdin', 'stdout','thread_info', 'version', 'version_info', 'warnoptions']

如果没有参数,dir() 会列出你当前定义的名称:

>>> a = [1, 2, 3, 4, 5]
>>> import fibo
>>> fib = fibo.fib
>>> dir()
['__builtins__', '__name__', 'a', 'fib', 'fibo', 'sys']

dir() 不会列出内置函数和变量的名称,如果你想要这些,它们的定义是在标准模块 builtins 中。

6.4. 包

包是一种通过用“带点号的模块名”来构造 Python 模块命名空间的方法,简单来说,包就是模块的集合。例如,模块名 A.B 表示 A 包中名为 B 的子模块。正如模块的使用使得不同模块的作者不必担心彼此的全局变量名称一样,使用加点的模块名可以使得 NumPy 或 Pillow 等多模块软件包的作者不必担心彼此的模块名称一样。

假设有这么一个包的文件,它有三个子包,每个子包里面有各自的模块:

sound/                          包含三个子包的包__init__.py               对sound初始化的模块formats/                  用于文件格式转换的子包__init__.py		对formats初始化的模块wavread.pywavwrite.pyaiffread.pyaiffwrite.pyauread.pyauwrite.py...effects/                  包含不同音效的子包__init__.py		对effects初始化的模块echo.pysurround.pyreverse.py...filters/                  用于声音滤波的子包__init__.py		对filters初始化的模块equalizer.pyvocoder.pykaraoke.py...

我们可以从包中导入单个模块,例如:

import sound.effects.echo

这会加载子模块 sound.effects.echo ,但引用它时必须使用它的全名

sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)

也可以直接导入子模块

from sound.effects import echo

这会加载子模块 echo ,并使其在没有包前缀的情况下可用,因此可以不使用全名

echo.echofilter(input, output, delay=0.7, atten=4)

甚至还可以直接导入所需的函数或变量

from sound.effects.echo import echofilter

同样,这也会加载子模块 echo,但这会使其函数 echofilter() 直接可用

echofilter(input, output, delay=0.7, atten=4)

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

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

相关文章

大揭秘| 我司项目组Gitlab Flow DevOps流程

长话短说&#xff0c;本文全景呈现我司项目组gitlab flow && devopsGit Flow定义了一个项目发布的分支模型&#xff0c;为管理具有预定发布周期的大型项目提供了一个健壮的框架。DevOps 强调的是团队通过自动化的工具协作和高效地沟通来完成软件的生命周期管理&#xf…

leetcode714.买卖股票的

一:题目 二&#xff1a;上码 class Solution { public:int maxProfit(vector<int>& prices, int fee) {/**思路:*/int ans 0;int minPrice prices[0];//最低时买入for(int i 1; i < prices.size(); i) {//低价买入minPrice min(minPrice,prices[i]);if(price…

C++ 学习之旅(1)——编译器Compiler

简单来说&#xff0c;由C代码文件生成可执行文件的过程如下&#xff1a; #mermaid-svg-GQamCVEXMVkYEemz {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GQamCVEXMVkYEemz .error-icon{fill:#552222;}#mermaid-svg-…

掌握Rabbitmq几个重要概念,从一条消息说起

RabbitMQ 是功能强大的开源消息代理。根据官网称&#xff1a;也是使用量最广泛的消息队列。就像他的口号“Messaging that just works”&#xff0c;开箱即用使用简单&#xff0c;支持多种消息传输协议&#xff08;AMQP、STOMP、MQTT&#xff09;。一个应用程序或者服务如何使用…

122. 买卖股票的时机

一&#xff1a;题目 二&#xff1a;上码 class Solution { public:int maxProfit(vector<int>& prices) {/**思路:1.这里用的是贪心算法&#xff08;我们每隔两天计算一次赚的钱 只要大于0的话 那就是赚的&#xff09;2.我们手里最多只能有一只股票,所以我们可以当…

C++ 学习之旅(2)——链接器Linker

每一个.cpp文件经过编译之后都会生成对应的.obj文件&#xff0c;然后通过链接器把它们进行链接&#xff0c;最后就可以生成.exe可执行文件了。 举个例子&#xff0c;假设我们有一个 Math.cpp 文件和 Log.cpp 文件&#xff1a; Math.cpp #include <iostream>void Log(c…

使用 WPF 版简易 SIP 服务器向 GB28181 摄像头发送直播请求

使用 WPF 版简易 SIP 服务器向 GB28181 摄像头发送直播请求目录一、引言二、项目渊源三、软件使用及 SIP INVITE 流程(一) 注册和心跳(二) 直播 INVITE四、注意事项五、资源独立观察员 2020 年 9 月 16 日一、引言之前写过一篇博客《使用 GB28181.Solution ZLMediaKit MediaSe…

leetcode968. 监控二叉树

一:论语 这个有意思,我们可以从中得出的是&#xff0c;一个人过错 其实是潜意思决定的 行为见品质 但知错更改也是nice的 二:题目 三:上码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* Tr…

C++ 学习之旅(3)——头文件Header

我们知道&#xff0c;在 C 中&#xff0c;函数只能定义一次&#xff0c;而在 cpp 文件中如果想使用其他 cpp 文件中定义了的函数&#xff0c;就必须声明&#xff0c;这样才能通过编译&#xff0c;然后链接器才会在调用函数时找到该函数的定义。那么当函数声明很多的时候&#x…

虚虚实实,亦假亦真的 ValueTuple,绝对能眩晕你

一&#xff1a;背景 1. 讲故事前几天在写一个api接口&#xff0c;需要对衣物表进行分页查询&#xff0c;查询的output需要返回两个信息&#xff0c;一个是 totalCount,一个是 clothesList,在以前我可能需要封装一个 PagedClothes 类&#xff0c;如下代码:public class PagedClo…

session.setAttribute和request.setAttribute的区别

一&#xff1a;问题的引出 我在设置拦截器的时候&#xff0c;将登录信息存在了request作用域当中&#xff0c;我设置登录页面的时候是放行 的登录页面的请求的&#xff0c;同时将登录信息是设置在request的作用域中的&#xff0c;可是进入主页面后&#xff0c;我再进入其他页面…

C++ 学习之旅(4)——调试Debug

调试 Debug 程序&#xff0c;首先应该确保处于 Debug 模式而不是 Release 模式下&#xff0c;因为后者会优化你的程序&#xff0c;也就是对你的程序作出了改变&#xff0c;这样你很难找出问题所在。记得在 Debug 之前确保优化是已禁用的&#xff1a; 我们有以下的文件&#xff…

关于脑机接口该如何实现的考虑

脑机接口&#xff0c;已经是最近最热门的科技热点了&#xff0c;因为埃隆马斯克的炒作和推动&#xff08;炒作说的是他本人并不懂技术&#xff0c;宣传中有了很多夸大和不实之词&#xff0c;推动说的是因为他的炒作和带动&#xff0c;有了更多的资金进入了这个领域&#xff0c;…

C++ 学习之旅(5)——设置Setup文件目录

使用过Visual Studio的朋友都应该知道&#xff0c;VS对于编译后的obj文件以及链接生成的exe文件的存放方式是非常反人类的&#xff0c;所以我们有必要对这个设置进行更改。 首先要分清Filter和Folder的概念&#xff0c;在默认的文件目录中&#xff0c;我们看到的实际上是Filte…

JVM笔记详解之垃圾回收器

一&#xff1a;什么是垃圾回收机制&#xff08;GC&#xff09; 在C/C程序中&#xff0c;程序员在内存中主动开辟一段相应的空间来存值。由于内存是有限的&#xff0c;所以当程序不再需要使用该内存空间时&#xff0c;就需要销毁对象并释放其所占用的内存资源&#xff0c;好重新…

跟我一起学.NetCore之配置初体验

前言配置对于程序来说&#xff0c;绝对是必不可少&#xff0c;毕竟配置是应用或组件动态适应各种环境的最优方案&#xff0c;没有之一(我还年轻&#xff0c;我是这么认为的)&#xff1b;之前可能用的最多的配置源是命令行、文件(XML、Json、INI)&#xff0c;Web中对于Asp.Net程…

C++ 学习之旅(6)——循环loop

C中最为常用的三种循环&#xff1a;for 循环、while 循环和 do-while 循环&#xff0c;直接上代码&#xff1a; for循环 for ( init; condition; increment ) {statement(s); }init 会首先被执行&#xff0c;且只会执行一次。这一步允许您声明并初始化任何循环控制变量。您也…

JVM笔记(JVM内存+垃圾回收器)详解

一:java代码的执行流程(引出JVM) 首先由程序员编写成.java文件然后由javac(java编辑器)将.java文件编译成.class文件.class文件可以在不同平台/操作系统上的JVM上执行再由JVM编译成可供不同操作系统识别的机器码&#xff08;0,1二进制&#xff09; 二:JVM来源 我们在下载JD…

跟我一起学.NetCore之Asp.NetCore中集成Autofac扩展

前言前两节针对.NetCore自带的依赖注入进行简要概述&#xff0c;对于日常开发的需求应该是能满足了&#xff0c;那为什么还需要引入第三方依赖注入组件呢&#xff0c;这里就从自带的依赖注入来分析&#xff0c;有什么样的需求满足不了&#xff1f;主要归纳为以下几点&#xff1…

C++ 学习之旅(7)——指针pointer

开门见山&#xff0c;如果把计算机的内存空间比作是一排房子&#xff0c;那指针就是房门号。指针实际上就是一个用来存储内存地址的整数&#xff0c;与类型没有关系&#xff0c;我可以定义一个void类型的指针&#xff1a; #include <iostream>int main() {int var 8;v…