python - 模块使用详解

news2024/9/26 5:23:20

前言

Python有非常强大的第三方库,也有非常多的内置模块帮助开发人员实现某些功能,无需开发人员自己造轮子。本文介绍Python的模块。

什么是模块

模块简单来说就是一系列功能的集合体,如果将程序的开发比喻成拼图,模块就是各种各样的拼图的碎片,准备好拼图碎片后,剩下的工作就是将需要的碎片按照顺序拼起来。

在Python中,一个py文件就是一个模块,Python中的模块分为三种,分别是:

  1. 内置模块 - Python解释器自带
  2. 第三方模块 - 需要手动安装
  3. 自定义模块 - 比如一个python文件

为啥要使用模块

自定义模块:可以将程序中的公用功能抽取出来放到一个模块中供大家使用,减少了代码冗余的前提下还能够使程序组织结构更加清晰。

内置模块和第三方模块:安装后直接使用模块的相关功能,无需自己造轮子,可以极大的提升开发效率。

自定义模块

自定义模块也是py文件,可以作为普通的python脚本执行,也可以作为模块来使用。比如新建一个test.py,该文件既是脚本程序也是一个模块,test就是模块名。

# test.py
x = 100
print(x)
def get():
    print(x)
    
def change():
    global x
    x = 0

自定义模块的使用

import语句

想要在其他文件中引用test.py中的数据和函数,可以使用import 模块名 进行模块导入,其他文件首次导入模块的时候会分为三步:

首先,执行模块文件中的代码;

然后,产生一个新的名称空间用来存放执行模块文件过程中产生的名字;

最后,在当前执行文件所在的名称空间中产生一个名字就是导入的模块名,该名字会指向模块执行时产生的名称空间,如果想要引用模块名称空间的名字,需要加上前缀用来区分当前文件的名称空间与模块的名称空间,防止名字的混淆。

具体代码如下:

import test  # import的语法是:import 模块名
# 引用test模块中的x,赋值给a变量
a = test.x
print(a)  # 1

# 调用test模块中的change函数
test.change()

加上test.作为前缀就相当于指名道姓的说明要引用test名称空间中的名字,所以肯定不会与当前执行文件所在名称空间中的名字相冲突,并且若当前执行文件的名称空间中存在x,执行test.change()操作的都是模块文件中的全局变量x。

需要注意的是,在导入模块时只有第一次导入时会执行模块中的代码将其加载到内存空间,之后重复的导入直接引用内存中已存在的模块,不会重复执行。

使用import导入多个模块时可以书写多行import语句。

import module1
import module2
...

也可以通过import一行导入,将不同模块用逗号隔开。

import module1, module2....

虽然两种格式都可以,但是前一种形式更加规范,推荐使用。在一个py文件中可能会包含多种模块,内置模块、第三方模块、自定义模块,为了增加代码可读性以及更好的符合PEP8规范(python开发中编写代码的规范)通常在文件开头导入模块,并且将三种不同模块中间用空行隔开。

import python内置模块
import python内置模块

import 第三方模块
import 第三方模块

import 自定义模块
import 自定义模块

from...import语句

from 模块名 import 名字,也可以实现导入模块,不同的是import 模块名 导入模块后,引用模块中的名字都需要加上模块名.作为前缀,而使用from 模块名 import 名字则可以在当前执行文件中直接引用模块中的名字,如下:

from test import x, change  # 将模块test名称空间中的x和change导入到当前名称空间

b = x  # 将模块test中的x赋值给b
change()  # 执行test模块中的change方法,修改的是模块中的x变量

这种方式在引用其他自定义模块的名字时不需要加模块名的前缀,使代码更加整洁,但是缺点也很明显,就是容易和当前py文件的名称空间中的名字冲突。

另外此种导入模块的方式也支持如下写法,表示将模块中所有的名字都导入到当前位置。

from 模块名 import *

使用此种导入模块的方式导入模块也会发生三件事:

首先,运行模块中的代码;

然后,运行模块文件将运行过程中产生的名字都放到模块的名称空间;

最后,被当前文件引用的模块中的名字也会导入到当前文件的名称空间,这些名字分别指向被导入的模块名称空间中的某一个内存地址。

两种导入方式对比

优缺点import 模块名from 模块名 import 名字
优点肯定不会与当前名称空间的名字冲突不加前缀,代码更精简
缺点加前缀显得代码不简洁容易与当前名称空间的名字混淆

其他语法 - as

可以为导入的模块起一个别名,例如:

import test as t

print(t.x)
t.change()

也可以为导入的名字起别名,例如:

from test import change as change_x

change_x()

当被导入的名字过长时就可以使用起别名的方式来精简代码,而且起别名可以很好地避免与当前文件的名称空间中的名字发生冲突。

循环导入

循环导入的问题指的是在一个模块加载/导入的过程中导入另外一个模块,而另一个模块中又返回来导入第一个模块中的名字,由于第一个模块尚未加载完毕,所以引用失败,抛出异常。以下述文件为例分析循环导入出现的异常的原因及解决方案。

 如果直接运行module1.py或者module2.py同样也会报错,报错的原因都是由于循环导入。解决循环导入问题有以下两种方案:

第一种,将导入语句放到代码最后,保证在导入的时候,模块中的所有名字都已经加载到名称空间中。

第二种,将导入语句放到函数中,只有调用函数时才会执行其内部代码。

这里需要补充一点,理论上来讲,在函数内导入模块,这个模块是在局部名称空间的,当函数调用结束之后模块对应的名称空间应该被回收,但是当函数调用结束之后,再次导入模块,模块文件却不会运行。如下述代码:

def test():
    import foo  # 在函数内导入模块
test()

import foo  # 执行函数后,再次导入,发现已经不会运行模块文件了,说明不是第一次导入

print(sys.modules)  # 查看加载到内存中的模块

产生这种现象的原因:python解释器内部优化机制,默认导入的模块在执行文件中会被大量使用,所以即便是在局部名称空间中也不会被回收。

循环导入问题大多数情况下都是因为程序设计失误导致的,上述方案也只是在设计失误额前提下的无奈之举,在设计程序的时候应尽可能避免出现循环导入的问题。

查找模块路径及优先级

无论是import 还是from...import...导入模块都涉及到查找模块路径的问题,模块查找顺序按照如下规则进行:

首先,在内存中查找,在导入一个模块时,如果该模块已经加载到内存中,就直接引用。可以通过导入sys模块(import sys),打印sys.modules查看已经加载到内存中的模块名称。

然后,如果内存中没有,再去查找内置模块。

最后,如果内置模块中没有,就按照从左到右的顺序依次检索sys.path(称为模块的搜索路径,是一个列表)中的路径,直到找到模块对应的文件,否则抛出异常。

通过下面的例子,来说明模块查找的优先级:创建一个test.py文件作为模块,创建一个run.py文件作为执行文件。

在执行文件休息10s的时间内,快速将模块文件foo.py删除,10s结束后再次调用foo.py中的foo函数,如果能够调用成功,那么就说明是在内存中导入的foo文件。经过验证,10s后的foo函数可以被调用,但是如果重新运行执行文件就会报错,提示没有foo模块。

# test.py
def test():
    print('我是test')
print('test')

# run.py
import time
from test import test

test()
time.sleep(10)
test()  

如果内存中没有找到模块,也不属于内置模块,就按照从左到右的顺序依次检索sys.path列表中路径下的文件。需要注意的是,sys.path在pycharm和python解释器中得到的结果不同,使用pycharm查看sys.path时会将当前项目路径自动加入到sys.path列表中。

# pycharm运行结果
import sys
print(sys.path)

['F:\\FullStack\\Python_based', 'F:\\FullStack\\Python_based', 'E:\\python3.9\\python39.zip', 'E:\\python3.9\\DLLs', 'E:\\python3.9\\lib', 'E:\\python3.9', 'E:\\python3.9\\lib\\site-packages']


# python解释器运行结果
>>> import sys
>>> sys.path

['', 'E:\\python3.9\\python39.zip', 'E:\\python3.9\\DLLs', 'E:\\python3.9\\lib', 'E:\\python3.9', 'E:\\python3.9\\lib\\site-packages']

使用python解释器得到的sys.path的结果第一个元素通常为空,代表执行文件所在的路径,所以在被导入模块与执行文件在同一目录下时肯定是可以正常导入的,而针对被导入的模块与执行文件在不同路径下的情况,为了确保模块对应的源文件仍可以被找到,需要将模块文件所在的路径添加到sys.path中,假设模块文件test.py所在的路径为D:/modules。

import sys

sys.path.append(r'D:/modules')  # 也可以使用insert方法
import test

py文件的两种用途

一个py文件有两种用途,一种是当做程序或者脚本执行,另一种是被当做模块,为了区分同一个py文件的不同用途,每个py文件都内置了__name__变量,该变量在py文件被当做脚本执行时赋值为__main__,在py文件被当做模块导入时赋值为模块名。

可以在模块文件的末尾基于__name__来测试模块功能代码,当文件被当做脚本运行时,会执行if后的代码块,当做模块导入时则不执行。

# test.py
...  # 代码
...  # 代码

if __name__ == '__main__':
    test.py被当做脚本文件执行时运行的代码

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

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

相关文章

读懂海尔智家大脑:深度体验的本质是深度生活

了解科技行业的读者,应该都对“大脑”这个名词不陌生。 “黑灯工厂”里指挥生产的“工业大脑”,繁忙机场里运筹帷幄的“航空大脑”,还有智慧城市建设的灵魂“城市大脑”…… 如果家也有一颗总揽全局的大脑,生活会发生什么改变呢&a…

SuperMap GIS基础产品三维GIS FAQ集锦(2)

SuperMap GIS基础产品三维GIS FAQ集锦(2) 【WebGL】桌面对三维缓存设置了最大最小可见高度,在iServer发布三维服务并进行预览是可以看到该效果的,但在前端代码打开该服务,最大最小可见高度效果丢失,请问怎…

Makefile零基础教学(一)初识makefile

从这篇文章开始就开始进入 Makefile 的零基础教程,相信只要看了本教程的都可以对 Makefile 有一个清晰的理解和正确的运用。那么现在就开始我们的 Makefile 学习之路。 文章目录 一、什么是 Makefile,优点?二、什么是 make, 为什么使用make?…

可拓展哈希

可拓展哈希 借CMU 15445的ppt截图来说明问题。 我们传统静态hash的过程是hash函数后直接将值存入对应的bucket,但是在可扩展hash中,得查询Directory(左),存入directory指向的bucket(右)。 下面…

linux线程池、基于线程池的单例模式、读者写者问题

线程池&单例模式 一、什么是线程池二、设计思路三、代码实现四、基于线程池的单例模式4.1 懒汉模式设计思路 五、读者写者问题及读写锁 一、什么是线程池 线程池: 一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个…

flashback database 深入学习

一.FlashbackDatabase 和 Restore Points 说明 OracleFlashback Database and restore points are related data protectionfeatures that allow you to rewind data back in time tocorrect any problems caused by logical data corruption or user errors within adesignate…

gopher 初探

文章目录 gopher协议简介发送GET请求curlgopher gopher发POST请求 gopher协议 简介 Gopher是Internet上一个非常有名的信息查找系统,它将Internet上的文件组织成某种索引,很方便地将用户从Internet的一处带到另一处。在WWW出现之前,Gopher是…

【AI绘画】——Midjourney关键词格式解析(常用参数分享)

目前在AI绘画模型中,Midjourney的效果是公认的top级别,但同时也是相对较难使用的,对小白来说比较难上手,主要就在于Mj没有webui,不能选择参数,怎么找到这些隐藏参数并且触发它是用好Mj的第一步。 今天就来…

Motrix 全能型下载神器(时隔两年,重新焕发生机)

简介 Motrix 是一款功能强大的下载管理器,支持 HTTP、FTP、BT、磁力链等多种下载协议,同时还具备浏览器插件和跨平台(Windows、macOS、Linux)的特点。它拥有多线程下载、断点续传、任务调度、自动更新等多种实用特性,…

学习笔记:基于SpringBoot的牛客网社区项目实现(六)之发表帖子 + 评论 + 私信

一、过滤敏感词 二、发布帖子 业务流程: 1、先创建帖子的实体DiscussPost,属性有帖子id,user_id,title,content,type,status,create_time,comment_count,scor…

【Python入门知识】NumPy 数组搜索,案例+理论讲解

前言 嗨喽~大家好呀,这里是魔王呐 ❤ ~! 搜索数组 可以在数组中搜索(检索)某个值,然后返回获得匹配的索引。 要搜索数组,请使用 where() 方法。 实例 查找值为 4 的索引: import numpy as nparr np.…

[ tool ] Xpath选择器和selenium工具基本使用

XPath xpath介绍 是一门在XML文档中查找信息的语言 html文档准备 doc <html><head><base hrefhttp://example.com/ /><title>Example website</title></head><body><div idimages><a hrefimage1.html aabb>Name: My…

车载激光雷达原理+双激光雷达方案+纯激光雷达感知3Dbonding box

集度汽车透露了首款汽车机器人概念车车头部位的设计细节&#xff0c;车前灯和车前盖处激光雷达的设计清晰可见。至此&#xff0c;集度汽车的车前盖、前向双激光雷达自动驾驶技术方案首次曝光。 集度汽车官方也称&#xff0c;“双激光雷达”设计方案极具创新性&#xff0c;激光…

求中位数?

文章目录 如何求一个中位数&#xff1f;[295. 数据流的中位数](https://leetcode.cn/problems/find-median-from-data-stream/)常规思路&#xff1a;解决思路&#xff1a; 如何求一个中位数&#xff1f; 如果输入一个数组&#xff0c;让你求中位数&#xff0c;简单的解决方法就…

不合格机器人工程讲师如何坦然面对失败

能坦然面对的重要原因是我自己从一开始就知道注定要失败的&#xff0c;或者说失败率接近99.9%。 能够从失败中成长&#xff0c;不断挑战自我&#xff0c;收获更多更大的失败也是一种体验。 失败是客观事实&#xff0c;坦然是主观上的正能量的情绪。 用客观态度对待客观事实。 …

JavaScript class和继承的原理

&#xff08;对于不屈不挠的人来说&#xff0c;没有失败这回事。——俾斯麦&#xff09; class 相关链接 MDN链接 有关类的详细描述 关于构造函数&#xff0c;原型和原型链的说明 类的概述 类是用于创建对象的模板。他们用代码封装数据以处理该数据。JS 中的类建立在原型上…

4月跳槽进字节跳动了,面试真简单...

前言: 最近金三银四跳槽季&#xff0c;相信很多小伙伴都在面试找工作&#xff0c; 怎样才能拿到大厂的offer&#xff0c;没有掌握绝对的技术&#xff0c;那么就要不断的学习&#xff0c;没有绝对的天才&#xff0c;只有持续不断的付出。对于我们每一个平凡人来说&#xff0c;…

Detecting Kernel Memory Leaks in Specialized Modules with Ownership Reasoning

Detecting Kernel Memory Leaks in Specialized Modules with Ownership Reasoning 背景&#xff1a; 内存泄漏&#xff1a;A memory leak happens when an allocated memory region is not released even though it will never be used again.分配的内存未被正常释放。 内存…

Java高阶数据结构 图 图的表示与遍历

高阶数据结构&#xff01; 文章目录 Java高阶数据结构 & 图的概念 & 图的存储与遍历1. 图的基本概念1.1 图的属性1.2 无向图与有向图1.3 完全图1.4 简单路径和回路1.5 子图1.6 连通图 2. 图的存储&#xff08;理论&#xff09;2.1 ※邻接矩阵2.2 邻接链表3. 图的存储&a…

新唐NUC980使用记录(5.10.y内核):u-boot linux rootfs 编译与烧录测试(基于SD1位置SD卡)

文章目录 目的基础准备烧录环境开发编译环境SD卡分区 制作和设置编译工具链制作toolchain和rootfs拷贝rootfs内容到SD卡设置编译工具链 u-boot编译与测试下载、配置与编译烧录u-boot与环境变量 linux kernel编译与测试下载、配置与编译系统运行测试 总结设备树文件内容 目的 从…