找往期文章包括但不限于本期文章中不懂的知识点:
个人主页:我要学编程(ಥ_ಥ)-CSDN博客
所属专栏: Python
目录
模块的概念
模块的导入
包的概念以及使用
主程序运行
Python中常用的内置模块
random模块
time模块
datetime模块
模块的概念
模块就是一个后缀名为.py的Python文件。我们前面写代码创建的.py文件就是一个模块。模块中可以定义变量、函数、类等等。模块可以避免函数、类、变量等名称相冲突的问题。模块不仅提高了代码的可维护性,同时还提高了代码的可重用性。在给模块命名的时候要求全部使用小写字母,多个单词之间使用下划线进行分隔。如果自定义模块名称与系统内置模块名称相同,那么在导入时会优先导入自定义的模块。
模块分为三种:一种是Python内置的模块,这是由Python的开发人员编写好的,在安装Python解释器的时候,就一同安装好了,例如:random模块、math模块等。另一种是第三方模块,非Python开发人员(第三方)编写好的,当我们想要使用时需要去下载。最后一种是自定义模块,这是我们自己在编写代码所创建的Python文件。
自定义模块的作用:一是规范代码,将功能相同的函数、类等封装到一个模块中,让代码更易于阅读;另外一个目的与系统内置模块相同,即可以被其它模块调用,提高开发的效率。
这里的模块与C语言中的头文件功能是类似的。
模块的导入
模块编写完成就可以被其它模块进行调用并使用被调用模块中的功能了。
语法:
# 1、直接导入模块中的全部代码
import 模块名称 [as 别名]
# 2、只导入模块中的部分功能代码
from 模块名称 import 变量/函数/类/* # * 和 第一种方式没啥区别都是导入全部
代码演示:
login模块:
n = '我要学编程'
pw = '12345678'
name = input('请输入你的用户名:')
password = input('请输入你的密码:')
if name == n and password == pw:
print('登录成功~')
else:
print('登录失败')
verify模块:
# 利用 login模块 中的代码来执行验证身份,而不需要再去编写代码了
import login
在verify模块中导入login模块, 相当于是将login模块中的代码全部搬到了verify模块中,因此可以使用login模块中的全部变量/函数/类了。
运行结果:
对于 login模块 的编写并不是很准确,如果后面我们需要编写模块,应当使用函数将不同功能的代码给封装起来,这样就不会全部都执行了。如下图所示:
由于 login模块 中的代码被封装起来了,而且我们并未在 login模块中直接去调用 login函数,因此即使在 verify模块 中,导入了 login模块,并不会执行login函数,而是需要我们手动地去执行。
上面是 import 的使用场景,下面我们来看 from import 的使用场景:
经过上面的学习,我们已经知道了 import 模块,会去执行其中的代码,而模块中的代码常常是成千上万行,如果全部执行的话,就会严重影响我们程序的运行效率,那怎么办呢?既然全部导入会影响效率,那么我们只将需要执行的代码导入不就好了嘛。于是便有了 from import 的语法。当然,由于模块中代码的具体功能都是经过函数封装的,肯定是不会直接出现代码中的,但是加载代码也是需要时间的,因此在以后的使用中,如果对于时间要求很高的场景最好还是不是导入全部。
代码演示:
login模块:
n = '我要学编程'
pw = '12345678'
def loginRoot():
name = input('请输入你的用户名:')
password = input('请输入你的密码:')
if name == n and password == pw:
print('登录成功~')
else:
print('登录失败')
username = '123'
userpassword = '12345'
def loginUser():
name = input('请输入你的用户名:')
password = input('请输入你的密码:')
if name == username and password == password:
print('登录成功~')
else:
print('登录失败')
verify模块:
# 利用 login模块 中的代码来执行验证身份,而不需要再去编写代码了
# import login
from login import loginUser # 这里相当于是将loginUser函数的代码搬到这里了
loginUser()
# loginRoot() # error 因为没有定义这里函数
运行结果:
由于模块名或者模块中的函数名可能过于繁琐,因此我们也可以自己手动去起别名。同时也可以导入多个模块,模块之间使用 "逗号" 进行分隔即可。
注意:
1、在上述代码中,如果想要调用某一个函数,有两种方式:
1)使用 import 模块名称,再去使用 "模块名称 . 具体函数" 来调用
2)使用 from 模块名称 import 具体函数,这就可以直接去调用函数了。
由于第一种方式使用繁琐,如果对于频繁访问的变量或函数,我们常常是使用 " from 模块名称 import * "的方式,将所有的代码全部加载到该文件中的方式,便于我们更好的访问。
2、如果导入的多个模块中存在多个相同的相同类型的变量名称,那么后导入的会将先导入的进行覆盖。如果是多个不同类型的变量名称,同样后导入的会将先导入的进行覆盖。如下所示:
上面两张图片也反映出了我们这里的注意情况。
使用 "import 模块名称" 的语法,在调用其中的变量或者函数时,需要使用 "import 模块名称" 来调用,而 "from 模块名称 import 函数名称 " 的语法相当于是直接将这个函数定义到了该文件中,因此后序可以直接去访问即可。同样第一种方式可以避免导入的内容因为重名而被覆盖的情况。
包的概念以及使用
前面我们学习了模块的出现可以让同名的变量存在,那如果模块同名了怎么办呢?这里就需要用到包了。包可以避免模块名称相冲突的问题,类似于文件夹的功能。在电脑中,C盘目录下不能存储两个相同的名称的文件,但是可以建一个文件夹,然后分别存在不同的文件下,这样就解决了文件名冲突的问题。在Python中与之不同的是还会新创建一个 __init__.py 的文件在包下。
代码演示:
__init__文件:
print('这是__init__.py文件中的内容')
test文件:
def info():
print('这是test.py文件中的内容')
Demo文件: (未在包的路径下)
# 需求:使用test包下面的test模块中的info方法
# 方式一:采用import的方式
import test.test
test.test.info()
# 方式二:采用from import的方式
from test import test
test.info()
运行结果:
按照正常的逻辑来说,这里只会调用 info函数,并打印其中内容,但是在一开始却打印了 init 文件中的内容。这是因为在导入某个包之后,程序会执行这个包下的 init 文件来初始化包的属性,然后再去执行其他的逻辑。
注意:如果在程序的执行过程中,遇到了导入包的语句,则是会先查看这个包是否已经导入过。如果导入了,那么继续往下执行,如果没导入过,就会先导入(在这个过程中就会执行 init 文件下的代码)。如下所示:
主程序运行
通过前面的学习,我们知道了:当我们手动导入一个模块之后,这个模块会被执行,如果不想要里面的部分代码被执行,前面我们是通过封装成函数的形式,但问题是:这个函数可能会被调用,如果是一些测试代码呢?这种只想要在模块主动执行才执行的代码呢?上面的方式就不适合了,因此这里需要用到"主程序运行"的知识。
if __name__ == '__main__':
...
当一个文件中存在上述代码时,只有当这个文件作为主程序执行时,这个代码下的 "......" 才会被执行。即只有当我们去主动执行这个Python文件时,if __name__ == '__main__': 下的代码才会被执行。
Python中常用的内置模块
在安装Python解释器时与解释器一起安装进来的模块被称为系统内置模块,也被称为标准模块或标准库。
模块名称 | 功能 |
os | 与操作系统和文件操作相关的模块 |
re | 与Python中字符串的正则表达式相关的模块 |
random | 用于产生随机数的模块 |
json | 用于对高维数据进行编码与解码的模块 |
time | 与时间相关的模块 |
datetime | 与日期时间相关的模块,可以方便的显示日期并对日期进行运算 |
random模块
random模块是Python中用于产生随机数的标准库。接下来我们学习random模块中常用的函数:
函数名称 | 功能 |
seed(x) | 初始化给定的随机数种子,默认为当前的系统时间 |
random() | 产生一个0-1的随机浮点数(左闭右开) |
randint(a, b) | 产生一个[a, b]之间的随机整数 |
randrange(m, n, k) | 产生一个[m, n)之间步长为k的随机整数 |
uniform(a, b) | 产生一个[a, b]之间的随机小数 |
choice(seq) | 从序列中随机选择一个元素 |
shuffle(seq) | 将序列seq中元素随机排列,返回打乱后的序列 |
代码演示:
import random as a
# seed(x)初始化随机数种子
a.seed(12) # 初始化随机数种子
# 当随机数种子为一个固定的数时,其生成的随机数也是固定的
print(a.randint(1,10))
print(a.randint(1,10))
# 注意这里的固定并不是上面随机数的结果一致,而是多次运行之后的结果不变
# random()生成一个[0,1)的随机浮点数
print(a.random())
# randrange(m,n,k)生成一个[m,n)之间步长为k的随机数
# 在[1, 3, 5, 7, 9]这个序列之间随机选择一个整数。
print(a.randrange(1,10,2))
# uniform()生成一个[a,b]之间的随机小数
print(a.uniform(1,10))
# choice()从序列中随机选择一个元素
s = 'hello-python'
print(a.choice(s)) # 只要是序列就行
# shuffle()将序列中的元素随机排序,返回打乱后的序列
lst = ['hello','python','java','cpp']
# 注意字符串是不可变序列是不支持shuffle操作的,但列表是可变的
a.shuffle(lst)
print(lst)
运行结果:
注意:由于上述代码的随机数种子已经确定了,因此即使多次运行也还是同样的结果。如果想要不同的结果就需要不同的随机数种子,这就需要用到我们待会学习的时间戳。
time模块
time模块是Python中提供的用于处理时间的标准库,可以用来进行时间处理、时间格式化和计时等操作。接下来我们学习time模块中常用的函数:
函数名称 | 功能 |
time() | 获取当前的时间戳 |
localtime(sec) | 获取指定时间戳对应的本地时间的struct_time对象 |
ctime() | 获取当前时间戳对应的易读字符串 |
strftime() | 格式化时间,结果为字符串 |
strptime() | 提取字符串的时间,结果为struct_time对象 |
sleep(sec) | 休眠sec秒 |
除了常用的函数之外,还有一些配合其使用的"格式化字符串":
格式化字符串 | 日期/时间 | 取值范围 |
%Y | 年份 | 0001-9999 |
%m | 月份 | 01-12 |
%B | 月名 | January-December |
%d | 日期 | 01-31 |
%A | 星期 | Monday-Sunday |
%H | 小时(24h制) | 00-23 |
%I | 小时(12h制) | 01-12 |
%M | 分钟 | 00-59 |
%S | 秒 | 00-59 |
先解释一个概念,时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数。
代码演示:
import time as t
from select import select
# time()获取当前的时间戳
print(t.time())
# localtime(sec)获取指定时间戳对应的本地时间的struct_time对象
# 不传参,默认为当前的时间戳
struct_t = t.localtime()
# struct_t是一个对象,可以去查看其详细的属性
print(struct_t.tm_year) # 时间戳转换为本地时间对应年份
print(struct_t.tm_mon) # 月份
print(struct_t.tm_mday) # 天
print(struct_t.tm_hour) # 小时(24小时制)
print(struct_t.tm_min) # 分钟
print(struct_t.tm_sec) # 秒
print(struct_t.tm_wday) # 一周中的第几天(0代表周一,依次递增)
print(struct_t.tm_yday) # 一年中的第多少天(1-365/366)
# ctime()获取当前时间戳对应的易读字符串
# Thu Dec 19 21:46:43 2024
# 格式:星期几 几月 天 具体时间 年
# 同样不传参,默认为当前的时间戳
print(t.ctime())
# strftime()格式化时间,结果为字符串
# 不传参,默认为localtime获取的当前时间戳对应的struct_time对象
# 这里相当于直接把 tm_year等参数直接拿出来然后通过格式化的方式输出
s = t.strftime('%Y-%m-%d')
print(s)
# strptime()解析字符串所对应的时间,结果为struct_time对象
s_t = t.strptime(s,'%Y-%m-%d') # 格式不对,解析错误
print(s_t.tm_year,s_t.tm_mon,s_t.tm_mday)
print(s_t.tm_hour,s_t.tm_min,s_t.tm_sec) # 这些未初始化,即为0
# sleep(sec)休眠sec秒
print('休眠之前')
t.sleep(3)
print('休眠之后')
运行结果:
注意:当遇到一个我们不太熟悉的函数时,如果想要查看其的相关功能的话,可以摁住 ctrl,然后用鼠标点击,就会跳转到这个函数的详细页面中,就可以去看其详细使用说明了。
除了上述方法,还有以下几种方法:
1、使用 help 函数:
import time
help(time.localtime)
运行结果:
2、查看官方文档
3、 查看函数源代码:这个需要去查看 time.localtime 函数的源代码在Python 安装目录下的Lib/time.py 文件中。这种方式对于新手还是不推荐,我们先得学会怎么用才是好的。
datetime模块
与time模块相比,datetime模块可以更方便的显示日期并对日期进行计算。
类名 | 功能 |
datetime.datetime | 表示日期时间的类 |
datetime.timedelta | 表示时间间隔的类 |
datetime.date | 表示日期的类 |
datetime.time | 表示时间的类 |
datetime.tzinfo | 时区相关的类 |
注意:
1、这里不再是与操作相关的函数了,而是具体的类。
2、datetime 类确实是 date 类和 time 类的结合。date 类用于处理年、月、日信息;time 类用于处理时、分、秒和微秒信息。
代码演示:
datetime类的使用:
# datetime类包含了整个的时间(包括日期(年月日)+时间(时分秒))
from datetime import datetime # 导入datetime类
# now()获取当前的系统时间(整个时间)
dt = datetime.now()
print(dt)
# 手动调用构造方法实例化一个类
dt = datetime(2024,12,20) # 年月日必须要有
print(dt)
# 也可以拿到datetime的年月日这些参数
print(dt.year,dt.month,dt.day)
# datetime对象可以比较大小(对应的时间先后)
dt1 = datetime(2020,1,1)
dt2 = datetime(2024,1,1)
print('2020年1月1日 比 2024年1月1日 先到吗?',dt1<dt2) # 类似与数轴上的比较
# 格式化为字符串:将dt转换为 %Y-%m-%d 的格式
s = datetime.strftime(dt,'%Y-%m-%d')
print(s)
# 解析字符串:将字符串按照 %Y-%m-%d 的格式,转换为datetime对象
dt = datetime.strptime(s,'%Y-%m-%d') # 格式一定要正确
print(dt)
运行结果:
timedelta类的使用:
# timedelta类表示的是时间间隔(不包括年、月在内)
# 年存在闰年的情况,而月存在28-31天多种情况,不是固定的一种数,会导致计算的不准确
# 但是天就不存在上述情况了,35天就是35天
from datetime import datetime # 导入datetime类
from datetime import timedelta # 导入timedelta类
dt1 = datetime(2020,12,20)
dt2 = datetime(2024,12,20)
td = dt2 - dt1
print(type(td)) # 这是一个timedelta对象
print('2024年12月20日 与 2020年12月20日 相差',td)
# 手动创建一个timedelta对象(时间间隔)
# 默认参数从左到右为:天、秒、微妙、毫秒、分钟、小时、周
td = timedelta(100) # 参数为day
print(td)
运行结果:
好啦!本期 初始Python篇(13)—— 模块以及Python中常用的内置模块 的学习之旅就到此结束啦!我们下一期再一起学习吧!