第4周-程序的控制结构
紧凑形式的二分支结构:<表达式1> if <条件> else <表达式2>
guess = eval(input())
print("猜{}了".format("对" if guess==99 else "错"))
条件组合的三个保留字
操作符及使用 | 描述 |
---|---|
x and y | 两个条件x和y的逻辑与 |
x or y | 两个条件x和y的逻辑或 |
not x | 条件x的逻辑非 |
异常处理
try:
<语块1>
except:
<语块2>
else:
<语块3> //else对应语块3在不发生异常时执行
finally:
<语块4> //finally对应语块4一定执行
实例——计算BMI(获取用户多个输入)
height, weight = eval(input("请输入身高(米)和体重(公斤)[以逗号隔开]: "))
bmi = weight / pow(height,2)
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指标为:{:.2f},参考范围:国际'{}',国内'{}'".format(bmi, who, nat))
遍历循环:for ... in ...
计数循环,字符串循环,列表循环,文件循环,...
for i in range(N):
for i in range(M,N,K):
for c in "字符串":
for item in [列表]:
for line in fi: //fi是文件标识符,遍历文件的每一行
- 无限循环
while
在条件不满足时,才结束循环 - 循环控制保留字
continue
和break
- 在循环语句后,用
else
语句来作为“正常”完成循环的奖励(没有执行break)。
for c in "PYTHON":
if c == "T":
continue
print(c, end="")
else:
ptint(",正常退出")
>>>PYHON,正常退出
for c in "PYTHON":
if c == "T":
break
print(c, end="")
else:
ptint(",正常退出") //可以用来判断程序是否执行了break语句
>>>PY
random库,使用梅森旋转算法产生的伪随机数。
- 基本随机数函数:seed(),random()
- 扩展随机数函数:randint(),getranbits(),uniform(),randrange(),choice(),shuffle()
函数 | 描述 |
---|---|
randint(a,b) | 生成一个[a,b]之间的随机整数:random.randint(10,100) >>>64 |
randrange(m,n[,k]) | 生成一个[m,n]之间以k为步长的随机整数:random.randrange(10,100,10) >>>80 |
getrandbits(k) | 生成一个k比特长的随机整数:random.getrandbits(16) >>>37885 |
uniform(a,b) | 生成一个[a,b]之间的随机小数:random.uniform(10,100) >>>13.096321648808136十六位小数 |
choice(seq) | 从序列seq中随机选择一个元素:random.choice([1,2,3,4,5,6,7,8,9]) >>>8 |
shuffle(seq) | 将序列seq中元素随机排列,返回打乱后的序列:s=[1,2,3,4,5,6,7,8,9];random.shuffle(s);print(s) >>>[3,5,8,9,6,1,2,7,4] |
实例——圆周率的计算(蒙特卡罗方法)
数学公式怎么推导的就不用管了,先用程序直接实现下面的公式:
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))
-
蒙特克罗撒点法:
from random import random
from time import perf_counter
DRATS = 1000*1000 #设定撒点数量为100万,在1/4圆范围内(半径为1的正方形)。
hits = 0.0 #设定变量hits为在圆内的点数量
start = perf_counter()
for i in range(1, DRATS+1): #遍历循环每一个点
x, y = random(), random() #设定每个点的x,y坐标变量为[0,1]之间的随机数
dist = pow(x**2 + y**2, 0.5) #变量dist为每个点到圆心的距离,为x平方加y平方,再开方。
if dist <= 1.0: #如果dist距离小于1,则该点在圆内部
hits += 1 #点数量加1,循环完成时,得到所有圆内部的撒点数量。
pi = 4*(hits/DRATS) #pi值则等于4倍圆内部点数量与总撒点数的比值。
print("圆周率的值是:{}".format(pi))
print("运行时间是:{:.5f}s".format(perf_counter()-start))
第5周-函数和代码复用
参数
- 函数也可以没有参数,但必须保留括号。
- 可以指定参数的默认值,构成可选参数,但必须放在非可选参数的后面。
计算n!//m,n的阶乘整除m
def fact(n,m=1): #m为可选参数,默认值为1
s=1
for i in range(1,n+1):
s*=i
return s//m
>>>fact(10)
3628800
>>>fact(10,5)
725760
- 可变参数——函数定义时可以设计可变参数的数量
计算n!,n的阶乘与可选参数b的乘数
def fact(n,*b): #b为可选参数,默认值为1,*b代表不确定数量
s=1
for i in range(1,n+1):
s*=i
for item in b:
s*=item
return s
>>>fact(10,3)
10886400
>>>fact(10,3,5,8)
43545600
函数的返回值
- return可以不返回任何值或返回一个和多个值
def fact(n,m=1):
s=1
for i in range(1,n+1):
s*=i
return s//m,n,m
>>>fact(10,5)
(725760,10,5) #返回的是一个包含多个值的元组类型
>>>a,b,c=fact(10,5) #可以将返回多个值分别赋值给a,b,c
>>>print(a,b,c)
725760,10,5
lambda函数
是一种匿名函数,返回函数名作为结果
>>>f = lambda x,y : x+y #x和y是两个参数,冒号后面是表达式:计算x+y
>>>f(10,15)
25
实例-七段数码管
基本思路:
1.绘制单个数字对应的数码管
2.获取一串数字,绘制对应的数码管
3.获取当前系统时间,绘制对应的数码管
import turtle, time
def drawGap(): #绘制数码管的间隔
turtle.penup()
turtle.fd(5)
def drawLine(draw): #绘制单段数码管
drawGap()
turtle.pendown() if draw else turtle.penup()
turtle.fd(30)
drawGap()
turtle.right(90)
def drawDigit(d): #根据数字绘制七段数码管
drawLine(True) if d in [2,3,4,5,6,8,9] else drawLine(False)
drawLine(True) if d in [0,1,3,4,5,6,7,8,9] else drawLine(False)
drawLine(True) if d in [0,2,3,5,6,8,9] else drawLine(False)
drawLine(True) if d in [0,2,6,8,] else drawLine(False)
turtle.left(90)
drawLine(True) if d in [0,4,5,6,8,9] else drawLine(False)
drawLine(True) if d in [0,2,3,5,6,7,8,9] else drawLine(False)
drawLine(True) if d in [0,1,2,3,4,7,8,9] else drawLine(False)
turtle.left(180)
turtle.penup()
turtle.fd(20)
def drawDate(date):
turtle.pencolor("red")
for i in date:
if i == '-':
turtle.write('年',font=("Arial",18,"normal"))
turtle.pencolor("green")
turtle.fd(40)
elif i == '=':
turtle.write('月',font=("Arial",18,"normal"))
turtle.pencolor("blue")
turtle.fd(40)
elif i == '+':
turtle.write('日',font=("Arial",18,"normal"))
else:
drawDigit(eval(i))
def drawTime(time):
turtle.pencolor("purple")
for i in time:
if i == ':':
turtle.write(':',font=("Arial",80,"normal"))
turtle.fd(40)
else:
drawDigit(eval(i))
def main():
turtle.setup(800,350,200,200)
turtle.penup()
turtle.goto(-300,75)
turtle.pensize(5)
drawDate(time.strftime('%Y-%m=%d+',time.localtime()))
turtle.penup()
turtle.goto(-240,-75)
drawTime(time.strftime('%H:%M:%S',time.localtime())) #gmtime()的时间是UTC标准时间,比北京时间少了8小时
turtle.hideturtle()
turtle.done()
main()
代码复用
函数 和 对象 是代码复用的两种主要形式
函数:将代码命名 | 对象:属性和方法 |
---|---|
在代码层面建立了初步抽象 | .和.()在函数之上再次组织进行抽象 |
模块化设计
- 子程序就是模块,主程序被看作是模块之间的关系
紧耦合:两个部分之间交流很多,无法独立存在
松耦合:两个部分之间交流较少,可以独立存在
对于函数,输入参数和返回值,就是和其它代码的交流通道,这样的交流函数定义的越少,越清晰,那么复用的可能性就越高。这样,我们希望:模块内部紧耦合、模块之间松耦合。
函数递归——函数调用自身的方式
两个关键特征:
- 链条:计算过程存在递归链条
- 基例:存在一个或多个不需要再次递归的基例
- 类似数学归纳法:
证明当n取第一个值n0时命题成立
假设当nk时命题成立,证明当n=nk+1时命题也成立
函数递归的实现
def fact(n):
if n == 0 #n=0时,阶乘为1,基例
return 1
else:23
return n*fact(n-1) #链条
实例1-字符串反转
def rvs(s):
if s == "": #空字符串是基例
return s
else:
return rvs(s[1:])+s[0] #每次将[0]首字符放到其余字符的后面
实例2-斐波那契数列
def f(n):
if n == 1 or n == 2:
return 1
else:
return f(n-1) + f(n-2)
实例3-汉诺塔
count = 0
def hanoi(n,src,dst,mid): #定义4个参数,n个圆盘,src起始柱,dst目标柱,mid中间柱
global count #计数count全局变量
if n == 1: #n=1时为基例
print("{}:{}->{}".format(1,src,dst))
count += 1
else:
hanoi(n-1,src,mid,dst) #将n个圆盘分解为n-1个圆盘和第n个圆盘,n-1个圆盘移到mid中间柱,以dst目标柱为辅助
print("{}:{}->{}".format(n,src,dst)) #打印第n个圆盘从src起始柱移到dst目标柱的过程
count += 1 #计数加1
hanoi(n-1,mid,dst,src) #将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
实例4-科赫雪花
分形几何是一种迭代的几何图形
import turtle as t
def koch(size,n):
if n == 0:
t.fd(size)
else:
for angle in [0,60,-120,60]:
t.left(angle)
koch(size/3,n-1)
def main():
t.setup(600,600)
t.penup()
t.goto(-200,100)
t.pendown()
t.pensize(2)
level=3
koch(400,level)
t.right(120)
koch(400,level)
t.right(120)
koch(400,level)
t.hideturtle()
main()
第6周-组合数据类型
1、集合类型
- 集合是多个元素的无序组合
- 集合元素之间无序,每个元素唯一,不存在相同元素
- 集合元素不可更改,不能是可变数据类型
- 集合用大括号{}表示,元素间用逗号分隔
- 建立集合类型用{}或set()
- 建立空集合类型,必须使用set()
>>>A = {"python", 123, ("python",123)} #使用{}建立集合
{123, 'python', ('python',123)}
>>>B = set("pypy123") #使用set()建立集合
{'1', 'p', '2', '3' ,'y'} #字符串被拆分为单个字符,相同的元素被去掉
集合间操作符
操作符及应用 | 描述 |
---|---|
S | T | 并集:返回一个新集合,包括集合S和T中的所有元素 |
S - T | 差集:返回一个新集合,包括在集合S,但不在T中的元素 |
S & T | 交集:返回一个新集合,包括同时在集合S和T中的元素 |
S ^ T | 补集:返回一个新集合,包括集合S和T中的非相同的元素 |
S <= T 或 S < T | 返回True/False,判断S和T的子集关系 |
S >= T 或 S > T | 返回True/False,判断S和T的包含关系 |
S |= T | 更新集合S,包括集合S和T中的所有元素 |
S - =T | 更新集合S,包括在集合S,但不在T中的元素 |
S &= T | 更新集合S,包括同时在集合S和T中的元素 |
S ^= T | 更新集合S,包括集合S和T中的非相同的元素 |
集合处理方法
操作符及应用 | 描述 |
---|---|
S.add(x) | 如果x不在集合S中,将x增加到S |
S.discard(x) | 移除S中元素x,如果x不在集合S中,不报错 |
S.remove(x) | 移除S中元素x,如果x不在集合S中,产生KeyError异常 |
S.clear() | 移除S中所有元素 |
S.pop() | 随机返回S中的一个元素,更新S,若S为空,产生KeyError异常 |
S.copy() | 返回集合S的一个副本 |
len(S) | 返回集合S的元素个数 |
x in S | 判断x是否在集合S中,返回True,否则返回False |
x not in S | 判断x是否不在集合S中,返回True,否则返回False |
set(x) | 将其它类型变量x转变为集合类型 |
- 集合类型最重要的操作——数据去重
>>> ls = ["p", "p", "y", "y", 123]
>>> s = set(ls) #利用集合无重复元素的特点,去重
{'p', 'y', 123}
>>> lt = list(s) #将集合转换为列表类型
2、序列类型
- 序列是具有先后关系的一组元素
序列是一维元素向量,元素类型可以不同
元素间由序号引导,通过下标访问序列的特定元素
序列类型是基类类型,我们使用其衍生类型:字符串类型,元组类型,列表类型 - 序列类型通用操作符
操作符及应用 | 描述 |
---|---|
x in s | 如果x是序列s的元素,返回True,否则返回False |
x not in s | 如果x是序列s的元素,返回False,否则返回True |
s + t | 连接两个序列s和t |
s*n 或 n*s | 将序列s复制n次 |
s[i] | 索引,返回s中第i个元素,i是序列的序号 |
s[i:j]或s[i,j,k] | 切片,返回序列s中第i到j,以k为步长的元素子序列 |
序列元素取反
>>> ls = ["python", 123, ".io"]
>>> ls[::-1]
['.io', 123, 'python']
>>> s = "python123.io"
>>> s[::-1]
'oi.321nohtyp'
- 序列类型通用函数和方法
函数和方法 | 描述 |
---|---|
len(s) | 返回序列s的长度 |
min(s) | 返回序列s中最小的元素,s中元素需要可比较 |
max(s) | 返回序列s中最大的元素,s中元素需要可比较 |
s.index(x)或s.index(x,i,j) | 返回序列s从i开始到j位置中,第一次出现元素x的位置 |
s.count(x) | 返回序列s中出现x的总次数 |
元组类型
- 元组是序列类型的一种扩展
元组一旦创建就不能被修改
使用小括号()或tuple()创建,元素间用逗号,分隔
可以使用或不使用小括号
>>> creature = "cat", "dog", "tiger", "human" #可以不使用小括号
>>> creature[::-1]
('human', 'tiger', 'dog', 'cat') #生成一个新的元组,不改变原有元组
>>> color = (0x001100, "blue", creature) #元组中的元素可以是另一个元组
>>> color[-1][2] #序号[-1]索引到creature元组,再在creature元组中索引到序号[2]
'tiger'
列表类型
- 列表是序列类型的一种扩展
创建后可以随意被修改
使用方括号[]或list()创建,元素间用逗号,分隔
列表中元素可以不同,也没有长度的限制 - 列表类型操作函数和方法
函数和方法 | 描述 |
---|---|
ls[i] = x | 替换列表ls第i个元素为x |
ls[i:j:k] = lt | 用列表lt替换ls切片后所对应元素子列表 |
del ls[i] | 删除列表ls中第i个元素 |
del ls[i:j:k] | 删除列表ls中第i到第j以k为步长的元素 |
ls += lt | 更新列表ls,将列表lt元素增加到列表ls中 |
ls *= n | 更新列表ls,其元素重复n次 |
ls.append(x) | 在列表ls最后增加一个元素x |
ls.clear() | 删除列表ls中所有元素 |
ls.copy() | 生成一个新列表,赋值ls中所有元素 |
ls.insert(i,x) | 在列表ls的第i位置增加元素x |
ls.pop(i) | 将列表ls中第i位置元素取出,并删除该元素 |
ls.remove(x) | 将列表ls中出现的一个元素x删除 |
ls.reverse() | 将列表ls中的元素反转 |
实例-基本统计值
总个数:len()
求和:for ... in
平均值:求和/总个数
方差:各数据与平均数差的平方的和的平均数
中位数:排序,然后... 奇数找中间1个,偶数找中间2个取平均值
def getNum(): #获取用户不定长度的输入
numbers = []
iNumStr = input("请输入数字(回车退出):")
while iNumStr != "":
numbers.append(eval(iNumStr))
iNumStr = input("请输入数字(回车退出):")
return numbers
def mean(numbers): #计算平均值
s = 0.0
for num in numbers:
s = s + num
return s/len(numbers)
def dev(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},方差:{:.2},中位数:{}".format(m, dev(n,m), median(n)))
字典类型
- 映射:是一种键(索引)和值(数据)的对应关系
- 键值对:键是数据索引的扩展
字典是键值对的集合,键值对之间无序
采用大括号{}和dict()创建,键值对用冒号:表示
空{}用来生成字典,空集合只能用set()来生成 - 字典类型操作函数和方法
函数和方法 | 描述 |
---|---|
del d[k] | 删除字典d中k键对应的数据值 |
k in d | 判断键k是否在字典d中,返回True,否则False |
d.keys() | 返回字典d中所有的键信息 |
d.values() | 返回字典d中所有的值信息 |
d.items() | 返回字典d中所有的键值对信息 |
d.get(k, |
键k存在,则返回相应值,否则返回 |
d.pop(k, |
键k存在,取出并删除相应值,否则返回 |
d.popitem() | 随机从字典d中取出一个键值对,以元组形式返回 |
d.clear() | 删除所有的键值对 |
len(d) | 返回字典d中元素的个数 |
3、jieba库
- 中文分词
- 常用函数
函数 | 描述 |
---|---|
jieba.lcut(s) | 精确模式,返回一个列表类型的分词结果:>>>jieba.lcut_for_search("中华人民共和国是伟大的") -->['中华', '人民', '共和国', '是', '伟大', '的' |
jieba.lcut(s, cut_all=True) | 全模式,存在冗余 |
jieba.lcut_for_search(s) | 搜索引擎模式,存在冗余:>>>jieba.lcut_for_search("中华人民共和国是伟大的") -->['中华', '华人', '人民', '共和', '共和国', '中华人民共和国', '是', '伟大', '的' ] |
jieba.add_word(w) | 向分词词典增加新词w |
实例-文本词频统计(Hamlet.txt)
- 哈姆雷特
def getText():
txt = open("hamlet.txt", "r").read()
txt = txt.lower() #转换小写
for ch in '!"#$%&()*+,-./:;<=>?@[\\]^_{|}~': #遍历文本中所有特殊符号和标点符号
txt = txt.replace(ch, " ") #将特殊符号替换为空格
return txt
hamletTxt = getText()
words = hamletTxt.split() #将文本以空格进行分割为每个单词,返回列表形式
counts = {} #建立一个空字典
for word in words: #遍历words列表中每个词
counts[word] = counts.get(word, 0) + 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)) #word编号0,左对齐,占位10字符;count编号1,右对齐,占位5字符
>>>词频前10位
the 1138
and 965
to 754
of 669
you 550
i 542
a 542
my 514
hamlet 462
in 436
划重点:
1-counts={}
建立空数组,因为counts.get(word,0)
第一次返回的是我们设定0
值,这样用counts[word]=0+1
,相当于把第一次出现的词作为key加入到字典中并赋值为1.
2-list(counts.items())
以字典的键值对作为元组类型产生成列表[(k1,v1),(k2,v2),(k3,v3)...]
3-sort(key=None, reverse=False)
排序函数的原型,关于key可以理解为可定义的排序规则,在这里sort(key=lambda x: x[1], reverse=True)
其中的lambda函数表达式意思是以每个元组元素的下标为1的值进行排列.
- 三国演义
import jieba
txt = open("threekingdoms.txt", "r", encoding="utf-8").read()
excludes = {"将军","却说","荆州","二人","不可","不能","如此","商议",\
"如何","军士","左右","军马","引兵","次日","大喜","天下",\
"东吴","于是","今日","不敢","魏兵","陛下","一人","人马",\
"不知","汉中","只见","众将","都督","主公","蜀兵","上马",\
"大叫","太守","此人","夫人","先主","后人","背后","城中",\
"天子","一面","何不","大军","忽报","先生","百姓","何故",\
"然后","先锋","不如","赶来","原来","令人","江东","因此",\
"下马","喊声","正是","徐州","忽然","不见","未知","大败",\
"成都","大事","之后","一军","引军","起兵","军中","接应",\
"进兵","大惊","可以","以为","大怒","不得","心中"} #排除词库集合
words = jieba.lcut(txt) #jieba分词会自动去除特殊符号和标点
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 = "曹操"
elif word == "后主" or word == "阿斗":
rword = "刘禅"
else:
rword = word
counts[rword] = counts.get(rword, 0) + 1 #因所有提取的word都赋值给rword,所以这一段代码要放到分支语句外
for word in excludes:
del counts[word] #删除掉排除词库里的数据
items = list(counts.items()) #将字典的键值对转换为列表类型,每个键值对是列表中的一组元组
items.sort(key=lambda x:x[1], reverse=True) #将以元组的第二个值进行从大到小排序
for i in range(20):
word, count = items[i] #定义两个变量,分别对应列表中每组元组的两个元素
print("{0:<10}\t{1:>5}".format(word,count)) #\t是水平制表符,作用是对齐
>>>人物出场排名前20位
曹操 1451
孔明 1383
刘备 1252
关羽 784
张飞 358
吕布 300
赵云 278
孙权 264
刘禅 255
司马懿 221
周瑜 217
袁绍 191
马超 185
魏延 180
黄忠 168
姜维 151
马岱 127
庞德 122
孟获 122
刘表 120
第7周-文件和数据格式化
1、文件的使用
文本文件
- 文件是数据的抽象和集合
由单一特定编码组成的文件,如UTF-8编码
由于存在编码,也被看成是储存着的长字符串
适用于:.txt、.py
二进制文件
- 直接由比特0和1组成,没有统一字符编码
一般存在二进制0和1的组织结构,即文件格式
适用于:.png、.avi
文件的打开
- 以文本形式打开文件
tf = open("f.txt", "rt")
print(tf.readline())
tf.close()
- 以二进制形式打开文件
tf = open("f.txt", "rb")
print(tf.readline())
tf.close()
- <变量名> = open(<文件名及路径>, <打开模式>)
文件的打开模式 | 描述 |
---|---|
'r' | 只读模式,默认值,如果文件不存在,返回FileNotFoundError |
'w' | 覆盖写模式,文件不存在则创建,存在则完全覆盖 |
'x' | 创建写模式,文件不存在则创建,存在则返回FileExistsError |
'a' | 追加写模式,文件不存在则创建,存在则在文件最后追加内容 |
'b' | 二进x制文件模式 |
't' | 文本w文件模式,默认值 |
'+' | 与r/w/x/a一同使用,在原功能基础上增加同时读写功能 |
文件的关闭
<变量名>.close()
文件内容的读取和写入
操作方法 | 描述 |
---|---|
读入全部内容,如果给出参数,读入前size长度:>>>s = f.read(2) #读入前2个字符 |
|
读入一行内容,如果给出参数,读入该行前size长度 | |
读入文件所有行,以每行为元素形成列表,如果给出参数,读入前hint行 | |
向文件写入一个字符串或字节流 | |
将一个元素全为字符串的列表写入文件,将字符串拼接后写入一行 | |
改变当前文件操作指针的位置,offset含义:0-文件开头;1-当前位置;2-文件结尾 |
实例-自动轨迹绘制
- 需求:根据脚本来绘制图形,不是写代码而是写数据绘制轨迹
使用数据脚本是自动化最重要的一步 - 基本思路
步骤1:定义数据文件格式(接口)
步骤2:编写程序,根据文件接口解析参数绘制图形
步骤3:编制数据文件
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: #以每一行进行遍历,结果是每一行形成一个列表,作为datals[]列表的每个元素
line = line.replace("\n","") #将每一行末尾的换行转换为空格
datals.append(list(map(eval, line.split(",")))) #map(<参数1>,<参数2>)是将参数1逐一作用于参数2;结果是将字符串转换为数字,存入datals列表中
f.close()
#自动绘制
for i in range(len(datals)):
t.pencolor(datals[i][3],datals[i][4],datals[i][5])
t.fd(datals[i][0])
if datals[i][1]:
t.right(datals[i][2])
else:
t.left(datals[i][2])
>>>data.txt
100,0,60,1,0,0 #长度,左转0右转1,转向角度,小数颜色
100,0,60,0,1,0
100,0,60,0,0,1
100,0,60,1,1,0
100,0,60,0,1,1
100,0,60,1,0,1
2、一维数据
- 由对等关系的有序或无序数据构成,采用线性方式组织
一维数据的表示
- 数据间有序:使用列表类型
- 数据间无序:使用集合类型
一维数据的存储
- 方式1:空格分隔
- 方式2:逗号分隔
- 方式3:特殊字符分隔
一维数据的处理
- 读入文件,转换为数据列表
fname.txt-->中国$美国$德国$法国$意大利$英国
txt = open(fname.txt).read()
ls = txt.split("$")
f.close()
>>>ls
['中国', '美国', '德国', '法国', '意大利', '英国']
- 将数据列表,写入到文件
ls = ['巴西', '阿根廷', '智利']
f = open(fname.txt, 'w')
f.write(' '.join(ls)) #将空格join到每个元素之间
f.close
>>>
fname.txt-->巴西 阿根廷 智利
3、二维数据
- 由多个一维数据构成,是一维数据的组合形式,如:表格
CSV数据存储格式
- CSV: Comma-Separated Values 由逗号分隔的值
如果某个元素缺失,逗号仍要保留
二维数据的表头可以作为数据存储,也可以另行存储 - 一般索引习惯: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') #'\n':每一行结尾换行
fo.close()
- 二维数据的逐一处理
采用二层循环
ls = [[], [], []] #二维列表
for row in ls:
for column in row:
print(ls[row][column])
3、wordcloud词云库
- wordcloud.WordCloud()代表一个文本对应的词云
可以根据文本中词语出现的频率等参数绘制词云
绘制词云的形状、尺寸、颜色和字体都可以设定
wordcloud库常规方法
w = wordcloud.WordCloud(<参数>)
方法和参数 | 描述 |
---|---|
w.generate(txt) | 向WordCloud对象w中加载文本txt |
w.to_file(filename) | 将词云输出为图像文件,.png或.jpg格式 |
width | 指定词云生成图片的宽度,默认400像素 |
height | 指定词云生成图片的高度,默认200像素 |
min_font_size | 指定词云中字体的最小字号,默认4号 |
max_font_size | 指定词云中字体的最大字号,根据高度自动调节 |
font_step | 指定词云中字体字号的步进间隔,默认为1 |
font_path | 指定字体文件的路径,默认为None:>>>w = wordclound.WordCloud(font_path="msyh.ttc") #指定字体 |
max_words | 指定词云显示的最大单词数量,默认为200 |
stop_words | 指定词云的排除词集合列表:>>>w = wordclound.WordCloud(stop_words={"Python"}) |
mask | 指定词云形状,默认为长方形,需要引用imread()函数:>>>from scipy.misc import imread >>>mk=imread("pic.png") >>>w = wordclound.WordCloud(mask=mk) |
background_color | 指定词云图片的背景颜色,默认为黑色 |
实例-词云展示
import wordcloud
import jieba
from scipy.misc import imread
img = imread("x.jpg") #图片背景要求是白色
t = open("threekingdoms.txt", "r", encoding="utf-8")
h = t.read()
t.close()
ls = jieba.lcut(h)
txt = " ".join(ls)
w = wordcloud.WordCloud(width=1500, height=1500,
background_color="white",
mask=img, font_path="msyh.ttc")
w.generate(txt)
w.to_file("threekingdoms.png")