文章目录
- 计算机基础
- 一、计算工具与计算思维
- 二、开启python之旅(I)
- 三、开启python之旅(II)
- 四、开启python之旅(III)
- 五、信息表示与编码——0与1的故事
- 六、计算机系统的程序员视角
- 七、网络知多少
- 八、数据库探秘
计算机基础
作者:xingzhe
笔名:浮生渡己
一、计算工具与计算思维
1.1、计算工具的历史

1.2、计算思维的概述
-
计算思维的特性:
- 概念化,不是程序化 。
- 基础的,不是机械的技能 。
- 人的,不是计算机的思维 。
-
能力目标:
- 从现实问题中抽取必要的细节。
- 以计算机能理解的方式描述问题。
- 自动化地实施问题求解的过程。
-
计算思维的表达体系
-
计算思维的本质
- 抽象
- 自动化
1.3、计算的自动化
1.3.1、从算盘开始
-
完成计算的关键环节
- 意识记录下参与运算的数 。
- 二是应用完成计算的规则 。
-
起源于中国,迄今为止已有2600的历史,是中国古代的一项重要发明。
-
算盘是一种手动工具。
1.3.2、帕斯卡加法器
1.3.3、“可编程”的织布机和八音盒
-
巴贝奇“自动计算”的思想(程序控制和可编程的思想雏形)
- 必须把计算步骤和原始数据预先地存在机器内。
- 计算机能取出这些数据,在必要时能做一些简单的判断,决定自己下一步的计算顺序 。
-
巴贝奇的分析机
-
“计算程序化”的思想
- 为分析机“编织”计算的方式同杰卡德为织布机编织图案的方式完全一样。
1.3.4、“自动化”思想的内涵
- 计算过程的关键要素:
- 原始的数据。
- 求解问题的计算步骤。
- 计算自动化本质:计算工具能够按照预先设定的计算步骤,去处理相关的数据,从而得到预期的结果。
- 算法:求解问题的计算步骤或方法。
- 程序:用计算机可以理解的语言来描述算法。
- 计算思维的能力目标:
- 从实现问题中抽取必要的细节。
- 以计算机能够理解的方式描述问题。
- 自动化的实施问题求解的过程 。
1.4、计算的抽象
1.4.1什么是抽象
-
抽象:
- 忽略一个主题中与当前问题(或目标)无关的那些放面,以便更充分地注意与当前问题(或目标)有关的方面。
- 一种从个体把握一般、从现象把握本质的认知过程和思维方法。
-
抽象过程的准心:
- 问题本身
- 要达成的目标
-
“抽象”认知的过程:
-
图灵机的结构:
-
一条两头可无限延伸的纸带
- 纸带被划分为一个个的小方格。
- 方格中可包含有限非空符号集中的任意符号,也可以为空。
-
一个读写头
- 向左或向右移到相邻方格。
- 读或写。
-
一个控制器
-
状态转移规则
-
状态转移规则的四个要素:
- 当前状态
- 读写头读到的当前符号
- 读写头要完成的操作
- 要进入的下一状态
-
1.4.3、计算的本质
-
-
从一个符号串f变换成另一个符号串g的过程
-
“通用性”的两成含义
- 处理数据的多样性
- 处理程序的多样性
-
计算思维的核心
- 从现实问题中抽取必要的细节
- 以计算机能理解的方式描述问题
- 自动化的实施问题求解的过程
1.5、小结
二、开启python之旅(I)
2.1、python
2.1.1环境的创建
- Anaconda的安装和使用
- 下载安装文件:Anaconda
- 安装:安装路径不要包含空格或中文
- 启动 Spyder:可以将Spyder图标固定到任务栏
- EduCoder在线实践课程的使用:EduCoder
2.2、绘制炸弹轨迹(I)
2.2.1、“绘制炸弹轨迹”问题
某轰炸机在h=3km的高空以v0 =200m/s的速度水平匀速飞行,到达A点是将投下一枚无动力炸弹,建立如下坐标系,不考虑空气阻力,求绘制炸弹轨迹。(g=9.8m/s2)

- 设经过时间t后炸弹坐标为(xt,yt)
x t = v 0 t y t = h − 1 2 g t 2 x_t=v_0t\\ y_t=h-\frac{1}{2}gt^2 xt=v0tyt=h−21gt2
2.2.2、计算第3.5秒时的炸弹纵坐标
-
print函数:打印括号中的内容
print("hello world") #打印字符串(直接打印字符串内容) print("1+1")#结果为1+1 #打印表达式(先计算值在进行打印) print(1+1)#结果为2 #表示注释,解释代码功能的作用,不会被执行
-
字符串:引号中的内容
-
表达式中常用的运算符:加:+;减:-;乘:*;除:/;乘方:**
2.2.3、计算第3.5秒时的炸弹坐标
-
赋值:将具体的某个值赋给自定义的变量
pi=3.14 #程序执行过程是从右往左
- 变量命名的具体规则
- 可包含大(小)写字母、数字、下划线,但不能以数字开头
- 区分大小写
- 一般不使用python已用的名字
print("你的名字是:",name) #打印"你的名字是:"和变量name的值(即从键盘上输入的姓名)
2.2.4、计算某时刻炸弹的坐标
-
input函数:从键盘读入一个字符串
name = input("请输入你的姓名:") #打印提示文字"请输入你的姓名:";读入键盘上输入的字符串;将字符串赋值给变量name
-
type函数:查看类型
type('18') str type(18) int type(3.14) float
-
数据类型的转换
1.str函数:转换成字符串 2.int函数:转换成整型 3.float函数:转换成浮点型 4.eval函数:对字符串表达式进行计算
2.2.5、绘制一个坐标点
-
python库的使用
-
确定要使用的库
-
在程序中导入库(可能需要安装)
import math#导入math库 import math as m #导入math库并取名为m from math import cos,pi #导入math库中的cos,pi两个模块 from math import * #导入math库中的所有对象
-
使用库中的功能
import matplotlib.pyplot as plt #导入库 h,V0,g = 3000,200,9.8 #设置参数 t = eval(input('t=')) #读取时刻t xt = V0*t #计算横坐标 yt = h-1/2*g*t**2 #计算纵坐标 plt.plot(xt,yt,'ro') #绘制坐标点(xt,yt) plt.grid('on') #显示网格线 plt.axis([0,5000,0,h]) #设置坐标轴范围 plt.show() #显示图像
-
2.2.6、办公软件的应用——搜索与文档“四步走”
-
“四步走”攻略之搜索
- 工具
- 技巧
- 主题明确
- 主题模糊
- 辅助关键字
-
“四步走”攻略之整理、精炼
- 大纲
- 撰写文稿
-
“四步走”攻略之排版
- 字体格式、段落格式、项目符号、特殊版式、段落边框
- 插入图片、插入表格、插入图表、其它元素
###### 2.2.6、摩尔定律与超级计算机
-
电子计算机的分代:根据构成计算机的电子元器件
- 第一代:电子管计算机(ENIAC)
- 第二代:晶体管计算机(TRADIC、7090)
- 第三代:集成电路(System360)
- 第四代:大规模和超大规模集成电路
-
摩尔定律
- 在价格不变的时候,击集成电路上可容纳的晶体管数目约每隔18个月就会增加一倍
- 微处理器的性能每隔18个月提高一倍而价格相对的就下降了一半
- 每一个月能够买到的计算机性能每隔18个月翻一番
-
千倍定律:高性能计算机的峰值性能每隔10年提升约1000倍(1P=1015,1E=1018)
-
超级计算机:具有和高的计算速度,能完成个人计算机和服务器不能完成的大型任务的计算机
三、开启python之旅(II)
2.3、绘制炸弹轨迹(II)
2.3.1、if-else分支符和流程图
-
缩进:若干(一般为4)个空格或/和制表符(Tab键)
-
在连续语句前添加一个相同的缩进可以形成一个语句块
-
如条件表达式成立则执行语句块1,否则执行语句块2
if 条件表达式: 语句块1 else: 语句块2
例:
x=eval(input("x=")) if x<0: a=-x else: a=x print('|x|=',a)
2.2.2、调试功能
- 跟踪程序执行过程,也能更好的理解程序的执行过程,方便发现代码可能出现的问题
- if条件表达式
- 计算结果是一个布尔类型(bool)得值
- 要么是true(真),表示条件成立
- 要么是false(假),表示条件不成立
- 计算结果是一个布尔类型(bool)得值
- 条件表达式(比较)
- 大于:>
- 小于:<
- 大于等于:>=
- 小于等于:<=
- 等于:==
- 不等于:!=
- 条件的复合
- 与(而且):and
- 或:or
- 非(不是):not
2.3.3、在合理范围绘制一个坐标
import matplotlib.pyplot as plt #导入库
h,V0,g = 3000,200,9.8 #设置参数
tmax = (2*h/g)**0.5
t = eval(input('t=')) #读取时刻t
if t<0 or t>tmax:
print('输入错误')
else:
xt = V0*t #计算横坐标
yt = h-1/2*g*t**2 #计算纵坐标
plt.plot(xt,yt,'ro') #绘制坐标点(xt,yt)
plt.grid('on') #显示网格线
plt.axis([0,5000,0,h]) #设置坐标轴范围
plt.show() #显示图像
2.2.4、while循环
-
重复执行语句块,直到条件表达式不成立
while 条件表达式: 语句块1
-
需要注意的地方
- 循环体的范围:需要重复执行的语句才被放入循环体
- 变化量:注意检查某些变量在循环体中的变化是否与预期相符
- 第一次执行:注意检查循环体第一次执行是否和预期相符
- 最后一次执行:注意检查循环最后一次执行是否与预期相符
2.2.5、绘制n个坐标点
-
两种结构
- 分支:if-else
- 循环:while
-
任何算符都可以用顺序、分支、循环三种结构来描述
-
两种工具:流程图、调试
import matplotlib.pyplot as plt #导入库 h,V0,g = 3000,200,9.8 #设置参数 tmax = (2*h/g)**0.5 delta = tmax/(n-1) while t<=tmax: xt = V0*t #计算横坐标 yt = h-1/2*g*t**2 #计算纵坐标 plt.plot(xt,yt,'ro') #绘制坐标点(xt,yt) t=t+delta #可简写为t+=delta plt.grid('on') #显示网格线 plt.axis([0,5000,0,h]) #设置坐标轴范围 plt.show() #显示图像
2.4、绘制炸弹轨迹(III)
2.4.1、列表(list)
-
包含若干元素
-
元素是按序编号的(从0开始)
-
利用编号可以对元素进行增删改查等操作
-
创建列表
L = [a,b,c,d] #用方括号括起来,元素之间用逗号隔开
-
range():生成类似等差数列的整数序列
range(a,b,c) #[a,b)左闭右开,c为公差 range(a,b) #[a,b) 公差为1 range(b) #[0,b) 公差为1
-
2.4.2、列表的查询与更新
-
读取元素
x = L[i] #读取的i号元素 x = L[i:j] #读取第[i:j)号元素 #i、j可为负数
-
修改元素
L[i] = x #修改第i号元素 L[i:j] = x #修改第[i:j)号元素 #i、j可为负数
-
添加元素
L.insert(i,x) #将x添加到L的第i出 L.append(x) #将x添加到L的尾部
-
删除元素
L.pop(i) #删除L的第i号元素 L.pop() #删除L最后一个元素
2.4.3、其他列表的操作
L.index(x) #返回L中首个x的编号
L.remove(x) #删除L中首个元素x
L.count(x) #返回L中x出现的次数
x in L #判断x是否是L中的元素
L.reverse() #升序排列
L.sort() #降序排列
L1 + L2 #将L1和L2拼接起来
L * n #将n个L拼接起来
len(L) #返回L的长度(元素的个数)
max(L)、min(L) #返回L中最大、最小的元素
sum(L) #返回L中所有元素之和
2.4.4、for循环
-
语法
-
X为变量,L为列表(或一些其他的值)
-
将L中的元素依次取出赋给X,没取一个元素,执行一次循环体
for X in L : 语句1
-
-
while循环和for循环
- for循环一般用于循环次数可以提前确定的情况
- while循环一般用于循环次数难以体检确定的情况
2.4.5、绘制一条轨迹
-
列表:包含若干元素,元素按序标号
L=[]、L = list(range()) #创建列表 X = L[] #读取元素 L[] = X #修改元素 L.insert(i,X)、L.append(X) #添加元素 L.pop(i)、L.pop() #删除元素
-
for循环
for X in L、for X in range()
import matplotlib.pyplot as plt #导入库 h,V0,g = 3000,200,9.8 #设置参数 tmax = (2*h/g)**0.5 delta = tmax/(n-1) xt,yt = [ ],[ ] #while循环 #while t<=tmax: # xt.append(V0*t) #计算横坐标 # yt.append(h-1/2*g*t**2)#计算纵坐标 # t=t+delta #可简写为t+=delta #forx #for i in range(n): # t = delta*i # xt.append(V0*t) #计算横坐标 # yt.append(h-1/2*g*t**2)#计算纵坐标 plt.plot(xt,yt,'r-') #绘制坐标点(xt,yt) plt.grid('on') #显示网格线 plt.axis([0,5000,0,h]) #设置坐标轴范围 plt.show() #显示图像
2.4.6、微机组装
-
台式计算机的组成:显示器、主机、鼠标、键盘
-
硬盘
-
内存条
-
CPU(中央处理器)
-
主板
-
常用的维修方法
- 维修思路
- 定位故障、逐步缩小
- 善用搜索引擎
- 维修方法
- 插板法:计算机部件接插在主板上或通过线缆进行连接,会出现松动、氧化等原因造成接触不良的可能
- 变换法:计算机部件一般使用标准接口硬件,比如内存条、硬盘、光驱等,通过使用完好的部件更换可疑的部件,进行故障判断
- 最小系统法:构建能够启动计算机的最小系统(主板、CPU、电源),然后逐步添加硬件部件,排查可能的故障部件
- 维修思路
四、开启python之旅(III)
2.5绘制炸弹轨迹Ⅳ
2.5.1、利用for循环创建列表
-
将序列中的每个元素X分别带入表达式,得到列表L
L = [包含X的表达式 for X in 序列]#序列可为列表、range()……
-
更简单的绘制一条轨迹(方法I)
import matplotlib.pyplot as plt #导入库 h,V0,g = 3000,200,9.8 #设置参数 tmax = (2*h/g)**0.5 delta = tmax/(n-1) T = [i*delta for i in range(n)] xt = [v0*t for t in T] yt = [h-1/2*g*t**2 for t in T] plt.plot(xt,yt,'r-') #绘制坐标点(xt,yt) plt.grid('on') #显示网格线 plt.axis([0,5000,0,h]) #设置坐标轴范围 plt.show() #显示图像
2.5.2、numpy数组
-
arange函数:用法、功能与range()函数类似,也可以生成等差数列,但不局限于整个数列
-
linspace函数:
- linspace(i,j,n):将闭区间[i,j]尽量均分为n-1份,返回n个端点形成序列
-
数组(Array)
-
arange()和linspace()返回的不是列表,而是numpy中的数组
-
numpy库中的数组能直接参与多种运算,而列表能参与的运算十分有限
#A,B是numpy库中的数组,c是一个数 A*B#对应元素相乘 A*c#个元素分别乘以c A**c#求个元素的c次方 A//c#求个元素整除c的商 A%c#求个元素整除c的余数 np.sqrt(A)#求个元素的平方根 ...
-
2.5.3、更简单的绘制一条轨迹
import matplotlib.pyplot as plt #导入库
h,V0,g = 3000,200,9.8 #设置参数
tmax = (2*h/g)**0.5
t = np.linspace(0,tmax)
xt = V0*t #计算横坐标
yt = h-1/2*g*t**2 #计算纵坐标
plt.grid('on') #显示网格线
plt.axis([0,5000,0,h]) #设置坐标轴范围
plt.show() #显示图像
2.6、绘制炸弹轨迹Ⅴ
2.6.1、定义函数
-
函数:一种代码复用技术
注:1、函数一般用来处理同类问题,而不是处理某一个特定问题;
2、任以默认值参数右边不能再出现非默认值参数
#函数被调用后才会被执行,被调用几次函数就执行几次 def 函数名 (a,b): 语句块1
-
参数:在函数体内的使用方法与变量相同
-
参数传递:调用函数时将具体值赋给参数
-
返回值:return将调用的代码替换成返回值,执行到函数时函数体就停止
2.6.2、绘制多条轨迹
import numpy as np
import matplotlib.pyplot as plt #导入库
def calBombTrace(h,v0):
g = 9.8
tmax = (2*h/g)**0.5
t = np.linspace(0,tmax)
xt = v0*t
yt = h-1/2*g*t**2
return xt,yt
H = [3000,2000]
v0 = [200,260]
for h in H:
for v0 in V0:
xt,yt = calBombTrace(h,v0)
plt.plot(xt,yt)
plt.grid('on') #显示网格线
plt.axis([0,5000,0,h]) #设置坐标轴范围
plt.show() #显示图像
2.6.4、思路的演示——四步走战略
-
“四不走”攻略之内容梳理
- 理清逻辑思路——思维导图来帮忙
- 确定应用场景——演示、演讲、阅读
-
“四步走”攻略之完成初稿
- 熟悉“套路”——封面、目录、提示页、内容、封底
- 搭建框架——套用版式
-
“四步走”攻略之整洁提升
- 修饰文本、图文搭配、图标制作、SmartArt、动画设置
-
“四步走”攻略之精华设计
2.6.3、小结

五、信息表示与编码——0与1的故事
3.1、什么时信息
3.1.0、计算机需要表示数据
-
计算机里需要表示各类数据:数字符号、推理符号、语言符号、声音图像
-
信息论的创始人
-
信息的定义:
-
客观存在的表现形式
-
事物复杂性和差异的反映
-
-
信息的复杂性
-
信息具体表现形式的多样性
-
信息的分类标准不一
-
信息的数学理论:信息是事物运动状态或存在方式的不确定性的描述
-
信息的多少:事物不确定性的描述能够有效的表达和衡量信息的多少
-
信息量计算公式(H:信息熵;单位:bit)
- 信息和长度,重量这些物理属性一样,也可以测量和规范
- 信息定量公式的解析
- p(xi)表示消息xi发生的概率
- -log2p(xi)表示信息xi所包含的信息量
- 事件的不确定程度可以用其出现的**概率
- 消息出现的概率越小,包含的信息量越大,反之信息量越小
- 每个消息的信息量乘上它发生的概率后再求总和,得到的是从一个信息源发出的各个消息所包含的平均信息量或H是所有信息的平均不确定性
- 确定性为100%时的熵:
- n=1,即1种可能性
- p(xi)=1,即确定性100%
- H=log2(1)=0,即信息量为零
H = − ∑ i = 1 n p ( x i ) l o g 2 p ( x i ) I = − l o g 2 p ( x i ) 当 p ( x i ) > 0 时, I = ∞ 当 p ( x i ) < 0 时, I = 0 H = -\sum\limits_{i=1}^np(x_i)log_2p(x_i)\\ I=-log_2p(x_i)\\ 当p(x_i)>0时,I=\infin\\ 当p(x_i)<0时,I=0\\ H=−i=1∑np(xi)log2p(xi)I=−log2p(xi)当p(xi)>0时,I=∞当p(xi)<0时,I=0
-
编码的概念
- 一切信息源发出的信息或者信号的可以用0和1的组合来描述
- 信息从一种形式转换为另一种形式的过程,成为编码
- 具体需要用多少个0或1来编码取决于信息熵的大小
-
3.2、为什么只有0和1
- 计算的本质:从一个0/1字符串到另一个0/1字符串的变换
3.2.1如何表示一个数
- 进制:进位计算制的简称,一般用于刻画数量之间的数量关系,是人们在长期实践中发现和发明的
3.2.2、十进制与二进制的抉择
- 十进制
- 逢十进一
- 十进制的基数
- R进制
- 逢R进一
- 十进制与二进制
- 任何一个数都可以用不同的进位制表示
- 任何一个进制都可以通过按权展开的方式转换成十进制
- 十进制与二进制的抉择
- 二进制33位的表示最大可以表示10的10次方量级的数,采用二进制会比十进制的系统要经济的多
3.2.3、计算的通用性
- 计算机为什么采用0/1编码来表示信息
- 基于二进制的运算规则简单,简化设计
- 与要实现的物理状态单一 ,系统可靠性和稳定性提高
- 适合实现逻辑运算,通用性强
3.3、算术运算与逻辑运算
3.3.0、算术运算与逻辑运算
-
任何运算过程都可以拆解为算术运算和逻辑运算
3.3.1、算术运算
-
二进制运算规则
3.3.2、逻辑运算
-
逻辑运算又称为布尔运算
-
运算的结果为布尔值
-
延伸出的一系列逻辑理论被称为布尔代数
-
基于0/1的逻辑运算
-
逻辑量的取值0或1
-
与或非三种逻辑运算的真值表
-
异或运算(XOR)
- 逻辑规则:相同为假,不同为真
- 等价表达式: a ⨁ b = ( ¬ a ∧ b ) ∨ ( a ∧ ¬ b ) a\bigoplus b=\ (\lnot a \land b)\lor (a\land\lnot b) a⨁b= (¬a∧b)∨(a∧¬b)
-
逻辑运算丰富了程序结构
-
3.3.3、位运算
-
数字电路
-
数字电路是现代计算机的重要基石,它利用硬件在物理上实现了对0/1字符串的表示,处理和存储
-
数字电路的基本原理,通过晶体管搭建不同功能的逻辑门来实现对0/1字符串中的每一位布尔运算
-
一切计算的本质都是0与1之间的“与”,“或”,“非”
-
-
位运算规则
- 对于给定的两个等长的0/1字符串,从左到右安位对齐,注意对每一位进行布尔运算(“与”,“或”,““非””)
- 对于单个定长的0/1字符串,根据应用的需求施加位运算(“非”,“左移位”,“右移位”)
3.4、进制转换
3.4.1、十进制与二进制之间的转换
- R进制转换为十进制的通式
a R = ( a n − 1 . . . a 0 a − 1 a − 2 . . . a − m ) R = a n − 1 ∗ R n − 1 + . . . + a 1 ∗ R 1 + a 0 ∗ R 0 + a − 1 ∗ R − 1 + . . . + a − m ∗ R − m a_R=(a_{n-1}...a_0a_{-1}a_{-2}...a_{-m})_R\\=a_{n-1}*R^{n-1}+...+a_1*R^1+a_0*R^0+a_{-1}*R^{-1}+...+a_{-m}*R^{-m} aR=(an−1...a0a−1a−2...a−m)R=an−1∗Rn−1+...+a1∗R1+a0∗R0+a−1∗R−1+...+a−m∗R−m
- 十进制转换为二进制的表示
- 整数部分:除2取余法(余数法),即整数除以2之后留取余数作为结果 (自下而上)
- 小数部分:乘2取整法(进位法),即小数乘以2之后留取整数部分作为结果(自上而下)
3.4.2、利用python实现“除二取余”
-
算法的输入和输出
- 0到多个输入量
- 1到多个输出量
-
算法包含一系列(用顺序、分支、循环结构进行组织)的步骤
- 有限个步骤
- 每个步骤都是可行的
- 每个步骤都是明确的
-
创建字符串
-
用单引号、双引号、三引号(三个单引号’''或三个双引号"“”)
-
s=input()
、s=src(3.14)
…… -
可以理解为列表,所含元素为单个字符
-
与列表类似的操作
x=s[i]、x=s[i:j]#提取子串 a=len(s)#求字符串长度 a=s.index(x)#求子串首次出现的位置 a=s.count(x)#求子串出现的次数 s=s1+s2#字符串拼接 s=s1*n#将s1拼接n次 x in s#判断是否包含字串x for x in s#对x中的每个字符s ......
-
专门的操作
a = s.startseith(x)#判断s是否以x开头 a = s.endswith(x)#判断s是否以x结尾 a = s.upper()#将字母全部转换成大写 a = lower()#将字母全部转换成小写 a = s.swapcase()#大小写互换 a = replace(s1,s2)#将s1替换为s2
-
-
构建算法
-
程序实现
def DecTobin_int(d): if d = 0: return '0' sign = '' if d<0: d = -d sign = '-' b = '' while d != 0: b = str(d%2)+b d = d/2 return sign + b d = int(input('d=')) print(DecTobin_int(d))
-
递归函数:函数自己调用自己
-
算法复杂度
- 时间复杂度:随着为题规模N的增加,算法所需时间(一般用操作次数来衡量)的增加趋势
- 空间复杂度
-
递归实现
- 递归:将复杂问题层层转化为与原来问题本质相同,但更容易解决的问题
-
除二取余的递归定义(d∈Z+)
def f(d): if d = 1: return '1' else: return f(d//2)+str(d%2) def DecToBin_int(d): if d==0: return '0' if d>0: return f(d) if d<0: return '-'+f(-d) d = int(input('d=')) print(DecToBin_int)
3.4.3、八进制与十六进制

-
转换方法
3.5、0/1表示的缺陷及计算机的局限性
-
十进制小数转换成二进制 小数部分:乘2取整法(进位法)
- 不一定能等值转换
- 近似转换的精度取决与计算机内部用于数据表示和存储的位数
- 可用的位数越多,精度就越高
-
计算机的局限性
- 数学思维的世界是连续的、无限的
- 计算思维的世界是离散的、有限的
-
位的概念(比特:bit;缩写:b)
- 0/1信息编码中的一位
- 信息量的最小度量单位
-
字节的概念(字节:Byte;缩写:B)
- 1个字节由8为组成
- 1字节等于8比特(1B=8b)
-
位模式:用于描述信息的0/1数字的位数
-
误差的来源
- 二进制无法精确表示部分十进制小鼠
- 数学当中存在无限循环和无限不循环小数,因为位模式的局限而无法精确表示
3.6、数值信息编码-计算机码制
3.6.1、最自然却是最“复杂”的原码
-
机器数
-
机器数:将真值的正负符号数值化,用0表示正,用1表示负
-
真值:带有“+”、“-”号的数据表示
-
-
数值信息的编码——原码
-
符号部分
- 数的最高位“符号位”
- 用代码0表示“+”,用代码1表示“-”
-
数值部分与真值相同
-
与位模式的关系:N为位模式下,数值部分不足N-1位,用0补足
-
原码的有点:简单直观,容易理解
-
原码的缺点
-
浪费编码资源,增加计算开销
-
进行加减运算较为复杂:要对符号和数值的绝对值大小进行判断
-
-
3.6.2、“取反加一”——特殊的补码规则
- 数值信息的编码——补码
- 符号部分同原码
- 最高位为符号位,0表示正数,1表示负数
- 数值部分与它的符号位有关
- 对于整数,补码的数值部分与原码相同
- 对于负数,是将原码数值部分按位取反再加1
- 符号部分同原码
3.6.3、0的回归——补码的表示范围
-
符号部分同原码
-
数值部分与它的符号位有关
-
对于正数,补码的数值部分与原码相同
-
对于负数,是将源码数值部分按位取反再加1
-
3.6.4、神奇的补码运算
-
同余理论:两个整数a,b,若它们除以整数m所得的余数相等,则称a,b对于整数m同余,m称为模,记作a=b(mod m),读作a与b关于m同余
-
推论
-
在模为M的条件下,A减B,可以用A加上-B的补数来实现
-
求-B的补数的公式:-B的补数 = -B + M
-
补码的定义:[X]补 = (2n + X) mod 2n
-
补码运算规则:两数和的补码等于两数补码的和
[x1 + x2]补 = [x1]补 + [x2]补
[x1 - x2]补 = [x1]补 + [-x2]补
-
只需要一套实现加法运算的器件,从而简化了计算机内部硬件电路的结构
-
3.6.5、危险的溢出
- 溢出的演示
- 两个数参加运算,结果超出了计算机能表示的数值的范围,称之为溢出
- 正溢出:加数和被加数的符号位为0,加完之后结果的符号位为1的情况,称之为正溢出
- 负溢出:加数和被加数的符号位为0,加完之后结果的符号位为1的情况,称之为负溢出
- 算法逻辑的设计,数据表示的范围和精度是导致错误的原因
3.6.6、小数点需要表示吗
-
由于规则的约定小数点变成了交互双方的以个默认信息而无需表示
- 信息论的解释:表示小数点的信息熵为零
-
定点表示和浮点表示的优缺点
- 定点表示法运算直观,但数表示范围小
- 浮点表示法表示的数的范围和精度都提升,但浮点运算复杂
-
定点数和浮点数
- 根据小数点的位置是否固定,数据有定点数和浮点数两种表达方式
- 编码由原码或补码构成
-
定点数:约定机器中所有数据的小数的小数点位置固定不变
- 定点整数:小数点固定在数的最低点之后
- 定点小数:小数点固定在符号位之后,最高数值之前
- 小数点便为隐含信息不需要表示
- 数符和数值部分的编码方式即可以用原码也可以用补码
- 用定点数进行运算处理的计算机被称为定点机
-
浮点数
- 一个数N的科学计数法形式可写成:N = M*RE
- 尾数M,通常是小数
- 阶码E,通常是整数
- 当尾数、阶码采用二进制,基数R= 2时,就是计算机中的浮点数据表示
- 一个数N的科学计数法形式可写成:N = M*RE
-
浮点表示格式
- 浮点数据表示用一对定点数表示
- 尾数:定点小数表示,决定了浮点数的表示精度
- 阶码:定点整数表示,决定了浮点数的表示范围
-
规格化浮点数
- 为了不损失有效数字,常对位数进行规格化处理
- 规格化对尾数M的要求:1/2<=|M|<1
- 即保证尾数部分真值的最高位1,大小通过阶码调整
- 为了不损失有效数字,常对位数进行规格化处理
-
定点机:CPU被设计为执行定点算数,通过分解运算序列,使用定点架构来实现浮点运算
-
浮点运算单元(FPU)
- 对浮点数执行加、减、乘、除、平方根和位移等操作
3.7、字符信息的编码
3.7.1、什么是ASCII码
-
关于多媒体信息表示
- 数值信息与非数值信息
- 建立抽象与具象的连接
-
美国信息交换标准码(American Standard Code for Information Interchange, ASCII)
- 国际标准:ISO 646标准,适用与拉丁文字字母
- 首发在1967年,最后一次更新在1986年
-
ASCII码的组成和存储
-
138个字符,7位二进制表示
-
在计算机内部用1个字节存放
- 最高位均设为0
-
3.7.2、ACSCII码够用吗
- ASCII码的扩展
- 利用ASCII码中闲置的最高位编入新的符号
- 可以表示最多256个符号
- 0—127保持不变,128-255为扩展段
- ASCII码不适于亚洲文字
- 国标码GB2312
- 用2个字节表示1个汉字
- 最多可表示256*256=65536个字符
- 计算机处理和显示不同的字符文字,必须适配不同的编码规则
- 国标码GB2312
3.7.3、庞大的汉字字符集
- 国标码
- 用2个字节表示1个汉字
- 至少13位二进制编码
- 考虑以后的扩充,设置14位
- 14位需要2个字节保存,每个字节最高位设位0
- 国标码与机内码的关系
- ASCCII码和国标码并存出现二义性
- 国标码每个字节的最高位置为1,机内码=国标码+8080H
- 国标码的发展
- **GB 2312-80:国标基本集6763个汉字,682个字符
- GBK兼容GB2312,包含20902个汉字
- GB18030-2000(或GBK2K)在GBK的基础上做了进一步扩充
3.7.4、万能的Unicode
- Unicode又称统一码、万国码、单一码
- 世界上所有语言的符号,组成通用字符集(Universal Character Set,UCS)
- Unicode编码由4个字节组成
- Unicode编码体系具有较复杂的“立体”结构
3.7.5、字符实训:凯撒加密
-
“凯撒加密”问题
-
信息加密
-
凯撒加密:将每个明文字符按字母表顺序进行偏移
-
-
加密一个小写字母
firstASCII = ord('a') N = 26 #字符总数 def enChar(x,key): xid = ord(x)-firstASCII yid = (xid+key) % N y = chr(firstASCII + yid) return y chars = 'abcdefghijklmnopqrstuvwxyz' for x in chars: print(x,'->',enChar(x,2))
-
加密一段文本
firstASCII = ord('a') N = 26 #字符总数 def enChar(x,key): xid = ord(x)-firstASCII yid = (xid+key) % N y = chr(firstASCII+yid) return y def Caesar(text,key): result = '' for x in text: if 'a'<=x<='z': x = enChar(x,key) result +=x return result #加密 text = 'attack tonight' key = 2 print(Caesar(text,key)) #解密 #text = 'attack tonight' #key = 2 #print(Caesar(text,-key))
-
加密其他字符
firstASCII = 0 N = 65535 #字符总数 def enChar(x,key): xid = ord(x)-firstASCII yid = (xid+key) % N y = chr(firstASCII+yid) return y def Caesar(text,key): result = '' for x in text: if 0<=ord(x)<N: x = enChar(x,key) result +=x return result #加密 text = '今晚发动攻击,代号Python!' key = 1234 print(Caesar(text,key)) #解密 #text = 'print(Caesar(text,key))' #key = 1234 #print(Caesar(text,-key))
3.8、数字音频及其处理
3.8.1、声音的数字化
-
声音:在介质中传播的机械波,是随时间连续变化的连续信号
-
采样:每隔一个时间间隔取一个幅度值
-
采样周期=1/采样频率
-
量化:对振幅值进行限定和近似的过程
-
编码:将量化后的振幅值用二进制表示
-
声音的数字化过程:模拟声音信号**(采样)、(量化)、(编码)**,最后转化成数字音频
3.8.2、数字音频的相关参数
- 采样频率:单位时间内采样的次数,单位:赫兹(HZ)
- 量化位数(也称采样精度):每个采样点的二进制位数,单位:位/字节
- 声道数:包含声道的个数
- 比特率:
- 单位时间的比特数,单位:比特/秒(bps)
- (采样频率量化位数声道数)
- 比特率*持续时间(秒) = 数据量(比特)
3.8.3、查看儿歌的参数
#注意程序运行时需要与文件在同一文件夹下
from pydub import AudioSegment as AS
song = AS.from_file('文件名称',format = '文件格式')
print(len(song)) #时长,单位:毫秒
print(song.frame_rate) #采样频率,单位:HZ
print(song.sample_width)#量化位数,单位:字节
print(song.channels) #声道数
3.8.4、数据压缩
-
原理:对原始数据进行重新编码,去除原始数据中的冗余数据
-
行程编码:重复的数据用改值和重复的次数来代替
-
压缩比:压缩前后的数据量之比
-
无损压缩(或可逆压缩):被压缩的数据经过解压缩后,可以得到与原始数据完全相同的数据
-
有所压缩(或不可逆压缩):被压缩后的数据经过解压缩后,不能得到与原始数据完全相同的数据
3.8.5、剪辑儿歌
-
常见的音频文件格式:wav、MP3、Flac、rm、wma等
#注意程序运行时需要与文件在同一文件夹下 from pydub import AudioSegment as AS song = AS.from_file('record.mp3',format = 'mp3') song = son[4000:8500] + song[10000:14500] file = song.export('生成的文件名',format = '生成的文件格式') file.close()
3.8.6、为儿歌配乐
#注意程序运行时需要与文件在同一文件夹下
#根据简谱生成音乐
from pydub import AudioSegment as AS
duoRuiMi = [ ]#用列表存放发音
duoRuiMi.append(AS.silent(500)#第0号是0.5秒静音
for i in range(1,8):#哆瑞咪发梭拉西
s = AS.from_file(str(i)+'.mp3',foramt = 'mp3')
duoRuiMi.append(s)
notation = '01231231034503450' #简谱
music = AS.empty()#空音频
for i in notation:#将各音符转化为对应的发音
music = music+duoRuiMi[ int(i) ]
file = music.export('music.mp3',format = 'mp3')
file.close()
#合并歌曲和配乐
for pydub import AudioSegment as AS
song = AS.from_file('song.mp3',format = 'mp3')
music = music[180 : 9180]
music +=8
song = song.split_to_mono()
music = music.split_to_mono()
twoTigers = AS.from_mono_audiosegment(music[0],song[0])
file = twoTigers.export('twoTigers.mp3',format = 'mp3')
file.close()
3.9、数字图像及其处理
3.9.1、绿幕抠像为题的描述
- 将图片中的人从图片中抠取出来的过程
3.9.2、获取图像分辨率
-
图片分辨率:横向像素数*纵向像素数
-
元组:不能被修改的列表
-
利用Python查看分辨率
from PIL import Image img = Image.open(head.jpg) w,h = img.size print(w,'x',h) t = (1,4,9)#定义元组 print(t[0],t[-1])#读取元素 a,b,c = t#多重赋值 print(a,b,c)
3.9.3、获取一个像素的信息
-
像素坐标(x,y):从左往右数的x个、从上往下数第y个**(x、y从0开始)**
from PIL import Image img = Image.open('head.jpg') pix = img.getpixel((23,5)) print(pix)
-
3.9.3、RGB颜色
- RGB颜色模型;自然界任意颜色都可以由**红(red)、绿(green)、蓝(blue)**三种基本颜色按一定比例组合而成
3.9.4、RGBA颜色
-
A分量:透明度,取值为[0,255]
- 0:完全透明
- 255:完全不透明
from PIL import Image boy = Image.open('boy.jpg') boy = boy.convert('RGBA')#修改格式为RGBA格式 w,h = boy.size for x in range(0,w):#横坐标为x for y in range(0,h):#纵坐标为y r,g,b,a = boy.getpixel((x,y))#取出(x,y)处颜色 a = 100#改为半透明 boy.putpixel((x,y),(r,g,b,a))#修改(x,y)处颜色 boy.save('boy.png')#png格式支持头透明度
3.9.5、实现绿幕抠像
#编写临时程序
#绿幕抠像
from PIL import Image
boy = Image.open('boy.jpg')
boy = boy.convert('RGBA')
w,h = boy.size
for x in range(0,w):
for y in range(0,h):
r,g,b,a = boy.getpixel((x,y))
if g-r>30 and g-b>30:#若是偏绿色
a = 0#改成完全透明
boy.putpixel((x,y),(r,g,b,a))#设置像素颜色
continue
boy.save('boy.png')
#添加场景
#from PIL import Image
#boy = Image,open('boy.png')
playground = Image.open('playground.jpg')
w,h = boy.size
boy = boy.resize((w//2,h//2))
playground.paste(boy,(620,140),mask = boy.split()[3])#将抠取下来的图片粘贴到'playground.jpg'中
playground.save('final.jpg')
3.10、小结
-
信息与编码——思维导图
六、计算机系统的程序员视角
4.1、冯·诺依曼体系结构
4.1.1、 再谈计算
- 理解计算:从一个符号串变换成另一个字符串
- 计算过程:从初始符号或已知符号开始,一步一步地变换符号,经过有限步骤,最后得到一个满足预先规定的符号串的变换过程
- 计算的实现:
- 计算装置在某个“过程”的控制下根据输入产生输出
- 一个通用的计算装置应该支持符号解译、过程记忆、可编程的功能
4.1.2、健忘的ENIAC与冯氏结构
-
存储程序控制原理:把程序本身当作数据来对待,程序与其处理的数据用同样的方式储存
4.1.3、从抽象结构到具体实现
-
冯氏结构的实现
-
存储器与CPU的关系
- 与CPU直接打交道的速度较快的内存储器
- 外存是作为长期保存程序和数据的辅助存储器
-
现代电子计算机的典型结构
-
玩转表格—— “四步走”攻略
- 制定计划
- 新建表格、输入文字、调整格式
- 搜集数据
- 汇总数据
- 分析数据
- 制定计划
4.2、冯氏结构的软件模拟——TOY计算机
4.2.1、存储程序思想的实现
-
冯诺依曼体系结构的核心思想是“存储程序”
-
程序是指完成一项特定任务,用计算机语言描述的问题求解步骤的有序序列
-
机器语言:程序和数据都用0/1形式表示,0/1编码称为机器语言
-
指令:用机器语言描述的计算机执行的最小单位
-
机器语言程序:由一组有序的指令组成的指令序列
-
指令格式
-
指令类型:
- 操作指令
- 数据移动指令
- 控制指令
-
指令系统:CPU所能执行的机器指令的集合,称为指令集或者指令系统
-
任何程序都是由指令集和内的不同指令组合而成的指令序列
-
汇编语言:用一些容易理解和记忆字母、单词来代替一个特定的指令中的0/1编码
-
高级语言:独立于机器的硬件系统、面向过程或对象的语言,它较接近自然语言或数学语言
-
高级语言编写的程序称之位源程序
-
编译之后得到的0/1代码则称之为可执行程序
-
TOY指令集
-
寄存器:CPU中用于存放数据和状态的临时存储单元
- Rx、Ry:CPU中某个通用的寄存器编号(取值为整数)
-
主存单元:主存被分为一个个的单元格,数据按字节顺序存放在这些单元格中
- mem:主存中的某个单元(取值为整数)
4.2.3、CPU模拟于指令的执行
-
CPU组成结构
-
算术逻辑运算单元(ALU):计算
- 算术运算:加减乘除
- 逻辑运算:与或非异或等、位运算
-
寄存器组:用于临时保存数据(数据十分有限,属于稀缺资源);存储
- 通用寄存器组:操作数、结果等;程序可以使用
- 专用寄存器组:计算机当前状态;CPU专用,用户不可见
-
控制单元(Control Unit):控制
- 功能:分析指令、传送指令及操作数;产生时序逻辑:控制和威胁整个CPU工作
-
控制单元(CU)的组成
- 程序计数器(PC):保存下条指令的地址
- 指令寄存器(IR):保存当前执行的指令
- 指令译码器(ID):根据IR内容,决定进行何种操作
- 操作控制器(OC):控制各种操作(取指令、取数、控制ALU)
-
CPU内部总线:互联
- 数据和指令在CPU中的传送通道:数据总线(DB)、地址总线(AB)、控制总线(CB)
-
-
CPU的执行过程
-
循环执行指令的过程:在CU的控制下,精确地、一步一步地完成
-
一条指令执行的时间称为指令周期,每一步称为一个节拍
-
时钟周期
-
CPU工作的最小时间单位
-
一个节拍可能花费多个时钟周期
-
时钟频率(主频):1/时钟周期
-
mem = ['']*1000 #主存 reg = [0]*10 #通用寄存器 pReg = 0 #程序计数器 iReg = '' #指令寄存器 def loadProgram(file): global pReg, mem #全局变量声明 fil = open(file, 'r') #打开文件 first = True #用于标识是否为第1条指令 while True: #每循环一次加载一条指令 line = fil.readline() #读1行 if line == '': #若读取完毕,则结束循环 break flds = line.split() #将1行拆分为若干部分 address = int(flds[0]) #第0部分为地址 instruc = flds[1] #将后面的部分重新拼接为指令 for fld in flds[2:len(flds)]: instruc = instruc+' '+fld mem[address] = instruc #将指令加载到主存单元 if first==True: #若是第1条指令 pReg = address #则将其地址存入程序寄存器 first = False #后面的指令不再是第1条指令''' fil.close() #关闭文件 def cycle(): global pReg, iReg, reg, mem #取指令 iReg = mem[pReg] #根据pReg的值,将指令从mem取到iReg pReg = pReg + 1 #pReg加1,指向下一条指令 #译码 flds = iReg.split() opcode = flds[0] #操作码 if len(flds)>1: op1 = int(flds[1]) #操作数1 if len(flds)>2: op2 = int(flds[2]) #操作数2 #执行和写结果 if opcode=='mov1': #数据移动指令:寄存器←主存 reg[op1] = mem[op2] elif opcode=='mov2': #数据移动指令:主存←寄存器 mem[op1] = reg[op2] elif opcode=='mov3': #数据移动指令:寄存器←数字 reg[op1] = op2 elif opcode=='add': #加法指令 reg[op1] = reg[op1]+reg[op2] elif opcode=='sub': #减法指令 reg[op1] = reg[op1]-reg[op2] elif opcode=='mul': #乘法指令 reg[op1] = reg[op1]*reg[op2] elif opcode=='div': #除法指令 reg[op1] = reg[op1]/reg[op2] elif opcode=='jmp': #无条件跳转指令 pReg = op1 elif opcode=='jz': #条件跳转指令 if reg[op1]==0: pReg = op2 elif opcode=='in': #输入指令 reg[op1] = int(input('input:')) elif opcode=='out': #输出指令 print('output:', reg[op1]) elif opcode=='halt': #停止指令 return False return True def run(file): global pReg, iReg, reg, mem loadProgram(file) #加载TOY程序 while True: #每循环一次,执行一条指令 hasNextInstruc = cycle() #执行一条TOY指令 if hasNextInstruc==False: #若执行的是halt指令 break #则跳出循环 run('sum100.txt') #运行sum100.txt中的TOY程序 for i in range(11): print('主存单元', i, ':', mem[i]) #打印当前主存单元中保存的程序 run('add.txt') #运行add.txt中的TOY程序 for i in range(5): print('主存单元', i, ':', mem[i]) #打印当前主存单元中保存的程序
-
4.2.4、处理器的组成结构和制造过程
-
处理器的组成结构
-
处理器,即平时所说的芯片或CPU
-
处理器主要完成的功能
- 逻辑运算:Y~(A&B + C&D)
- 算术运算:Sum = 100+200
-
“开关”器件,及它们之间的连线
- 金属—氧化物·半导体场效应晶体管(MOSFET),晶体管
- nMOS晶体管和pMOS晶体管
-
香农,1938年硕士论文《继电器于开关电路的符号分析》
- 将电路系统的“开、关”与逻辑运算的“真、假对应”
- 指出可以通过构建开关电路解决任何逻辑和数值运算
-
实现逻辑运算的核心器件是开关
- 基本逻辑运算:与、或、非
-
算术运算的核心是“加法运算”
- **1位二进制加法运算:{C,S} = A+B
- 将多个1位二进制加法器连接得到一个多位二进制加法器
-
- 处理器的制造过程
- 采用类似于“印刷过程”的光刻机制
- 包括多个步骤,每一步都对不同材料进行沉淀或腐蚀
4.3、操作系统漫谈
4.3.1、计算机硬件和软件
- 软件系统:应用软件、系统软件
- 硬件系统:CPU、鼠标、键盘、主机、显示屏
4.3.2、什么是操作系统
- 操作系统(OS)是管理计算机硬件资源并向用户提供公共服务的软件
- 操作系统(进程管理、存储管理、文件管理、设备管理)是资源得到充分有效的利用
- 用户接口:人机接口、API接口
4.4、文件合并工具(I)
4.4.1、问合并问题
- 文件合并前:原始文件;合并后:结果文件
- 文件合并功能——文件管理
- 打开关闭功能——进程管理
- 图形化界面实现——用户接口
4.4.2、文件
-
程序和数据以文件的形式存储在外存上
-
文件包括文件内容和文件属性
-
文件名称:文件名称.扩展名
-
文件的分类
- 程序文件和数据文件
-
目录(文件夹):便于管理文件
- 实际上也是一种文件
- 内容:所含文件的描述信息
- 属性
- 目录可以包含目录:父目录、子目录、根目录
- 实际上也是一种文件
-
操作系统中的文件系统
- 对外存上的文件实施管理
- 并向用户提供调用接口
4.4.3文件路径
-
用于标识文件(包括文件夹)的位置
- 父文件夹路径+文件名称
- 绝对路径:从根目录开始
- 相对路径:从用户所在位置开始
-
Python中的特殊符:
制表符:\t 换行符:\n 解决方法1:\\表示一个\ 解决方法2:/ 解决方法3:r 表示不使用特殊符
4.4.4、添加文件夹功能
import os
print(os.path.isfile(''))#判断是否为文件
print(os.path.isdir(''))#判断是否为目录
print(os.path.join(''))#形成路径
print(os.path.realpath(''))#绝对路径
print(os.listdir(''))#获取目录下所有名称
if not os.path.exists('temp'):#判断路径是否存在
os.mkdir('tmp')#新建目录
os.rename('tmp','abc')#重命名
-
添加文件夹功能
import os #获取文件夹下所有txt文件的路径 def getTxtPaths(dirpath): paths = [ ] filenames = os.listdir(dirpath) for filename in filenames: filepath = os.path.join(dirpath,filename) if os.path.isfile(filepath) and filename.endswith('.txt'): paths.append(filepath) return paths for path in getTxtPaths('学生反馈'): print(path)
4.4.5、读取一个txt文件
-
写文件
txt = open('test.txt','w')#以写模式打开文件 txt.write('计算机\n')#写文件 txt.write('计算思维\n') txt.write('Python\n') txt.close()#关闭文件 #W:写模式(覆盖) #a:写模式(追加)
-
读文件
txt = open('test.txt','r') print(txt.read())#读所有内容返回值是字符串 print(txt.readlines())#都所有内容返回值是列表 print(txt.readline())读一行返回值是字符串 txt.close()
-
异常处理(当发生异常时程序终止运行):当try中发生异常时,转而执行except后的异常处理语句
-
读取一个txt文件(异常时不终止)
import os def readOneTxt(filepath): try: file = open(filepath,'r') text = file.read() file.close() return text except: return '' print(readOneTxt('test.'))
4.4.6、文本合并功能
def mergeTxts(srcPaths,destPath):
destFile = open(destPath,'w')
for srcPath in srcPaths:
text = readOneTxt(srcPath)
if text!='':
destFile.write(text)
destFile.write('\n'*2+'-'*50+'\n'*2)
destFile.close()
return os.path.realpath(destPath)
srcPaths = getTxtPaths('红楼梦')
mergeTxts(srcPaths,'result.txt')
print(readOneTxt('result.txt'))
-
揭开操作系统的神秘“面纱”
-
定位和作用
-
管控计算机软硬件资源的程序
-
计算机系统中的重要核心软件,是其他软件的基础
-
-
直观的体验和技术内涵
-
-
操作系统的“前世”和“今生”
-
硬发展推动
- 向下:追求更高地发挥硬件资源所提供的计算、存储、通信等能力
-
应用需求牵引
- 向上:更好地为用户和应用程序提供服务、提高易用性
-
4.5.文件合并工具(II)
4.5.1、进程
- 现代操作系统的基本特征
- 并发:多个程序在同一时间段中运行
- 共享:资源可供多个并发程序共同使用
- OS的CPU管理:如何将CPU合理地分配给各个程序,既提高CPU的使用效率,又能满足不同程序地要求
- 进程
- OS中最核心的概念
- 可并发执行的程序在一个数据集合上的运行过程,是系统进行资源分配和调度的一个独立单位
- 直观理解:程序的一次执行
- 进程和程序的关系
- 进程时动态的,程序时静态的
- 进程是程序的执行
- 程序是指令的序列
- 进程是暂时的,程序是永久的
- 进程有生命周期,会消亡
- 程序可长期保存在外存上
- 进程的组成包括程序、数据和程序控制快
- 数量上的关系
- 一个程序的多次运行对应到多个进程
- 一个进程可以通过调用运行多个程序
- 进程时动态的,程序时静态的
4.5.2、进程的状态
-
进程状态的转换
4.5.3、进程的管理
-
进程控制块(PCB)
- OS为了管理和控制进程的运行,为每个进程定义一个用于记录进程信息的表
- 是进程存在的唯一标志,随着进程的创建二建立,随着进程的撤销而消失
- 在进程生命周期中,OS利用PCB对进程进行调度和资源分配
-
PCB包含的信息
-
进程标识信息:用于区别不同进程
-
位置信息:程序和数据的存放位置
-
状态信息:进程当前状态
-
进程优先级:用于进程调度
-
进程现场保护区
-
队列指针:将同一状态进程链接成一个队列
……
-
4.5.4、进程调度策略
- 先来先服务
- 时间片轮转
- 优先级法:抢占式、非抢占式
- 多级反馈队列轮转
4.5.5利用Python查看进程信息
- 打印系统中所有进程的信息
import psutil
for p in psutil.process_iter():#查看w
try:
print(p.pid)
print(p.name())
print(p.status())
print(p.username())
print(p.cpu_percent())
print('-'*10)
except:
print('-'*10)
print('*'*50)
for p in psutil.process_iter():
if 'notepad' in p.name().lower():
print(p.name(),end='\t')
print(p.cmdline())
4.5.6、打开和关闭功能
from subprocess import Popen
import psutil
import os
def openOneTxt(path):
if os.path.exists(path) and path.endswith('.txt'):
Popen( ['notepad.exe', path] )
def openManyTxt(paths):
for path in paths:
openOneTxt(path)
def closeAllTxt():
for p in psutil.process_iter():
if p.name().lower()=='notepad.exe':
p.terminate()
import time
paths=['红楼梦\\第001回.txt',
'红楼梦\\第002回.txt',
'红楼梦\\第003回.txt',
'红楼梦\\第004回.txt']
openManyTxt(paths)
time.sleep(3)
closeAllTxt()
4.6、文件合并工具(III)
4.6.1、生成主窗口
import tkinter as tk
window =tk.TK()
window.title('文件合并工具')#标题窗口
window.geometry('440x600+300+200')
#窗口宽440,高600;窗口左上角离屏幕左侧距离300,离屏幕上方距离200
window.resizable(False,False)
window.mainloop()
4.6.2、添加控件
-
控件:按钮、文本框、滚动式文本框、标签
import tkinter as tk from tkinter import scrolledtext #主窗口 window = tk.Tk() window.title('文件合并工具') window.geometry('440x600+300+200') window.resizable(False, False) #“添加文件”按钮 button_addFile=tk.Button(window,text='添加文件',font=('楷体',12)) button_addFile.place(x=20, y=20, width=120, height=40) #“添加文件夹”按钮 button_addDir=tk.Button(window,text='添加文件夹',font=('楷体',12)) button_addDir.place(x=160, y=20, width=120, height=40) #“开始合并”按钮 button_merge=tk.Button(window,text='开始合并',font=('楷体',12), bg='orange') button_merge.place(x=300, y=20, width=120, height=40) #用于展示所选文件对应路径的文本框(可滚动) textbox_txtPath=scrolledtext.ScrolledText(window) textbox_txtPath.place(x=20,y=70,width=400,height=400) #“生成结果”标签 label=tk.Label(window, text='生成结果:', font=('楷体',12)) label.place(x=20,y=490,width=100,height=40) #用于展示生成结果路径的文本框 textbox_resultPath=tk.Text(window) textbox_resultPath.place(x=120,y=490,width=300,height=40) textbox_resultPath.configure(state=tk.DISABLED)#不可修改 #“打开结果”按钮 button_openResult=tk.Button(window,text='打开结果',font=('楷体',12), bg='orange') button_openResult.place(x=20, y=540, width=120, height=40) #“打开所有”按钮 button_openAll=tk.Button(window,text='打开原始文件',font=('楷体',12)) button_openAll.place(x=160, y=540, width=120, height=40) #“关闭所有”按钮 button_closeAll=tk.Button(window,text='关闭所有文件',font=('楷体',12)) button_closeAll.place(x=300, y=540, width=120, height=40) #显示图形化界面 window.mainloop()
4.6.3、消息响应
import tkinter as tk
from tkinter import scrolledtext
from tkinter import filedialog
def clickButton_addFile():
filePaths = filedialog.askopenfilename(title = '选择文件',filetypes = [('txt','.txt')])
for filePath in filePaths:
textbox_txtPath.insert(tk.END,filePath+'\n')
textbox_txtPath.see(tk.END)
#主窗口
window = tk.Tk()
window.title('文件合并工具')
window.geometry('440x600+300+200')
window.resizable(False, False)
#“添加文件”按钮
button_addFile=tk.Button(window,text='添加文件',font=('楷体',12))
button_addFile.place(x=20, y=20, width=120, height=40)
#“添加文件夹”按钮
button_addDir=tk.Button(window,text='添加文件夹',font=('楷体',12))
button_addDir.place(x=160, y=20, width=120, height=40)
#“开始合并”按钮
button_merge=tk.Button(window,text='开始合并',font=('楷体',12), bg='orange')
button_merge.place(x=300, y=20, width=120, height=40)
#用于展示所选文件对应路径的文本框(可滚动)
textbox_txtPath=scrolledtext.ScrolledText(window)
textbox_txtPath.place(x=20,y=70,width=400,height=400)
#“生成结果”标签
label=tk.Label(window, text='生成结果:', font=('楷体',12))
label.place(x=20,y=490,width=100,height=40)
#用于展示生成结果路径的文本框
textbox_resultPath=tk.Text(window)
textbox_resultPath.place(x=120,y=490,width=300,height=40)
textbox_resultPath.configure(state=tk.DISABLED)#不可修改
#“打开结果”按钮
button_openResult=tk.Button(window,text='打开结果',font=('楷体',12), bg='orange')
button_openResult.place(x=20, y=540, width=120, height=40)
#“打开所有”按钮
button_openAll=tk.Button(window,text='打开原始文件',font=('楷体',12))
button_openAll.place(x=160, y=540, width=120, height=40)
#“关闭所有”按钮
button_closeAll=tk.Button(window,text='关闭所有文件',font=('楷体',12))
button_closeAll.place(x=300, y=540, width=120, height=40)
#显示图形化界面
window.mainloop()
4.6.4、再谈import语句
#位于同一文件夹下的不同Py文件之间相互调用其内部的函数,则可以利用import函数来进行调用。
#调用规则:调用的文件中的函数是将被调用的文件重新执行一边
#解决方法:if__name__=='__main__'
#a.py
myPi = 3.14
def myFunction(x):
return x^2
#直接执行a.py则为True,a.py被导入时为False
if__name__=='__main__':
print(myFunction(myPi))
#b.py
import a
print(a.myPi)
print(a.myFunction(3))
4.6.5、文件合并工具程序
#myFile.py
import os
'''
获取dirpath文件夹下所有txt文件的路径
'''
def getTxtPaths(dirpath):
paths = [ ]
filenames = os.listdir(dirpath)
for filename in filenames :
filepath = os.path.join(dirpath,filename)
if os.path.isfile(filepath) and filename.endswith('.txt'):
paths.append(filepath)
return paths
'''
读取一个txt文件的内容,filepath是文件路径
'''
def readOneTxt(filepath):
try:
file = open(filepath, 'r')
text = file.read()
file.close()
return text
except:
return ''
'''
将多个txt文件(原始文件)合并成一个txt文件(结果文件)
srcPaths是一个列表,存放了所有原始文件的路径
destPath是一个字符串,表示结果文件的路径
'''
def mergeTxts(srcPaths, destPath):
destFile = open(destPath, 'w')
for srcPath in srcPaths:
text = readOneTxt(srcPath)
if text != '':
destFile.write(text)
destFile.write('\n'*2+'-'*50+'\n'*2)
destFile.close()
return os.path.realpath(destPath)
if __name__ == '__main__':
srcPaths = getTxtPaths('红楼梦') #获取“红楼梦”文件夹下所有txt文件的路径
mergeTxts(srcPaths, 'result.txt') #对文本文件进行合并
print(readOneTxt('result.txt')) #读取并打印结果文件
#myProcess.py
from subprocess import Popen
import psutil
import os
def openOneTxt(path):
if os.path.exists(path) and path.endswith('.txt'):
Popen( ['notepad.exe', path] )
def openManyTxt(paths):
for path in paths:
openOneTxt(path)
def closeAllTxt():
for p in psutil.process_iter():
if p.name().lower()=='notepad.exe':
p.terminate()
if __name__ == '__main__':
import time
paths=['红楼梦\\第001回.txt',
'红楼梦\\第002回.txt',
'红楼梦\\第003回.txt',
'红楼梦\\第004回.txt']
openManyTxt(paths)
time.sleep(3)
closeAllTxt()
#注意与myFile、myprocess在同一文件夹下执行
#myTool.py
import tkinter as tk
from tkinter import scrolledtext
from tkinter import filedialog
import myFile
import myProcess
#“添加文件”按钮的消息响应函数
def clickButton_addFile():
filePaths=filedialog.askopenfilenames(title='选择文件',filetypes=[('txt', '.txt')])
for filePath in filePaths:
textbox_txtPath.insert(tk.END,filePath+'\n')
textbox_txtPath.see(tk.END)
#“添加文件夹”按钮的消息响应函数
def clickButton_addDir():
dirpath=filedialog.askdirectory(title='选择文件夹')
filePaths = myFile.getTxtPaths(dirpath)
for filePath in filePaths:
textbox_txtPath.insert(tk.END,filePath+'\n')
textbox_txtPath.see(tk.END)
#“开始合并”按钮的消息响应函数
def clickButton_merge():
tmp = textbox_txtPath.get(0.0, tk.END)
filePaths = tmp.split('\n')
destPath = myFile.mergeTxts(filePaths, 'result.txt')
textbox_resultPath.configure(state=tk.NORMAL)
textbox_resultPath.delete(0.0, tk.END)
textbox_resultPath.insert(0.0, destPath)
textbox_resultPath.configure(state=tk.DISABLED)
#“打开结果”按钮的消息响应函数
def clickButton_openResult():
destFile = textbox_resultPath.get(0.0, tk.END).strip()
myProcess.openOneTxt(destFile)
#“打开原始文件”按钮的消息响应函数
def clickButton_openAll():
tmp = textbox_txtPath.get(0.0, tk.END)
filePaths = tmp.split('\n')
myProcess.openManyTxt(filePaths)
#“关闭所有文件”按钮的消息响应函数
def clickButton_closeAll():
myProcess.closeAllTxt()
#主窗口
window = tk.Tk()
window.title('文件合并工具')
window.geometry('440x600+300+200')
window.resizable(False, False)
#“添加文件”按钮
button_addFile=tk.Button(window,text='添加文件',font=('楷体',12), command=clickButton_addFile)
button_addFile.place(x=20, y=20, width=120, height=40)
#“添加文件夹”按钮
button_addDir=tk.Button(window,text='添加文件夹',font=('楷体',12), command=clickButton_addDir)
button_addDir.place(x=160, y=20, width=120, height=40)
#“开始合并”按钮
button_merge=tk.Button(window,text='开始合并',font=('楷体',12), bg='orange', command=clickButton_merge)
button_merge.place(x=300, y=20, width=120, height=40)
#用于展示所选文件对应路径的文本框(可滚动)
textbox_txtPath=scrolledtext.ScrolledText(window)
textbox_txtPath.place(x=20,y=70,width=400,height=400)
#“生成结果”标签
label=tk.Label(window, text='生成结果:', font=('楷体',12))
label.place(x=20,y=490,width=100,height=40)
#用于展示生成结果路径的文本框
textbox_resultPath=tk.Text(window)
textbox_resultPath.place(x=120,y=490,width=300,height=40)
textbox_resultPath.configure(state=tk.DISABLED)#不可修改
#“打开结果”按钮
button_openResult=tk.Button(window,text='打开结果',font=('楷体',12), bg='orange', command=clickButton_openResult)
button_openResult.place(x=20, y=540, width=120, height=40)
#“打开所有”按钮
button_openAll=tk.Button(window,text='打开原始文件',font=('楷体',12), command=clickButton_openAll)
button_openAll.place(x=160, y=540, width=120, height=40)
#“关闭所有”按钮
button_closeAll=tk.Button(window,text='关闭所有文件',font=('楷体',12), command=clickButton_closeAll)
button_closeAll.place(x=300, y=540, width=120, height=40)
#显示图形化界面
window.mainloop()
4.7、单元小结


七、网络知多少
5.1、互联网从何而来
- 起源:美国组件了美国国防部高级研究计划局ARPA
- 统一:TCP/IP协议
5.2、互联网如何工作

5.2.1、互联网的传输介质
-
有线传输介质
-
双绞线(传输距离较短(<100m))
- 非屏蔽双绞线(Unshielded Twisted Pair,UTP)
- 屏蔽双绞线(Shielded Twisted Pair,STP)
-
-
同轴电缆
-
光导纤维
5.2.2、互联网的关键设备
-
网络适配器(网卡)
-
MAC地址(物理地址:16进制)
- 设置在网络适配器(网卡)接口上,全球唯一
- 长度:6字节(48位)
- 前3个字节由IEEE的注册管理机构负责个不同的厂家分配的代码
- 后3个字节由各厂家自行指派给生产的网络适配器接口
-
交换机
- 用于搭建局域网,即插即用
- 实现多台计算机之间数据的并发交换
- 根据交换机表中的表表项转发数据报文
-
路由器
- 用于实现 多个网络之间的互联
- 网络的调度中心和交通枢纽
5.3、互联网“吸粉”的奥秘
5.3.1、TCP/IP协议体系
-
OSI(Open System Interconnection Reference Model,开放系统互联参考模型)
-
TCP/IP(Transmision Control Protocol/Internet Protocol,传输控制协议/网际协议)
-
TCP/IP体系协议结构
-
网络协议:未进行数据交换而建立的规则、标准或约定
-
组成要素:
-
语法:数据与控制信息的结构或格式
-
语义:数据与控制信息的含义
-
同步:规定事件实现顺序的详细说明
-
5.3.2、IP地址
-
全网唯一性,标识每个设备的位置和身份
-
IPv4地址
- 用32位二进制数表示
- 点分十进制表示法(192.168.10.123)
-
IP地址的构成(网络号+主机号)
- 主机号全为0代表本网络的网络地址号(主机号不能全为0或1)
- 主机号全为1代表本网络段的广播地址(网络号不能全为0或1)
-
IP地址的分类
-
A类IP地址
-
地址范围:0.0.0.0~127.255.255.255
-
特殊用途:0.X.Y.Z、10.X.Y.Z、127.X.Y.Z
-
可分配给27-3 = 125 个网络
-
主机号不能全为0或1(包括B类和C类)
每个A类网络可容纳224-2 = 16777214台主机
-
-
B类IP地址
- 地址范围:128.0.0.0~191.255.255.255
- 特殊用途:172.16.0.0~172.31.255.255
- 可分配给214-16 = 16368个网络
- 每个B类网络可容纳216-2 = 65534台主机
-
C类IP地址
- 地址范围:192.0.0.0~223.255.255.255
- 特殊用途:192.168.0.0~192.168.255.255
- 可分配给221-256 = 2096896网络
- 每个C类网络可容纳28-2 = 254台主机
-
-
划分子网
- 把一个较大的网络划分成几个较小的子网
- 从主机号中分出若干位作为子网号
- IP地址由两级变成三级
-
子网掩码
5.3.3、域名系统
-
域名
-
用来代替难记忆、无意义的IP地址
-
具有唯一性
-
由一串用点分隔的名字组成
-
采用层次结构,从左到右,域的范围变大
-
-
域名系统
- DNS(Domain Name System, 域名系统)
- 将域名映射为IP地址
- 由一组专门的服务器组成
5.3.4、网络组建
- 小型局域网
- 交换机
- 网线和水晶头
- 分类:CAT5(五类)、Cat5e(超五类)、Cat6(六类)、Cat6a(超六类)、Cat7(七类)
- 路由器
5.4、“触摸”万维网——网络数据获取
5.4.1、数据获取——分数线目录页
-
URL——统一资源定位符
-
URL(Uniform Resource Locator,统一资源定位符)
-
<协议>://<主机名>:[端口号]/<被访问的网页在服务器上的路径>
https://www.nudt.edu.cn/bkzs/xxgk/lqfs/index.html
-
-
HTTP协议(HyperText Transfer Protocol,超文本传输协议)
- 基于TCP/IP的应用层协议
- 规定了浏览器和服务器之间请求和响应的交互过程必须遵守的规则
- B/S模式
- browser:浏览器使用HTTP协议发送、接收web对象,并显示
- server:Web服务器使用HTTP协议响应客户请求发送对象
import urllib.request as req url = 'https://www.nudt.edu.cn/bkzs/' webpage = req.urlopen(url) webdata = webpage.read() webdata = webdata.decode('utf-8') print(webdata)
5.4.2、数据分析——提取历年分数线数据页
import urllib.request as req
url = 'https://www.nudt.edu.cn/bkzs/xxgk/lqfs/index.htm'
webpage = req.urlopen(url)
webdata = webpage.read().decode('utf-8')
for year in range(2016,2024):
substr = str(year)+'年录取分数统计'
index = webdata.find(substr)
href = webdata[index-133:index-97]
href = 'https://www.nudt.edu.cn/bkzs/xxgk/lqfs/'+href
webpage = req.urlopen(href)
content = webpage.read().decode('utf-8')
#print(content)
outfile = open(str(year)+'年录取分数网页.txt','w',encoding = 'utf-8')
outfile.write(content+'\t')
outfile.close()
5.4.3、数据分析——提取历年分数线的数据
-
正则表达式
-
用于表示一系列符号某一模式的字符串
-
常用于字符串查找、替换、文本解析等
-
点好(·):某一个字符,不包括换行符’\n’
a.b:以a开头、以b结尾、长度为3的所有字符串
-
星号(*):前一字符出现0到无限次
a*b:以a开头、以b结尾所有字符串
import re s = 'abd000\n0000acb' ab = re.findall(r'a.b*',s,re.S)#贪婪模式 ab = re.findall(r'a.*?b',s,re.S)#非贪婪模式 #findall找出所有匹配正则表达式的字串 #r定义正则表达式 #使点号匹配任意字符串,包括换行符 #ab列表类型 print(ab)
import urllib.request as req import re url='https://www.nudt.edu.cn/bkzs/xxgk/lqfs/index.htm' webpage=req.urlopen(url) webdata=webpage.read().decode('utf-8') for year in range(2016, 2019): substr=str(year)+'年录取分数统计' index=webdata.find(substr) href=webdata[ index-133 : index-97 ] href='https://www.nudt.edu.cn/bkzs/xxgk/lqfs/'+href webpage=req.urlopen(href) content=webpage.read().decode('utf-8') tables=re.findall(r'<table.*?>(.*?)</table>',content, re.S) table=tables[0] rows = re.findall(r'<tr.*?>(.*?)</tr>', table, re.S) for row in rows: tds = re.findall(r'<td.*?>(.*?)</td>', row, re.S) for td in tds: print([ td ],'\n')
-
5.4.4、数据清洗——整理并保存数据
import urllib.request as req
import re
url='https://www.nudt.edu.cn/bkzs/xxgk/lqfs/index.htm'
webpage=req.urlopen(url)
webdata=webpage.read().decode('utf-8')
for year in range(2016, 2019):
substr=str(year)+'年录取分数统计'
index=webdata.find(substr)
href=webdata[ index-133 : index-97 ]
href='https://www.nudt.edu.cn/bkzs/xxgk/lqfs/'+href
webpage=req.urlopen(href)
content=webpage.read().decode('utf-8')
tables=re.findall(r'<table.*?>(.*?)</table>',content, re.S)
table=tables[0]
rows = re.findall(r'<tr.*?>(.*?)</tr>', table, re.S)
datalist = []
for row in rows:
tds = re.findall(r'<td.*?>(.*?)</td>', row, re.S)
data_row = []
for td in tds:
item = re.findall(r'<p.*?>(.*?)</p>',row,re.S)
if len(item)>0:
data_row.append(item[0])
datalist.append(data_row)
outfile = open(str(year)+'年数据.txt','w',encoding = 'utf-8')
for rows in datalist:
for cell in rows:
outfile.write(cell+'\t')
outfile.write('\n')
outfile.close()
5.5、小结

八、数据库探秘
6.1、MySQL的安装
- 现代计算机主要用途之一:数据库管理
- 数据库技术是数据库管理最有效的方法
- 数据库技术已成为信息基础设施的核心技术之一
- 数据库理论和技术是计算机领域的一个重要分支
- 数据库系统的建设规模、信息的多少和使用频率已成为衡量一个国家信息化程度的重要标志
6.2、录取分数数据管理(II)
6.2.1、数据预处理
- 删去标题行
- 省份名用拼音表示
- 空取值用NULL表示
6.2.2、问什么需要数据库
-
利用文件系统同可以进行数据管理
-
利用文件系统管理数据存在的问题
-
程序员需要关注大量操作细节,负担很重
-
数据可能因误操作、认为等原因存在错误
-
数据格式发生变化,程序页需进行修改
……
-
-
数据库系统(DBS)
- 应用程序
- 数据库管理系统(DBMS)
- 数据库(DB):再不引起混淆的情况下,常把数据库系统简称为数据库
6.2.3、关系数据库
-
关系:简单理解即二维表
- 元组(或记录):表中一行
- 属性:表中列
- 主关键字(或主码)
- 挑选出的一组属性,用来唯一标识每个元组
- 元组的主关键字取值具有唯一性
-
数据查询
- 关系操作的最主要部分
- 关系的查询表达能力很强
-
数据更新
- 插入、删除、修改
6.2.4、创建数据库
- 查看数据库:show databases
- 不区分大小写
- 一般以分号结尾
- 可以写成多行
- 创建数据库:create database mydb
- 数据库的名字
- 删除数据库 drop database mydb
- 选择数据库:uer mydb
- 操作前要先选择一个数据库
6.2.5、创建基本列表
create table S(
Sno char(9),
Sname char(20),
Ssex char(2),
Sage int,
primary key (Sno));
- 可写成一行或多行,推荐后者
- 注意标点,均为英文标点
- 写在txt中,然后拷入cmd,以便修改
- 查看数据库中所有表名:show tables;
- 查看某表格的描述信息:desc S;
creat table grade(
year int,
prov char(100),
ybx int,
jsMax int,
jsMin int,
jsAvg int,
hxMax int,
hxMin int,
hxAvg int,
primary key (year,prov)
);
6.3、录取分数数据管理(II)
6.3.1、数据更新
-
插入数据(若属性名与表中数量、顺序相同,则可以省略)
insert into S values ('S1','Zhang','M',19);
-
查看表中所有数据:
select * from S;
-
修改数据
update S 改那个表 set Sage = Sage + 1 怎么改 where Ssex = 'M'; 改哪些
-
删除数据
delete from S 从那个表删 where Sage>18; 删哪些
6.3.2、利用Python访问MySQL
import pymysql
#格式化打印游标中存放的结果
def display(cursor):
#获取结果,结果的类型是嵌套元组,即元组中包含了很多小元组,小元组对应结果的一行
records = cursor.detchall()
print('\n-----',len(records),'lines -----') #总行数
for rec in records: #对于每个小元组rec(对应表中一行)
s = ''
for value in rec : #value相当于一行中的一个单元格
s = s+str(value)+'\t' #用制表符把这一行个单元格拼接成一个字符串
print(s)
#连接数据库,相当于在命令行中执行mysql -uroot -p
conn = pymysql.connect(host = 'localhost', #MySQL所在主机(主机名、IP地址或域名),localhost为本机
user = 'root', #账号
password = '11111',#密码,根据情况进行修改
charset = 'gbk') #字符编码方式
#print(conn.get_host_info()) #显示MySQL所在主机信息(主机、端口等)
#获取游标
cs = conn.cursor() #用于执行SQL语句并存放结果
#创建数据库
cs.execute('drop database if exists nudt') #如存在nudt数据库则删除,execute函数用于执行括号内的SQL语句,若有结果则存于游标cs中
cs.execute('create databases nudt') #创建nudt数据库
cs.execute('show databases') #获取所有数据库名字
display(cs) #格式化打印所有数据库名字
#创建表grade
conn.select_db('nudt') #选择数据库nudt,相当于use nudt
cs.execute('create table grade(\
year int,\
prov char(100),\
jsMax int,\
jsMin int,\
jsAvg int,\
hxMax int,\
hxMin int,\
hxAvg int,\
primary key (year,prov))') #创建grade表
cs.execute('desc grade') #获取表格的描述信息
display(cs) #打印表格描述信息
#提交和关闭
conn.commit() #提交结果
cs.close() #关闭游标
conn.close() #断开连接
6.3.3、字符串格式化
- 占位符:整型(%d)、浮点型(%f)、字符串(%s)……
- 格式设置
6.3.4、载入程序
-
SQL数据更新:insert、updata、delete
-
利用Python访问MySQL:连接·用游标执行SQL语句·断开与关闭
import pymysql #格式化打印游标中存放的结果 def display(cursor): records=cursor.fetchall() #获取结果,结果的类型是嵌套元组,即元组中包含了很多小元组,小元组对应结果中的一行 print('\n-----', len(records), 'lines -----') #总行数 for rec in records: #对于每个小元组rec(对应表中一行) s='' for value in rec: #value相当于一行中的一个单元格 s=s+str(value)+'\t' #用制表符把这一行各单元格拼接成一个字符串 print(s) #连接数据库,相当于在命令行中执行mysql -uroot -p conn=pymysql.connect(host='localhost', #MySQL所在主机(主机名、IP地址或域名),localhost为本机 user='root', #账号 passwd='111111', #密码,根据情况进行修改 charset='gbk') #字符编码方式 #print(conn.get_host_info()) #显示MySQL所在主机信息(主机、端口等) #获取游标 cs = conn.cursor() #用于执行SQL语句并存放结果 #创建数据库 cs.execute('drop database if exists nudt') #若存在nudt数据库则删除,execute函数用于执行括号内的SQL语句,若有结果则存于游标cs中 cs.execute('create database nudt') #创建nudt数据库 cs.execute('show databases') #获取所有数据库名字 #display(cs) #格式化打印所有数据库名字 #创建表grade conn.select_db('nudt') #选择数据库nudt,相当于use nudt cs.execute('create table grade(\ year int,\ prov char(100),\ ybx int,\ jsMax int,\ jsMin int,\ jsAvg int,\ hxMax int,\ hxMin int,\ hxAvg int,\ primary key (year, prov))') #创建grade表(斜杠用于换行) cs.execute('desc grade') #获取表格的描述信息 #display(cs) #打印表格的描述信息 #载入数据:将三个txt中的数据插入grade表 for year in range(2014, 2017): #对于2014~2016年中的某一年 f=open(str(year)+'年数据.txt', 'r') #打开这一年数据所在的txt文件 while True: #依次处理文件中的每一行 line=f.readline() #读取一行 if line=='': #若这一行为空,表示文件读取完毕,跳出循环 break v=line.split() #拆分这一行,得到对应的属性值 #构建这一行对应的insert语句(斜杠用于换行) sql='insert into grade values\ (%s, "%s", %s, %s, %s, %s, %s, %s, %s)'\ % (year,v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]) cs.execute(sql) #执行插入语句,将这一行添加到grade表 f.close() cs.execute('select * from grade') #查询表中所有数据 display(cs) #提交和关闭 conn.commit()#提交结果 cs.close() #关闭游标 conn.close() #断开连接
6.4、录取分数数据管理(III)
6.4.1、单表查询I
-
查询所有学生的所有信息
select * 所有属性 from S; 从哪查
-
查询所有学生的姓名和性别
select Sname,Ssex 某些属性 from S;
-
查询所有学生的姓名和性别,按性别升序排列
select Sname,Ssex from S order by Ssex asc; 升序:asc,降序:desc
-
查询所有学生的姓名和出生年份
select Sname,2020-Sage from S;
-
查询学生的平均年龄
select avg(Sage) from S
-
查询学生的总人数
select count(Sno) from S;
-
查询学生年龄,升序排列
select Sage form S order by Sage asc;
-
查询学生年龄,升序排列,不重复
select distinct Sage from S order by Sage asc;
6.4.2、单表查询II
-
查询女同学的姓名
select Sname 挑选列(投影) from S where Ssex = 'F'挑选行(选择)
-
查询18岁以上同学的姓名和年龄
select Sname,Sage from S where Sage>18;
-
查询18~20岁(包括)的同学的姓名和年龄
select Sname,Sage from S where Sage>=18 and Sage<=20; 还可以使用or、not
6.4.3、多表查询
-
连接的两种方式
select Sname from SC join S on S.Son = SC.Sno where Cno = 'C7'; 第二种 select Sname from SC ,S where S.Sno = SC.Sno and Cno = 'C7';
6.4.2、在Python中查询
import pymysql
import matplotlib pyplot as plt
#格式化打印
def display(cursor):
records = cursor.fetchall()
print('\n-----',len(records),'line -----')
for rec in records:
s = ''
for value in rec:
s = s+str(value)+'\t'
print(s)
#图形化显示
def plot(cursor):
records = cursor.fetchall()
prov.frades = [],[]
for rec in records:
prov.append(rec[0])
grades.append(int(rec[1]))
plt.barh(range(len(grades)),grades,color = 'rgb',tick_lable = prov) #barh是横向柱状图
plt.show()
conn = pymysql.connect(host = 'localhost',
user = 'root',
password = '1111',
charset = 'gbk') #连接数据库
conn.select_db('nudt') #选择数据库
cs = conn.cursor() #创建游标
sql = 'select prov , jsAvg from grade where year = 2016'
#sql = 'select prov,ybx from grade where year = 2015 order by ybx desc'
cs.esecute(sql) #执行查询语句
#display(cs) #打印结构
plot(cs) #绘制结果
cs.close() #关闭游标
conn.close() #断开连接
6.5、单元小结
#读取一行
if line==‘’: #若这一行为空,表示文件读取完毕,跳出循环
break
v=line.split() #拆分这一行,得到对应的属性值
#构建这一行对应的insert语句(斜杠用于换行)
sql=‘insert into grade values
(%s, “%s”, %s, %s, %s, %s, %s, %s, %s)’
% (year,v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7])
cs.execute(sql) #执行插入语句,将这一行添加到grade表
f.close()
cs.execute(‘select * from grade’) #查询表中所有数据
display(cs)
#提交和关闭
conn.commit()#提交结果
cs.close() #关闭游标
conn.close() #断开连接
##### 6.4、录取分数数据管理(III)
###### 6.4.1、单表查询I
* 查询所有学生的所有信息
```mysql
select * 所有属性
from S; 从哪查
-
查询所有学生的姓名和性别
select Sname,Ssex 某些属性 from S;
-
查询所有学生的姓名和性别,按性别升序排列
select Sname,Ssex from S order by Ssex asc; 升序:asc,降序:desc
-
查询所有学生的姓名和出生年份
select Sname,2020-Sage from S;
-
查询学生的平均年龄
select avg(Sage) from S
-
查询学生的总人数
select count(Sno) from S;
-
查询学生年龄,升序排列
select Sage form S order by Sage asc;
-
查询学生年龄,升序排列,不重复
select distinct Sage from S order by Sage asc;
6.4.2、单表查询II
-
查询女同学的姓名
select Sname 挑选列(投影) from S where Ssex = 'F'挑选行(选择)
-
查询18岁以上同学的姓名和年龄
select Sname,Sage from S where Sage>18;
-
查询18~20岁(包括)的同学的姓名和年龄
select Sname,Sage from S where Sage>=18 and Sage<=20; 还可以使用or、not
6.4.3、多表查询
-
连接的两种方式
select Sname from SC join S on S.Son = SC.Sno where Cno = 'C7'; 第二种 select Sname from SC ,S where S.Sno = SC.Sno and Cno = 'C7';
6.4.2、在Python中查询
import pymysql
import matplotlib pyplot as plt
#格式化打印
def display(cursor):
records = cursor.fetchall()
print('\n-----',len(records),'line -----')
for rec in records:
s = ''
for value in rec:
s = s+str(value)+'\t'
print(s)
#图形化显示
def plot(cursor):
records = cursor.fetchall()
prov.frades = [],[]
for rec in records:
prov.append(rec[0])
grades.append(int(rec[1]))
plt.barh(range(len(grades)),grades,color = 'rgb',tick_lable = prov) #barh是横向柱状图
plt.show()
conn = pymysql.connect(host = 'localhost',
user = 'root',
password = '1111',
charset = 'gbk') #连接数据库
conn.select_db('nudt') #选择数据库
cs = conn.cursor() #创建游标
sql = 'select prov , jsAvg from grade where year = 2016'
#sql = 'select prov,ybx from grade where year = 2015 order by ybx desc'
cs.esecute(sql) #执行查询语句
#display(cs) #打印结构
plot(cs) #绘制结果
cs.close() #关闭游标
conn.close() #断开连接
6.5、单元小结
[外链图片转存中…(img-wBD1GB1f-1735281118896)]