Python学习笔记
课程笔记参考B站视频: Python全栈开发教程。
第十四站 百宝箱
本章介绍模块。
1. 什么叫模块
模块(Modules) 是比函数范围更广一层的概念,一个模块中可以包含多个函数、类、语句。在Python中一个扩展名为.py的文件就是一个模块。使用模块的好处有:
- 方便其它程序和脚本的导入并使用。
- 避免函数名和变量名冲突。
- 提高代码的可维护性。
- 提高代码的可重用性。
下图给出了这些概念囊括类型(注意一个Python程序可以包含多个包):
2. 自定义模块
创建模块的步骤就是 新建一个.py文件,注意名称尽量不要与Python自带的标准模块名称相同。导入模块的标准语法格式有以下两种:
'''方法一:导入整个模块'''
import 模块名称 [as别名]
'''方法二:导入模块的某个函数/变量/类'''
from 模块名称 import 函数/变量/类 [as 别名]
下面是导入整个模块的代码示例:
'''math是关于数学计算的一个模块'''
import math
print(id(math), type(math), math)
print(dir(math))
print('---------调用math中的变量、函数等----------')
print(math.pi)
print(math.ceil(9.98))
- 运行结果
2740922946160 <class 'module'> <module 'math' (built-in)>
['__doc__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh',
'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'comb', 'copysign', 'cos', 'cosh',
'degrees', 'dist', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor',
'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite',
'isinf', 'isnan', 'isqrt', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf',
'nan', 'perm', 'pi', 'pow', 'prod', 'radians', 'remainder', 'sin', 'sinh', 'sqrt',
'tan', 'tanh', 'tau', 'trunc']
---------调用math中的变量、函数等----------
3.141592653589793
10
注:上述目录为手动换行。
下面是从模块中导入单个函数/变量/类的代码示例:
from math import pi
print(type(pi), pi)
print(math.pow(2,3))
- 运行结果
<class 'float'> 3.141592653589793
8.0
注意单独导入的函数/变量等就不需要再加math.
了。
下面演示如何自定义模块:
- Pycharm中创建Python Package包文件夹,右键–>标记目录为–>Source Root。
- 在该包文件中创建Python文件calc.py,写入以下代码:
def add(a, b):
return a+b
def mul(a, b):
return a*b
- 新建一个文件。即可使用这个包中的模块:
import calc
print(calc.add(1.0, 2))
print(calc.mul(3, 1.2))
- 运行结果为:
3.0
3.5999999999999996
3. 以主程序的形式执行
在每个模块的定义中都包括一个记录模块名称的变量_ _name_ _
,程序可以检查该变量,以确定他们在哪个模块中执行。如果一个模块不是被导入到其它程序中执行,那么它可能在解释器的顶级模块中执行。顶级模块的_ _name_ _
变量的值为_ _main_ _
。
上面这段翻译成人话就是,如果我在定义模块的文件中,也写了一些输出的语句,那么我在其他文件中调用这个模块时,会首先执行完模块中的输出语句,然后再执行其他的文件语句。这肯定不行啊,于是可以在定义模块的时候给所有的语句都加上下面这句限制条件:
if __name__ == '__main__':
含义就是只有当这个模块作为main文件的时候,才会运行if块里面的语句,否则不会运行,于是称之为“以主程序形式运行”。
下面是代码示例:
- 模块文件:
def add(a, b):
return a+b
def mul(a, b):
return a*b
if __name__ == '__main__':
print(add(10, 20))
print(mul(10, 20))
- 主文件:
import calc
print(calc.add(1.0, 2))
- 运行结果1(加上以主程序运行的判定条件)
3.0
- 运行结果2(不加判定条件)
30
200
3.0
4. python中的包
Python中的 包(Package) 是一个分层次的目录结构,它将一组功能相近的模块组织在一个目录下。作用是规范代码、避免模块名称冲突。与包相似的概念是 目录(Directory),它们的区别是:
- 包含
_ _init_ .py
文件的目录称为包。- 目录里通常不包含
_ _init_ _.py
文件。注:只要在目录中创建一个
_ _main_ _.py
文件,那么这个目录就立刻转换成包。
包的导入语法如下
import 包名.模块名 [as 别名]
from 包名 import 模块名 [as 别名]
最后切记:
- 使用import…方式进行导入时,只能跟包名或模块名。
- 使用from…import…可以导入包,模块,函数,变量。
下面是Python自带的一些常用的模块:
模块名 | 描述 |
---|---|
sys | 与Python解释器及其环境操作相关的标准库 |
time | 提供与时间相关的各种函数的标准库 |
os | 提供了访问操作系统服务功能的标准库 |
calendar | 提供与日期相关的各种函数的标准库 |
urllib(包) | 用于读取来自网上(服务器)的数据标准库 |
json | 用于使用JSON序列化和反序列化对象 |
re | 用于在字符串中执行正则表达式匹配和替换 |
math | 提供标准算术运算函数的标准库 |
decimal | 用于进行精确控制运算精度、有效数位和四舍五入操作的十进制运算 |
logging | 提供了灵活的记录事件、错误、警告和调试信息等目志信息的功能 |
以上模块导入后都可以直接点开查看具体的函数有哪些。
下面是代码示例:
import sys
import time
import urllib.request
print('-----获取存储变量的内存大小(单位:字节)-----')
help(sys.getsizeof)
print(sys.getsizeof(12))
print(sys.getsizeof(23.6))
print(sys.getsizeof(True))
print(sys.getsizeof('嗯'))
print('-----使用time模块中的一些函数-----')
help(time.time)
print(time.time()) # 输出距离1970-01-01 00:00:00 UTC(Epoch)过去的秒数
print(time.localtime(time.time()))# 转换成年月日等时间
print('-----使用urllib包中的一些函数-----')
print(urllib.request.urlopen('http://baidu.com').read()) #.read()表示读取
# 哔哩哔哩要用post请求,而不是requests
- 运行结果
-----获取存储变量的内存大小(单位:字节)-----
Help on built-in function getsizeof in module sys:
getsizeof(...)
getsizeof(object [, default]) -> int
Return the size of object in bytes.
28
24
28
76
-----使用time模块中的一些函数-----
Help on built-in function time in module time:
time(...)
time() -> floating point number
Return the current time in seconds since the Epoch.
Fractions of a second may be present if the system clock provides them.
1657612783.7382038
time.struct_time(tm_year=2022, tm_mon=7, tm_mday=12, tm_hour=15, tm_min=59, tm_sec=43, tm_wday=1, tm_yday=193, tm_isdst=0)
-----使用urllib包中的一些函数-----
b'<html>\n<meta http-equiv="refresh" content="0;url=http://www.baidu.com/">\n</html>\n'
5. 第三方模块的安装及使用
Python很强大,很大程度上也是因为第三方模块丰富多样。下面是第三方模块的安装语法(在线安装,最常用):
pip install 模块名
下面是安装schedule
模块,这个模块主要用于计划:
- 配置环境变量:“我的电脑→属性→高级系统设置→环境变量→点击系统变量Path→编辑→新建→浏览放入python目录下的Scripts”。
- win+r输入cmd,然后输入
pip install schedule
即可。 - 若不想用windows命令行(也有可能在windoiws命令行安装完成后,依旧不能导入模块),直接在Pycharm最下面的终端(Terminal)安装即可。
安装完成后,第三方模块的使用语法如下:
import 模块名
下面是代码示例:
import schedule
import time
def job():
print('哈哈哈...')
schedule.every(3).seconds.do(job)# 每3秒执行一次函数job
while 1:
schedule.run_pending() # 开始执行
time.sleep(1) # 休眠1秒
于是程序便可以每个3秒输出1次,然后休眠1秒,循环不止。
6. 本章作业
1. 模拟高铁售票系统
下面是代码示例:
import prettytable as pt
# 显示座席
def show_seat(row_num):
table1 = pt.PrettyTable()
# 定义标题
table1.field_names = ['行号', '座位1', '座位2', '座位3', '座位4', '座位5']
# 定义每一行
for i in range(row_num):
lst = [f'第{i+1}行', '有票', '有票', '有票', '有票', '有票']
table1.add_row(lst)
# 打印表格
print(table1)
def order_ticket(row_num, row, column):
tb = pt.PrettyTable()
tb.field_names = ['行号', '座位1', '座位2', '座位3', '座位4', '座位5']
for i in range (row_num):
if int(row)==i+1:
lst = [f'第{i + 1}行', '有票', '有票', '有票', '有票', '有票']
lst[int (column)] = '已售'
tb. add_row(lst)
else:
lst = [f'第{i + 1}行', '有票', '有票', '有票', '有票', '有票']
tb.add_row(lst)
print(tb)
if __name__ in '__main__':
row_num = 13
show_seat(row_num)
order_ticket(row_num, 1, 1)
- 运行结果
+--------+-------+-------+-------+-------+-------+
| 行号 | 座位1 | 座位2 | 座位3 | 座位4 | 座位5 |
+--------+-------+-------+-------+-------+-------+
| 第1行 | 有票 | 有票 | 有票 | 有票 | 有票 |
| 第2行 | 有票 | 有票 | 有票 | 有票 | 有票 |
| 第3行 | 有票 | 有票 | 有票 | 有票 | 有票 |
| 第4行 | 有票 | 有票 | 有票 | 有票 | 有票 |
| 第5行 | 有票 | 有票 | 有票 | 有票 | 有票 |
| 第6行 | 有票 | 有票 | 有票 | 有票 | 有票 |
| 第7行 | 有票 | 有票 | 有票 | 有票 | 有票 |
| 第8行 | 有票 | 有票 | 有票 | 有票 | 有票 |
| 第9行 | 有票 | 有票 | 有票 | 有票 | 有票 |
| 第10行 | 有票 | 有票 | 有票 | 有票 | 有票 |
| 第11行 | 有票 | 有票 | 有票 | 有票 | 有票 |
| 第12行 | 有票 | 有票 | 有票 | 有票 | 有票 |
| 第13行 | 有票 | 有票 | 有票 | 有票 | 有票 |
+--------+-------+-------+-------+-------+-------+
+--------+-------+-------+-------+-------+-------+
| 行号 | 座位1 | 座位2 | 座位3 | 座位4 | 座位5 |
+--------+-------+-------+-------+-------+-------+
| 第1行 | 已售 | 有票 | 有票 | 有票 | 有票 |
| 第2行 | 有票 | 有票 | 有票 | 有票 | 有票 |
| 第3行 | 有票 | 有票 | 有票 | 有票 | 有票 |
| 第4行 | 有票 | 有票 | 有票 | 有票 | 有票 |
| 第5行 | 有票 | 有票 | 有票 | 有票 | 有票 |
| 第6行 | 有票 | 有票 | 有票 | 有票 | 有票 |
| 第7行 | 有票 | 有票 | 有票 | 有票 | 有票 |
| 第8行 | 有票 | 有票 | 有票 | 有票 | 有票 |
| 第9行 | 有票 | 有票 | 有票 | 有票 | 有票 |
| 第10行 | 有票 | 有票 | 有票 | 有票 | 有票 |
| 第11行 | 有票 | 有票 | 有票 | 有票 | 有票 |
| 第12行 | 有票 | 有票 | 有票 | 有票 | 有票 |
| 第13行 | 有票 | 有票 | 有票 | 有票 | 有票 |
+--------+-------+-------+-------+-------+-------+
评论:我只想说这个程序很智障,只能定一次票。由于我在PrettyTable里面反复的查找,也没有看到直接获取某个元素的函数,只能说这个模块只能用于美化显示,而不是对元素进行修改等操作。理想的情况应该是将所有作为存成一个二维列表,所有的中间处理过程都在列表完成,只有最后显示的时候才使用PrettyTable。
思来想去,虽然骂爽了,但是自己不写点什么好像也说不过去,于是下面是代码示例:
import prettytable as pt
# 显示座席
def show_seat(seat_lst):
table1 = pt.PrettyTable()
# 定义标题
table1.field_names = ['行号', '座位1', '座位2', '座位3', '座位4', '座位5']
# 定义每一行
for index,value in enumerate(seat_lst):
lst = [f'第{index+1}行']
lst.extend(value)
table1.add_row(lst)
# 打印表格
print(table1)
# 初始化座位列表
def ini_seat(row_num):
lst = []
for i in range(row_num):
lst.append(['有票', '有票', '有票', '有票', '有票'])
return lst
# 订票
def order_seat(seat_lst, row, column):
if seat_lst[row-1][column-1] == '已售':
print('对不起,这个座位已售出!')
else:
seat_lst[row - 1][column - 1] = '已售'
return seat_lst
if __name__ in '__main__':
row_num = 13
lst_seat = ini_seat(row_num)
show_seat(lst_seat)
while True:
position = input('请输入座位的行列(如:13,1):')
posi_lst = position.split(',')
row = int(posi_lst[0])
col = int(posi_lst[1])
lst_seat = order_seat(lst_seat, row, col)
con_judge = input('是否继续订票?y/n ')
while con_judge!='n' and con_judge!='N' and con_judge!='y' and con_judge!='Y':
con_judge = input('输入错误!是否继续订票?y/n ')
show_seat(lst_seat)
if con_judge=='Y' or con_judge=='y':
continue
else:
print('感谢您的使用!')
break
2. 推算今年几天后的日期
下面是代码示例:
import datetime
def inputdate():
indate = input('请输入开始日期(如:20220707)后按回车:')
indate = indate.strip() # 去掉前后的空格
datestr = indate[0:4] + '-' + indate[4:6] + '-' + indate[6:]
return datetime.datetime.strptime(datestr,'%Y-%m-%d')
if __name__ == '__main__':
print('推算几天后的日期'.center(30,'-'))
sdate = inputdate()
in_num = int(input('请输入间隔的天数:'))
fdate = sdate + datetime.timedelta(days=in_num)
print('推算的日期是:' + str(fdate).split(' ')[0])
- 运行结果
-----------推算几天后的日期-----------
请输入开始日期(如:20220707)后按回车:20220701
请输入间隔的天数:-1
推算的日期是:2022-06-30