程序控制结构

0x1 程序的分支结构

单分支结构

if <条件>:
<语句块>

二分支结构

if <条件>:
<语句块1>
else:
<语句块2>

#示例:
guess = eval(input())
if guess == 99:
print("猜{}了".format("对"))
else:
print("猜{}了".format("错"))

#紧凑形式:
<表达式1> if <条件> else <表达式2>

guess = eval(input())
print("猜{}了".format("对" if guess == 99 else "错"))

紧凑形式中,if,else所对应的不是语句,而是表达式,不能赋值,只能放在类似上述的执行语句中

多分支

if <条件> :
<语句块1>
elif:
<语句块2>
else:
<语句块3>

条件判断操作符与C相同

逻辑保留字

and(&&)、or(||)、not(!)

if A > B or B < A :
<执行语句>

0x2 程序的异常处理

abc = eval(input("请输入数字"))
print(num**2)
请输入数字0.2

Traceback (most recent call last):
File "E:\python_item\text1.py", line 2, in <module>
print(num**2)
NameError: name 'num' is not defined

NameError 是python内部预定义的错误名称,可以作为错误类型进行判断

类似的python内部有许多错误名称,都可以用来判断

异常处理的基本使用

#执行出错执行下方操作
try:
<语句块1>
except:
<语句块2>

#判断是否属于某种错误,该错误再执行下方操作
try:
<语句块1>
except <异常名称>:
<语句块2>

#异常处理的高级使用
try:
<语句块1>
except: #发生异常时执行
<语句块2>
else: #不发生异常时执行
<语句块3>
finally: #finally对应语句块4一定执行
<语句块4>

0x3 身体质量指数BMI

问题分析:body Mass index

定义:BMI = 体重(kg)/身高^2 (m^2)

国际标准:世界卫生组织 国内:国家卫生健康委员会

分类 国际BMI(kg/m^2) 国内BMI值(kg/m^2)
偏瘦 < 18.5 < 18.5
正常 18.5~25 18.5~24
偏胖 25~30 24~28
肥胖 ≥30 ≥28

问题需求:输入体重和身高值

#CalBMIv1.py
height,weight = eval(input("请输入身高(米)和体重\(公斤)[逗号隔开]"))
bmi = weight / pow(height,2)
print("BMI 数值为:{:.2f}".format(bmi))
who = ''
if bmi < 18.5:
who = "偏瘦"
elif 18.5 <= bmi <25 :
who = "正常"
elif 25 <= bmi < 30:
who = "偏胖"
else:
who = "肥胖"
print("BMI 指标为:国际'{0}'".format(who))

#输出:
请输入身高(米)和体重\(公斤)[逗号隔开]1.8,73
BMI 数值为:22.53
BMI 指标为:国际'正常'

#CalBMIv2.py
height,weight = eval(input("请输入身高(米)和体重\(公斤)[逗号隔开]"))
bmi = weight / pow(height,2)
print("BMI 数值为:{:.2f}".format(bmi))
who,nat = "",""
if bmi < 18.5:
who,nat = "偏瘦","偏瘦"
elif 18.5 <= bmi <24 :
who,nat= "正常","正常"
elif 24 <= bmi < 25:
who,nat= "正常","偏胖"
elif 25 <= bmi < 28:
who,nat= "偏胖", "偏胖"
elif 28 <= bmi < 30:
who,nat= "偏胖","肥胖"
else:
who,nat= "肥胖","肥胖"
print("BMI 指标为:国际'{0}',国内'{1}'".format(who,nat))

#输出:
请输入身高(米)和体重\(公斤)[逗号隔开]1.8,73
BMI 数值为:22.53
BMI 指标为:国际'正常',国内'正常'

多分支组合注意

多分支条件之间的覆盖要分析清除

程序可运行,但不正确要注意多分支

阅读代码时,先看分支

0x4 程序的循环结构

for遍历

for <循环变量> in <遍历结构>:
<语句块>

for i in range(N): # range(N)产生数字序列,包含N个元素 0 到 N-1.
<语句块>

for i in range(M,N,K): #产生以M开始不到N的以K为步长取数的序列

for c in s : #字符串遍历,s是字符串,取出s中每个字符到循环变量中,执行语句

for item in ls : #对列表进行遍历,取出每个列表元素遍历 [123,"PY",456]

for line in fi : #文件遍历循环,fi文件标识符,遍历文件每一行,
print(line) #打印每行

还可以对元组等遍历循环,只要是多个元素组成的数据结构,都可以用for in 遍历

逐一从遍历结构中提取元素到循环变量中,然后执行语句块

while循环

while <条件判断> :
<语句块>

循环控制保留字

break 和 continue 与 C 含义相同

for c in "PYTHON" :
if c =="T":
break #或者写continue
print(c , end ='')

循环高级用法

#else没有被break退出时,循环正常完成,则执行else语句
#for循环加else
for <循环变量> in <遍历结构> :
<语句块1>
else:
<语句块2>

#while循环加else
while <条件> :
<语句块1>
else:
<语句块2>

0x5 random库使用

random库介绍

random库时使用随机数的python标准库,主要用于生成随机数

伪随机数:采用梅森旋转算法生成的伪随机序列中元素

import random
基本随机数函数:seed(),random()
扩展随机数函数:randint(),getrandbits(),uniform(),randrange(),choice(),shuffle()

基本随机数函数

随机数种子:用来通过梅森旋转算法产生随机序列,随机序列中的数就是随机数

函数 描述
seed(a = None) 初始化给定的随机数种子,默认为当前系统时间(精确到微妙)
random() 生成一个[0.0 ,1.0)之间的随机小数
>>> import random
>>> random.seed(1)
>>> random.random()
0.13436424411240122
>>> random.random()
0.8474337369372327
#设定seed(10),在不同设备上产生的随机数时一致的,为了再现随机程序,再次设定后调用产生的随机数结果也是一样的

扩展随机数函数

函数 描述
randint(a,b) 生成一个[a,b]之间的随机整数
randrange(m,n[,k]) 生成一个[m,n]之间以k为步长的随机整数
getrandbits(k) 生成一个k比特长度随机整数
uniform(a,b) 生成一个[a,b]之间的随机小数,16位精度
choice(seq) 从序列seq中随机选择一个元素
shuffle(seq) 将序列seq中元素随机排列,返回打乱后的序列
>>> random.randint(1,100)
98
>>> random.randrange(0,100,10)
40

>>> random.getrandbits(8)
126
>>> random.getrandbits(32)
3268308804

>>> random.uniform(1,10)
5.045419583098643

>>> s = [1,2,3,4,5,6,7,8,9,0]
>>> random.choice(s)
7
>>> random.shuffle(s)
>>> print(s)
[5, 9, 3, 7, 6, 0, 1, 8, 2, 4]
>>> random.shuffle(s)
>>> print(s)
[8, 2, 1, 4, 0, 5, 3, 9, 7, 6]

>>> import random;s=[1,2,3,4,5];random.shuffle(s);print(s) #可以用分号;将语句放到一行
[3, 1, 5, 2, 4]

0x6 实例 圆周率计算

问题分析

圆周率的近似计算公式

无限求和公式

π=k=0[116k(48k+128k+418k+518k+6)]\pi = \sum_{k = 0}^{\infty }[\frac{1}{16^{k}}\left ( \frac{4}{8k+1} -\frac{2}{8k+4}-\frac{1}{8k+5}-\frac{1}{8k+6}\right )]

蒙特卡罗方法

对正方形随机撒点,撒点数量的比值

s3tylj.png

公式法

#CalPiv1.py
pi = 0
N = 100
for k in range(N):
pi += 1/pow(16,k)*( \ # \ 可用于换行,不影响程序运行可以多次使用,提高可读性
4/(8*k +1) - 2/(8*k +4) - \
1/(8*k +5) - 1/(8*k+6))
print("圆周率值是:{}".format(pi))

输出:
圆周率值是:3.141592653589793

蒙特卡罗法

#CalPiv1.py
from random import random
from time import perf_counter
DARTS = 10000*10000
hits = 0.0
start = perf_counter()
for i in range(1,DARTS+1):
x,y = random(),random()
dist = pow(x**2+y**2,0.5)
if dist <= 1.0:
hits = hits + 1
pi = 4 *(hits/DARTS)
print("圆周率值是:{}".format(pi))
print("运行时间是:{:.5f}s".format(perf_counter()-start))

圆周率值是:3.143908
运行时间是:0.71663s

圆周率值是:3.14156908
运行时间是:59.99088s

理解方法思维

数学思维

计算思维

四色定理

  • 程序运行时间分析

    程序运行80%的时间消耗在不到10%的循环代码上

    用于求解某个特定图形的面积

函数和代码复用

0x1 函数的定义及使用

函数的理解与定义

是一种抽象

定义的时候可以没有参数,但必须有括号

def <函数名>(参数):
<函数体>
return <返回值>

示例:
def dayUP(df): #函数dayUP
dayup = 1
for i in range(365):
if i % 7 in[6,0]:
dayup = dayup*(1 - 0.01)
else:
dayup = dayup * (1 + df)
return dayup

函数的使用及调用过程

函数调用是,用实际值替换函数中参数

函数的参数传递

可选参数传递

#调用参数时,必须有必选参数。可选参数可以没有,如果没有,则使用定义的默认值
def <函数体>(<必选参数>,<可选参数>):
<函数体>
return <返回值>

示例:
#1
def fact(n,m=1):
s = 1
for i in range(1,n+1):
s *= i
return s//m
print(fact(10))
3628800

#2计算n的阶乘,m = 1是默认的参数,不给指定参数则默认为1
def fact(n,m=1):
s = 1
for i in range(1,n+1):
s *= i
return s//m
print(fact(10,5))
725760

可变参数传递

#多个可变参数调用
def fact(n,*b): # *b表示可变参数
s = 1
for i in range(1,n+1):
s *= i
for item in b : #如果b是一个列表, in b 将依次调用 b 中的值赋给item
s *= item
return s

示例:n!乘数
def fact(n,*b): # *b表示可变参数
s = 1
for i in range(1,n+1):
s *= i
for item in b : #如果b是一个列表, in b 将依次调用 b 中的值赋给item
s *= item
return s

print(fact(10,11,12,13))
print(fact(13))

6227020800
6227020800

函数调用时,参数可以按照位置或名称方式传递(代表地址)

位置传递

名称传递

sgnAs0.png

函数的返回值

return,和c类似,不一定有返回值,或者传多个

但是返回的语法不同

sgntoD.png

多个返回的是 元组数据类型

>>> def fact(n,m=1) :
s = 1
for i in range(1,n+1):
s *= i
return s//m,n,m

>>> a,b,c = fact(10,5) #元组类型赋值,输出
>>> print(a,b,c)
725760 10 5
>>>

局部变量和全局变量

函数定义,就属于全局变量

规则1 局部变量与全局变量不同

函数定义的函数体中的是局部变量

函数运算结束后,局部变量会释放

函数内部的局部变量可以可以和外部的变量重名,但不同

全局变量的函数调用

#使用 global 保留字在函数内部使用全局变量
n,s = 10 , 100
def fact(n):
s = 1
for i in range(1, n+1):
s *= i
return s
print(fact(n),s) #此处s 是全局变量s

——————————————————————————————————————————

n,s = 10 , 100
def fact(n):
global s #此处表示使用的是全局变量S
for i in range(1, n+1):
s *= i
return s #此处是指全局变量s的运算结果
print(fact(n),s) #此处s 是全局变量s,但是被函数运算修改了
规则2

局部变量为组合数据类型且在函数内部未创建时,且它的名字和全局变量同名,则该函数内部的变量等同于全局变量,即全局变量会发生改变

#ls在函数内部为全局变量

ls = ["F","f"] #通过使用[]“真实"创建了一个全局变量列表ls
def func(a) :
ls.append(a) #此处ls是列表类型,未真实创建则等同于全局变量
return
fun("C") #全局变量ls被修改
print(ls)

运行结果
['F','f','C']

-------------------------------
#ls在函数内部为局部变量

ls = ["F","f"] #通过使用[]“真实"创建了一个全局变量列表ls
def func(a) :
ls = [] #此处在函数内部被真实创建,此时则为局部变量
ls.append(a) #此处ls是列表类型
return
fun("C")
print(ls)

运行结果
['F','f','C']

此处组合数据类型与C语言中的指针相对应,如果在函数内部没有创建,则以指针的方式调用外部变量

规则总结

基本数据类型,无论是否重名,局部变量与全局变量不同,可以通过global保留字在函数内部声明全局变量

组合数据类型,如果局部百年来未真实创建,则是全局变量

lambda函数

返回一个函数名,是一种匿名函数

用于定义简单的、能够在一行内表示的函数

<函数名> = lambda <参数>:<表达式>

等价于def,区别是,内容只能是表达式,不能是函数体

>>> f = lambda x,y: x+y
>>> f(10,15)
25

>>> f = lambda : "lambda函数"
>>> print(f())
lambda函数

建议使用def定义函数,特殊情况使用lambda

0x2 实例七段数码管绘制

问题分析

七段不同的数码管的亮暗,可以显示数字,字母

用程序绘制七段数码管

效果

s2pROJ.png

基本思路

绘制单个数字,对应数码管

获得一串数字,一一表示

获得系统时间,表示出来

代码

第一步,绘制单个数字,对应数码管

import turtle
def drawLine(draw): #单段数码管,函数绘制一条线,并且判断该线是越过还是画
turtle.pendown()if draw else turtle.penup()
turtle.fd(40)
turtle.right(90)
def drawDight(digit): #根据数字绘制七段数码管
drawLine(True) if digit in [2,3,4,5,6,8,9] else drawLine(False)
drawLine(True) if digit in [0,1,3,4,5,6,7,8,9] else drawLine(False)
drawLine(True) if digit in [0,2,3,5,6,8,9] else drawLine(False)
drawLine(True) if digit in [0,2,6,8] else drawLine(False)
turtle.left(90)
drawLine(True) if digit in [0,4,5,6,8,9] else drawLine(False)
drawLine(True) if digit in [0,2,3,5,6,7,8,9] else drawLine(False)
drawLine(True) if digit in [0,1,2,3,4,7,8,9] else drawLine(False)
turtle.left(180)
turtle.penup() #为绘制后续数字确定位置
turtle.fd(20) #为绘制后续数字确定位置

第二步,获得一串数字,一一表示

def drawDate(date):  #获得要输出的数字
for i in date:
drawDight(eval(i)) #通过eval()函数将数字变成整数
def main():
turtle.setup(800,350,200,200)
turtle.penup()
turtle.fd(-300)
turtle.pensize(5)
drawDate('20181010')
turtle.hideturtle()
turtle.done()
main()

第三步,获得系统时间,表示出来

import turtle
import time
def drawLine(draw): #单段数码管,函数绘制一条线,并且判断该线是越过还是画
turtle.pendown()if draw else turtle.penup()
turtle.fd(40)
turtle.right(90)
def drawDight(digit): #根据数字绘制七段数码管
drawLine(True) if digit in [2,3,4,5,6,8,9] else drawLine(False)
drawLine(True) if digit in [0,1,3,4,5,6,7,8,9] else drawLine(False)
drawLine(True) if digit in [0,2,3,5,6,8,9] else drawLine(False)
drawLine(True) if digit in [0,2,6,8] else drawLine(False)
turtle.left(90)
drawLine(True) if digit in [0,4,5,6,8,9] else drawLine(False)
drawLine(True) if digit in [0,2,3,5,6,7,8,9] else drawLine(False)
drawLine(True) if digit in [0,1,2,3,4,7,8,9] else drawLine(False)
turtle.left(180)
turtle.penup() #为绘制后续数字确定位置
turtle.fd(20) #为绘制后续数字确定位置
def drawDate(date): #获得要输出的数字
for i in date:
drawDight(eval(i)) #通过eval()函数将数字变成整数
def main():
turtle.setup(800,350,200,200)
turtle.penup()
turtle.fd(-300)
turtle.pensize(5)
drawDate(time.strftime("%H%M%S"))
turtle.hideturtle()
turtle.done()
main()

代码优化

增加绘制间的距离

增加绘制年月日

获取时间

import turtle
import time
def drawGap():
turtle.penup()
turtle.fd(5)
def drawLine(draw): #单段数码管,函数绘制一条线,并且判断该线是越过还是画
drawGap()
turtle.pendown()if draw else turtle.penup()
turtle.fd(40)
drawGap()
turtle.right(90)
def drawDight(digit): #根据数字绘制七段数码管
drawLine(True) if digit in [2,3,4,5,6,8,9] else drawLine(False)
drawLine(True) if digit in [0,1,3,4,5,6,7,8,9] else drawLine(False)
drawLine(True) if digit in [0,2,3,5,6,8,9] else drawLine(False)
drawLine(True) if digit in [0,2,6,8] else drawLine(False)
turtle.left(90)
drawLine(True) if digit in [0,4,5,6,8,9] else drawLine(False)
drawLine(True) if digit in [0,2,3,5,6,7,8,9] else drawLine(False)
drawLine(True) if digit in [0,1,2,3,4,7,8,9] else drawLine(False)
turtle.left(180)
turtle.penup() #为绘制后续数字确定位置
turtle.fd(20) #为绘制后续数字确定位置
def drawDate(date): #改获得日期格式为,'%Y-%m=%d+',判断符号进行替换
turtle.pencolor("red")
for i in date:
if i == '-':
turtle.write('年',font=("Arial",30,"normal"))
turtle.pencolor("green")
turtle.fd(40)
elif i == '=' :
turtle.write('月',font=("Arial",30,"normal"))
turtle.pencolor("blue")
turtle.fd(40)
elif i == '+' :
turtle.write('日',font=("Arial",30,"normal"))
else:
drawDight(eval(i)) #通过eval()函数将数字变成整数
def main():
turtle.setup(800,350,200,200)
turtle.penup()
turtle.fd(-300)
turtle.pensize(5)
drawDate(time.strftime('%Y-%m=%d+',time.gmtime()))
turtle.hideturtle()
turtle.done()
main()

举一反三

理解模块化方法思维:确定模块接口,封装功能

规则化思维:抽象过程为规则,

化繁为简:分治

扩展

到小数点

倒计时时刷新

14段的数码管

数码管有更多段

0x3 代码复用与函数递归

代码复用与模块化设计

代码资源化:程序代码是一种用来表达计算的”资源“

代码抽象化:使用函数等方法对代码赋予更高级别的定义

代码复用:函数和对象

函数:将代码命名,在代码层面建立了初步抽象

对象:属性和方法,在函数之上再次组织进行抽象

<a>.<b> 和 <a>.<b>()

分而治之

通过函数或对象分装将程序划分为模块及模块间的表达

具体包括:主程序、子程序、和子程序的关系

紧耦合 交流多无法独立

松耦合 交流少可以独立

函数内部要紧耦合,模块之间要松耦合

函数递归的理解

函数中调用自身

函数递归的调用过程

def fact(n):
if n == 0:
return 1
else :
return n*fact(n-1)
fact(5)

函数递归实例解析

字符串反转

将字符串s反转后输出

s[::-1]

函数 +分支结构

递归链条

递归基例

>>> def rvs(s):
if s == "" :
return s
else :
return rvs(s[1:])+s[0]

>>> s = '这是一个字符串'
>>> rvs('这是一个字符串')
'串符字个一是这'
斐波那契数列
def f(n):
if n==1 or n==2 :
return 1
else :
return f(n-1) + f(n-2)
汉诺塔问题

思考n-1和n的关系

count = 0
def hanoi(n,src,dst,mid):
global count
if n == 1:
print("{}:{}->{}".format(1,src,dst))
count += 1
else :
hanoi(n-1,src,mid,dst)
print("{}:{}->{}".format(n,src,dst))
count += 1
hanoi(n-1,mid,dst,src)
hanoi(3,"A","C","B")
print(count)

输出
1:A->C
2:A->B
1:C->B
3:A->C
1:B->A
2:B->C
1:A->C
7

0x4 PyInstaller库的使用

基本介绍

将.py源代码转换为无需源代码的可执行程序文件

windows(exe)、linux、macos均可

它是一个第三方库

需要额外安装

使用pip工具安装

在cmd中输入

pip install pyinstaller

使用说明

(cmd命令执行) pyinstaller -F <文件名.py>

sR5VBD.png

帮助显示命令

(cmd命令执行) pyistaller -h 

更多常用参数

sRopS1.png

实例

产生有图标的文件

sRIcsf.png

0x5 实例 科赫雪花小包裹

科赫曲线

分形几何

有迭代关系的几何图形

用python绘制科赫曲线

sRTFcq.png

绘制不同阶数的科赫曲线

import turtle
def koch(size,n) : #确定大小和阶数
if n == 0: #当n=0时,画直线
turtle.fd(size)
else:
for angle in [0,60,-120,60]: #一阶曲线
turtle.left(angle)
koch(size/3,n-1)
def main():
turtle.setup(800,400)
turtle.penup()
turtle.goto(-300,-50)
turtle.pendown()
turtle.pensize(2)
koch(600,3) #3阶科赫曲线,阶数
turtlw.hideturtle()

连成雪花

import turtle
def koch(size,n) : #确定大小和阶数
if n == 0: #当n=0时,画直线
turtle.fd(size)
else:
for angle in [0,60,-120,60]: #一阶曲线
turtle.left(angle)
koch(size/3,n-1)
def main():
turtle.setup(600,600)
turtle.penup()
turtle.goto(-200,100)
turtle.pendown()
turtle.pensize(2)
level = 4
koch(400,level) #3阶科赫曲线,阶数
turtle.right(120)
koch(400,level)
turtle.right(120)
koch(400,level)
turtlw.hideturtle()
main()

科赫雪花小包裹

用pylnstaller打包

绘制条件的扩展

修改阶数

修改科赫曲线的基本定义及旋转角度

修改绘制科赫雪花的基础框架图形

分形几何很多

康托尔集

谢尔宾斯基三角形

门格海绵,龙形曲线,空间填充曲线

组织数据类型

一个数据表达一个含义

一组数据表达多个含义

类型结构:

集合类型、序列类型、字典类型

0x1 集合类型及操作

集合类型定义

多个元素的无需组合

与数学概念一致

集合元素之间无序,每个元素唯一,不存在相同元素

集合元素不可更改,不能是可变数据类型

建立集合

集合用{ } 建立或set(),元素用逗号分隔

建立空集合必须用set(),相同元素合并

>>> A = {"python",123,("python",123)}
>>> print(A)
{123, 'python', ('python', 123)}

>>> B = set("pupu123")
>>> print(B)
{'3', 'p', '2', '1', 'u'}

元素唯一,无序,{}表示逗号分隔

集合操作符

sWYJ91.png

sWY8hR.png

关系操作符返回true或false

增强操作符

sW38QU.png

>>> A = {"p","y",123}
>>> B = set("pypy123")
>>> print(B)
{'1', 'y', '3', '2', 'p'}
>>> print(A)
{'p', 123, 'y'}

>>> A - B
{123}

>>> A | B
{'1', 'y', '3', '2', 'p', 123}

>>> A & B
{'p', 'y'}

>>> A ^ B
{'3', '1', '2', 123}

集合处理方法

sWtqJA.png

sWU5Ue.png

输出全部元素实例

#方法1 遍历
A = {"p","y",123}
for item in A:
print(item,end="")

y123p

#方法2 使用pop函数
try:
while True:
print(A.pop(),end="")
except:
pass

y123p

python存储元素与实际计算机存储的元素顺序不相符,固输出顺序不同

集合类型应用场景

包含关系比较

>>> "p" in {"p","y",123}
True
>>> {'p','y'} >= {"p","y",123}
False

数据去重

利用集合元素无序且唯一的特点对数据去重

ls = ["p","p","y","y",123]
s =set(ls) #此处将列表类型转换为集合类型
{'p','y',123}
lt = list(s) #此处为集合类型转换为列表类型
['p','y',123]

#程序运行
>>> ls = ["p","p","y","y",123]
>>> s =set(ls)
>>> lt = list(s)
>>> print(lt)
['y', 123, 'p']

0x2 序列类型及操作

序列类型定义

序列具有先后关系的一组元素

序列是一维元素向量,元素类型可以不同

类似数学元素序列:S0,S1,…,Sn-1

元素间由序号引导,通过下标访问序列的特定元素

序列是一个基类类型

序列类型,衍生出字符串类型、元组类型、列表类型

序号的定义

sWr5LR.png

序列处理函数及方法

6个操作符

sWO1yj.png

实例

>>> ls = ["python",123,".io"]
>>> ls[::-1]
['.io', 123, 'python']
>>> s = "python123.io"
>>> s[::-1]
'oi.321nohtyp'

五个函数和方法

sfSTBQ.png

例子

>>> ls = ["python",123,".io"]
>>> len(ls)
3
>>> s = "python123.io"
>>> max(s)
'y' #根据字母排序得出
>>> t = "a987b" #字母大于数字
>>> max(t)
'b'
>>> t = "0987341"
>>> max(t)
'9'

元组类型及操作

序列类型的扩展

一旦创建不能被修改

使用小括号()或者tuple创建,元素间用逗号分隔

可以不适用或使用小括号

返回的实际上是一个值,返回的数据类型是元组类型

def func():
return 1,2
元组类型定义
>>> create = "cat","dog","tiger","human"
>>> create
('cat', 'dog', 'tiger', 'human')
>>> color = (0x001100,"blue",create)
>>> color
(4352, 'blue', ('cat', 'dog', 'tiger', 'human'))

继承序列的全部通用操作

列表类型及操作

列表是一种序列类型,创建后可以随意被修改

使用方括号[]或list()创建,元素间用逗号,分隔

列表中类型可以不同,没有长度限制

列表类型定义

此处并没有真正的将ls列表内的值赋给lt,而是将该列表新定义了一个名字

这里使用了内存和指针的概念

['cat', 'dog', 'tiger', 'human', 1024]
>>> lt = ls
>>> lt
['cat', 'dog', 'tiger', 'human', 1024]

列表类型的操作函数和方法

sfe7Hx.png

实例

切片替换

>>> ls = ['cat', 'dog', 'tiger', 'human',1024]
>>> ls[1:2]
['dog']
>>> ls[1:2] = [1,2,3,4]
>>> ls
['cat', 1, 2, 3, 4, 'tiger', 'human', 1024]

删除

['cat', 1, 2, 3, 4, 'tiger', 'human', 1024]
>>> del ls[::3]
>>> ls
[1, 2, 4, 'tiger', 1024]
更多方法

sfmHMj.png

序列类型应用场景

用于数据表示

元组用于元素不改变的应用场景,更多用于固定搭配场景

列表更灵活,是最常用的序列类型

表示一组有序数据,进而操作它们

元素遍历

for item in ls :
<语句块>

for item in tp :
<语句块>

数据保护

将列表类型转换为元组类型,从而达到保护数据的目的

>>> ls = ["cat","dog","tiger",1024]
>>> lt = tuple(ls) #用于将列表类型转换为元组类型
>>> lt
('cat', 'dog', 'tiger', 1024)

元组类型数据不会修改数据,在多人写程序的情况,接口的传递

实例 基本统计值计算

基本统计值

总个数、求和、平均值、方差、中位数

总个数:len()

求和:for …in

平均值:求和/总个数

方差:各数据与平均数差的平方的和的平均数

中位数:排序,然后…奇数找最中间的1个,偶数找中间2个取平均

通过函数,完成不同的功能

假定数据是用户输入,数量不确定

用户输入和输入结束函数

def getNum():
nums =[]
iNumStr = input("请输入数字(回车退出):")
while iNumStr != "": #当输入为空是退出
nums.append(eval(iNumStr))
iNumStr =input("请输入数字(回车退出):")
return nums

求和

def mean(numbers):  #计算平均值
s = 0.0
for num in numbers:
s = s + num
return s / len(numbers)

计算方差

def dev(numbers,mean):   #输入numbers列表,mean是平均值
sdev = 0.0
for num in numbers :
sdev = sdev + (num - mean)**2 #取出每个数与平均值做差求平方,累加
return pow(sdev/(len(numbers)-1),0.5) #对中位数开方返回

计算中位数

def median(numbers):
sorted(numbers)
size = len(numbers)
if size % 2 == 0:
med = (numbers[size//2-1] + numbers[size//2])/2
else:
med = numbers[size//2]
return med

调用

n = getNum()
m = mean(n)
print("平均值:{},方差:{:.2},中位数:{}.".format(m,dev(n,m),median(n)))

举一反三

获取多个用户输入的方法

分隔多个函数,模块化

字典类型及操作

字典类型定义

映射

索引和数据的对应关系,键和值

属性和值,一种属性对应一个值

例如

"streetAddr":"中关村南大街5号"
"zipcode": "100081"

比较序列类型和映射类型

shi7Cj.png

字典类型是映射的体现

键相当于值的标签,找到标签就可获得值

键值对:键是数据索引的扩展

字典是键值对的集合,键值对之间无序

采用大括号{}和dict创建,键值对用冒号:表示

{<键1>:<值1>,<键2>:<值2>,...,<键n>:<值n>}

字典变量作用

在字典变量中,通过键获得值

<字典变量> = {<键1>:<值1>,<键2>:<值2>,...,<键n>:<值n>}

<值1> = <字典变量>[<键1>]

<字典变量>[<键1>] = <值1>
>>> d = {"first" : 1 ,"second":2,"third":3}
>>> d["first"]
1

生成空字典

空的集合类型定义不用{},将 {} 留给字典类型

>>> de = {} ; type(de)  #检测变量类型
<class 'dict'>

字典处理函数及方法

shLYzF.png

>>> d = {"first":1,"second":2,"third":3}

>>> d.keys()
dict_keys(['first', 'second', 'third'])

>>> d.values()
dict_values([1, 2, 3])

返回字典的key类型,可以用for in 遍历,不能像列表一样操作

shOQ6e.png

示例

>>> d.get("first","forth")  
1
>>> d.get("fifth","forth") #此时forth是错误时返回的值
'forth'

>>> d.popitem()
('third', 3)

字典类型应用场景

对映射的表达

表达键值对数据,进而操作它们

元素遍历

for k in d :
<语句块>

0x3 模块 jieba库的使用

pycharm上的conda环境需要找其他方法安装

中文分词第三方库,需额外安装

(cmd命令行) pip install jieba

jieba提供三种分词模式

一般掌握一种足以

jieba通过中文词库方式识别分词

利用一个中文词库,确定汉字之间的关联概率

汉字间概率大的组成自促,形成分词结果

除了分词,用户还可以添加自定义的词组

三种模式

精确模式、全模式、搜索引擎模式

精确模式 : 把文本精确的切分开,不存在冗余单词

全模式: 把文本中所有可能的词语都扫描出来,由冗余

搜索引擎模式: 在精确模式基础上,对长词再次切分

常用函数

s4pP4s.png

>>> import jieba
>>> jieba.lcut("我今天去美国找了特朗普总统谈话")
['我', '今天', '去', '美国', '找', '了', '特朗普', '总统', '谈话']

s4pUVe.png

0x4 实例 文本词频统计

英文文本:Hamlet

中文文本:三国演义

Hamet英文词频统计实例讲解

#CalHamletV1.py
def getText():
txt = open("hamlet.txt","r").read() #打开文件
txt = txt.lower() #将英文变成小写
for ch in '!"#$%&()*+,-./:;<=>?@[\\]^_‘{|}~': #逐一选取特殊符号
txt = txt.replace(ch," ") #将特殊符号替换为空格
return txt #返回替换后的文本
hamletTxt = getText() #将返回的文本赋给hamlettxt
words = hamletTxt.split() #文本分隔方法,以空格分隔
counts = {} #根据映射关系,定义一个空字典
for word in words:
counts[word] = counts.get(word,0) + 1
#形成键值对,get得到该词键对应的值+1,然后将新+1的值映射给该词键
#遍历了文本字符串内的所有元素
items = list(counts.items()) #将字典类型转换为列表类型
items.sort(key=lambda x:x[1],reverse=True) #将一个列表按照键值对的两个元素中的第二个元素进行排序,从大到小
for i in range(10): #打印前十个,词和对应出现的次数
word,count = items[i]
print("{0:<10}{1:>5}".format(word,count))

三国演义

import jieba
txt = open("threekingdoms.txt","r",encoding="utf-8").read()
words = jieba.lcut(txt)
counts = {}
for word in words:
if len(word) == 1:
continue
else:
counts[word] = counts.get(word,0) + 1
items = list(counts.items())
items.sort(key=lambda x:x[1],reverse=True)
for i in range(15):
word,count = items[i]
print("{0:<10}{1:>5}".format(word,count))




曹操 953
孔明 836
将军 772
却说 656
玄德 585
关公 510
丞相 491
二人 469
不可 440
荆州 425
玄德曰 390
孔明曰 390
不能 384
如此 378
张飞 358


深入讲解

将词频与人物相关联,面向问题

词频统计 人物统计

去除排名靠前但不是人物的词语

import jieba
txt = open("threekingdoms.txt","r",encoding="utf-8").read()
excludes = {"将军","却说","荆州","二人","不可","不能","如此","如何","商议","军士","左右","军马","引兵","次日","大喜","天下","东吴","于是","今日","不敢","魏兵"}
words = jieba.lcut(txt)
counts = {}
for word in words:
if len(word) == 1:
continue
elif word == "诸葛亮" or word == "孔明曰":
rword = "孔明"
elif word == "关公" or word == "云长":
rword = "关羽"
elif word == "玄德" or word == "玄德曰":
rword = "刘备"
elif word == "孟德" or word == "丞相":
rword = "曹操"
else:
rword = word
counts[rword] = counts.get(rword,0) + 1
for word in excludes:
del counts[word]
items = list(counts.items())
items.sort(key=lambda x:x[1],reverse=True)
for i in range(8):
word,count = items[i]
print("{0:<10}{1:>5}".format(word,count))

应用问题的扩展

绘制词云

对红楼梦、西游记、水浒传分析

政府工作报告、科研论文、新闻报道等

文件和数据格式化

格式化

将字符串按照样式规范

数据格式化

将一组数据按照一定规格和样式进行规范:表示、存储、运算等

方法论 从python角度理解文件和数据表示

0x1 文件的使用

文件的类型

文件 文件时数据的抽象和集合

文件时存储在辅助存储器上的数据序列

文件时数据存储的一种形式

文件展现形态:文本文件和二进制文件

所有文件都是二进制形式存储的,只是表现形式不同

文本文件

由单一特定编码组成的文件

也可以理解为字符串

二进制文件

直接由0和1组成,没有编码

两种形式都可以二进制形式打开

文本形式打开文件

tf = open("f,txt","rt")
print(tf.readline())
tf.close()

this is a word 123abc

#当文件中有中文时,读取文件内容会报如下错误
UnicodeDecodeError: 'gbk' codec can't decode byte 0xb9 in position 35: illegal multibyte sequence

二进制形式打开文件

bf = open("f.txt","rb")
print(bf.readline())
bf.close()

b'this is a word 123abc\xef\xbc\x8c\xe4\xb8\xad\xe6\x96\x87\xe5\x86\x85\xe5\xae\xb9\r\n'

文件的打开和关闭

打开-操作-关闭

存储状态、占用状态

a = open(,)
a.close()

读写文件方法

#读文件
a.read(size)
a.readline(size)
a.realines(hint)

#写文件
a.write(s)
a.writelines(lines)
a.seek(offset)

文件打开

<变量名> = open(<文件名>,<打开模式>)

sTpBMn.png

文件路径:

绝对路径

\ 表示转义符,所以路径要写成

D:/PYE/f.txt

D:\\PYE\\f.txt

相对路径

./PYE/f.txt

在同一文件夹下直接用文件名
"f.txt"

文件打开模式

sT9htS.png

默认时文本形式,只读模式

文件关闭

<变量名>.close()

程序结束后自动关闭

文件的内容的读取

sTZs1K.png

sTZ4ht.png

一次读入,统一处理

fname = input("请输入要打开的文件名称:")
fo = open(fname,"r")
txt = fo.read()
#对全文txt进行处理
fo.close()

#采用一次读入,统一处理,文件过大不适用

按数量读入,逐步处理

适合大文件

fname = input("请输入要打开的文件名称:")
fo = open(fname,"r")
txt = fo.read(2)
while txt !="":
#对txt进行处理
txt = fo.read(2)
fo.close()

逐行遍历

一次读入,分行处理

fname = input("请输入要打开的文件名称:")
fo = open(fname,"r")
for line in fo.readlines():
print(line)
fo.close()

分行读入、逐行处理

fname = input("请输入要打开的文件名称:")
fo = open(fname,"r")
for line in fo:
print(line)
fo.close()

数据的文件写入

sTmKGq.png

writelines直接将文字拼接写入文件,没有空格换行

sTmrLD.png

输入位置指针,描述了当前在文件内写入的具体内存位置

fo = open("output.txt","w+")
ls = ["中国""法国""美国"]
fo.writelines(ls)
for line in fo:
print(line)
fo.close()

#此时输入指针在输入的末尾,之后是没有内容的,固没有输出
#修改如下,使用seek方法

fo = open("output.txt","w+")
ls = ["中国""法国""美国"]
fo.writelines(ls)
fo.seek(0) #将输入指针返回到最开始
for line in fo:
print(line)
fo.close()

0x2 实例:自动轨迹绘制

自动轨迹绘制

根据脚本来绘制图形

写数据绘制图形

是自动化程序的重要内容

基本思路

定义数据文件格式(接口)

根据文件接口解析参数绘制图形

编制数据文件

数据接口定义

根据个人需求

sTu3E4.png

编写对应程序

map函数,将第一个参数对应的函数作用于一个列表或集合的每个元素

import turtle as t
t.title('自动轨迹绘制')
t.setup(800,600,0,0)
t.pencolor("red")
t.pensize(5)
#数据读取
datals = []
f = open("data.txt")
for line in f:
line = line.replace("\n","")
datals.append(list(map(eval,line.split(","))))
f.close()
#自动绘制
for i in range(len(datals)):
t.pencolor(datals[i][3],datals[i][4],datals[i][5])
#找到第i个参数,获取第3个值、第4个值,第5个值,即RGB参数
t.fd(datals[i][0]) #读取0位数据,获得绘制长度
if datals[i][1]: #根据判断是否转向,选择左右转的角度
t.right(datals[i][2])
else:
t.left(datals[i][2])

理解方法思维

自动化思维

接口化设计

二维数据应用

拓展

增加更多接口

增加功能

增加应用动画绘制

0x3 一维数据的格式化和处理

数据组织的维度

线性方式组织

二维方式组织

多维、高维

一维数据

由对等关系的有序或无序数据构成,采用线性方式组织

对应列表数组和集合等概念

二维数据

由多个一维数据构成,是一维数据的组合形式

仅利用最基本的二元关系展示数据间的复杂结构

例如 键值对定义

sThLpF.png

数据的操作周期

存储、表示、操作

存储格式、数据类型、操作方式

一维数据的表示

如何用程序类型表达一维数据

如果数据间有序:使用列表类型

可以用for循环遍历

数据无序:使用集合类型

可以使用for循环遍历

一维数据的存储

存储方式

空格分隔 即存储的数据之间需要空格

但数据中不能由空格

逗号分隔 也如空格存在缺点

一般用特殊符号分隔

一维数据的处理

读入

从空格分隔的文件中读入数据

txt = open(fname).read()
ls = txt.split()
f.close()

从特殊分隔的文件中读入数据

txt = open(fname).read()
ls = txt.split("$")
f.close()

写入

采用空格方式写入数据文件

ls = ['中国','美国','日本']
f = open(fname,'w')
f.write(''.join(ls)) #将' '作为分隔放到ls数据之间
f.close()

特殊分隔的方式写入数据文件

ls = ['中国','美国','日本']
f = open(fname,'w')
f.write('$'.join(ls)) #将'$'作为分隔放到ls数据之间
f.close()

0x4 二维数据的格式化和处理

二维数据的表示

使用表格形式,使用二维列表

类似于C语言中的二维数组

使用列表类型

遍历需要两层for循环

数据维度是数据的组织形式

一维数据:列表和集合类型

有序用列表,无序用集合

CSV数据存储格式

CSV Comma-Separated Values

用逗号来分隔值的一种存储方式

是国际通用的一二维数据存储格式,一般.CSV扩展名

每行一个一维数据,采用逗号分隔,无空行

Excel和一般编辑软件都可以读入或另存为CSV文件

二维数据的存储

如果某个元素缺失,逗号仍要保留

二维数据的表头可以作为数据存储,也可以另行存储

逗号为英文半角逗号,逗号与数据至今无额外空格

数据中的逗号可以用引号标识,也可加转义符

数据如何存的,按行存或者按列存都可以,具体由程序决定

一般索引习惯:

ls [row][column]

二维数据的处理

二维数据的读入处理

从CSV格式的文件读入数据

fo = open(fname)
ls = []
for line in fo:
line = line.replace("\n","")
ls.append(line.split(","))
fo.close()

将数据写入CSV格式的文件

ls = [[],[],[]] #二维列表
f = open(fname,'w')
for item in ls:
f.write(','.join(item) + '\n')
f.close()

遍历

采用二层循环

ls = [[1,2],[3,4],[5,6]] #二维列表
for row in ls:
for column in row:
print(column)

0x5 模块:wordcloud库的使用

wordcloud是优秀的词云展示第三方库

将词语用可视化的方式,艺术的展示的文本

安装

(cmd命令行) pip install wordcloud

如果安装失败,报错查阅 https://www.jb51.net/article/198751.htm

使用说明

wordcloud库把词云当作一个WordClloud对象

wordcloud.WordCloud()代理一个文本对应的词云

绘制词云的形状、尺寸和颜色都可以设定

w = wordcloud.WordCloud()

以WordCloud对象为基础

配置参数、加载文本、输出文件

s7kttx.png

常规方法

配置对象参数

加载词云文本

输出词云文件

import wordcloud
c = wordcloud.WordCloud()
c.generate("Wordcloud by Python")
c.to_file("pyworcloud.png")

最后生成图片宽400高200像素

操作过程

以空格分隔单词

单词出现次数并过滤

根据统计配置字号

颜色环境尺寸

s74oLj.png

s7o7eH.png

s77fKO.png

import wordcloud
txt = "life is short,you need python"
w = wordcloud.WordCloud(\
background_color = "white")
w.generate(txt)
w.to_file("pywcloud.png")

中文构成词云

import jieba
import wordcloud
txt = "程序设计语言是计算机能够理解和\
失败用户操作意图的一种交互体系,它按照\
特定规则组织计算机指令,使计算机能够自\
动进行各种运算处理。"
w = wordcloud.WordCloud(width=1000,\
font_path="msyh.ttc",height=700) #此处msyh为字体微软雅黑文件路径
w.generate(" ".join(jieba.lcut(txt))) #先变成列表,然后用join方法加空格
w.to_file("pywcloud.png") #输出为图片

0x6 实例:政府工作报告词云

直观理解政策文件

《决胜全面建成小康社会 夺取新时代中国特色社会主义伟大胜利》

《中共中央关于乡村振兴的战略》

基本思路

读取文件

输出词云

观察结果、迭代

第一本

import jieba
import wordcloud
f = open("xjp.txt","r",encoding="utf-8") #打开文本
t = f.read() #将文本内容一次性读入t
f.close()
ls = jieba.lcut(t) #对文本进行分词,将分词结果保存为列表类型
txt = " ".join(ls) #词云需要长文本输入,用空格将列表元素链接起来
w = wordcloud.WordCloud(font_path = "msyh.ttc",\
width = 1000,height = 700,background_color = "white")
w.generate(txt)
w.to_file("grwordcloud.png")

限制文字输出量

import jieba
import wordcloud
f = open("xjp.txt","r",encoding="utf-8")
t = f.read()
f.close()
ls = jieba.lcut(t)
txt = " ".join(ls)
w = wordcloud.WordCloud(font_path = "msyh.ttc",\
width = 1000,height = 700,background_color = "white",\
max_words = 15) #限制显示的词
w.generate(txt)
w.to_file("grwordcloud.png")

词云形状

import jieba
import wordcloud
from scipy.misc import imread #引入库,用来读取图片文件,形成图片变量
mask = imread(" ")
f = open("xjp.txt","r",encoding="utf-8")
t = f.read()
f.close()
ls = jieba.lcut(t)
txt = " ".join(ls)
w = wordcloud.WordCloud(font_path = "msyh.ttc",mask = mask\ #将mask赋给mask参数
width = 1000,height = 700,background_color = "white",\
max_words = 15) #限制显示的词
w.generate(txt)
w.to_file("grwordcloud.png")