第7周文件和数据的格式和处理-Python语言程序设计(学习笔记
文章原创,最近更新:2018-04-26
1.文件的使用
2.实例11:自动轨迹绘制
3.一维数据的格式化和处理
4.二维数据的格式化和处理
5.所有代码汇总
原链接 语言程序设计北京理工大学
1.文件的使用
1.1单元开篇
1.2文件的类型
文本文件就是一个字符串.
二进制文件,相当于图片以及视频这类的文件.
- 以文本形式理解:
打印出来的是"中国是个伟大的国家" - 以二进制形式理解:
以二进制构成的字符串.相当于"中国是个伟大的国家"对应储存形态的二进制形式. - 两者之间的区别
通过文本形式可以更好的理解这段信息,而二进制形式是最原始的存储格式.在使用的时候,如果一个文件是文本文件,又经需要对里面的字符进行理解,我们就需要用文本形式对其打开.
仅以存储的形态,那就使用二进制对其打开储存并进行处理.
"rt"是以文本形式打开
"rb"是以二进制形式打开
可以选择二进制以及文本形式打开文件,选择哪种方式?是跟程序以及功能有关.
1.3文件的打开和关闭
- 处理文件之前,先要open文件,处理文件之后,要close文件.
- 打开文件后,可以对文件进行数据读入,以及数据输出.简称为读文件和写文件.
- 提供了三个常用的读文件函数,分别如下:
- a.read(size)
- a.readline(size)
- a.readlines(hint)
- 提供了三个常用的写文件函数,分别如下:
- a.write(s)
- a.writeline(lines)
- a.seek(offset)
- 第一个参数是文件路径和名称,指当前要打开的文件与当前程序所对应位置直接的相互关系,我们要知道打开哪个文件.
- 第二个参数是打开模式,是以文本形式打开还是以二进制形式打开.打开过程是读信息还是写信息.
- 文件打开之后用一个抽象的变量叫文件句柄来表示.
-
文件路径包含绝对路径和相对路径的名称,共四种:
比如在windows平台,保持在D盘,PYE目录下,文件名称为f.txt.(D:\PYE\f.txt)我们在打开文件的时候,需要绝对路径,可以有2种方式,如下:- 第一种:文件的路径,如"D:/PYE/f.txt"
需要注意:在windows下,文件的路径方式是 \ 方式,但是斜杠在python字符串当中,被解析为转义符.所以一般来讲,我们用反斜杠/来替代斜杠 - 第二种:文件的路径,如"D:\PYE\f.txt"
需要注意:由于在python而言,\斜杠是转义符,而\表示的是\斜杠
- 第一种:文件的路径,如"D:/PYE/f.txt"
-
文件的相对路径,是指打开的路径与当前程序直接的路径,如果当前的程序存储在D盘根目录下,希望打开PYE根目录下的f.txt文件,可以有2种方式,如下:
- 第一种:文件的路径,如"./PYE/f.txt"
指的是从当前可执行的程序的当前目录起,找它的PYE目录,以及这个目录下的f.txt文件. - 第二种:文件的路径,如"f.txt"
指的是当前的程序和文件在相同的目录里,可以直接打开f.txt这个文件.
- 第一种:文件的路径,如"./PYE/f.txt"
对于文件路径参数中,无论采取哪种方式,最终目的是,要用程序在运行当前目录下,能够很好有效的找到这个文件,无论是绝对路径还是相对路径.只要能够找到这个文件并指定这个文件的正确名称,那么读取这个文件就会比较顺利.
- "r",如果返回FileNotFoundError,可以用try/except用来捕捉异常,并进行处理.
- "x",如果返回FileExistsError,可以用try/except用来捕捉异常,并进行处理.
- "b",是以二进制的文件模式打开
- "t",是以文本的文件模式打开
- "rt"模式,指的是"r"和"t",指的就是默认情况的方式.如果使用"rt"指的就是默认值.
- 根据文件的需求,来指定打开模式.
-
无论哪种方式,要确定是文本形式还是二进制的方式打开文件,还是只读模式还是各种写入模式.组合起来就是你使用文件的打开模式.
注意:写了一个程序,只有打开文件,而没调用文件f.close()关闭这个文件,在程序运行中这个文件始终是被打开状态,但是程序退出.python解析器会自动的把这个文件关闭.写程序尽可能的增加f.close()这个函数.
- "rt"以文本读的形式打开
- "rb"以二进制读的形式打开
1.4文件内容的读取
-
用read()的方法读取文件所有的信息,返回字符串
弊端:如果这个文件特别大,有100个gb,一次性将文件读入内存,将会耗非常多的时间和资源.对于大文件而言,一次性读入文件,代价很大. -
处理文件可以分批分阶段的进行处理,就是以下图片的处理的第二种办法:
- 分阶段,按数量读入,逐步处理的办法,处理大文件更加可行有效.
- fo.read(2),每次读入2个字节
- 只要读入的信息不为空,就将持续处理下去.直到空的为止,然后退出.
- 一次性读入,进行遍历以分行处理的方法.
- fo.readlines()对所有的行以列表的形式,line是其中列表的一个元素.
弊端:一次性读入,会消耗很大的内存.以逐行的方式,以大文件的方式读出.并由程序再进行处理,再进行下一行好点.具体如下截图方法:
- 这样的模式是分行读入,逐行处理的思路.对极大的文件处理,非常有效.
- fo这里指的是文件句柄,使用for in这样的组合,可以对文件尤其是文本文件,进行逐行处理.
1.5数据的文件写入
f.writelines()是直接将列表的元素拼接写入,没有换行,没有空格,将各个元素直接拼接.然后写入文件.
文件写入后指针在文件的最后面,即下一次写入文件的位置.
- 如果调用for in的方式遍历一行,打印输出的时候,指的是当前位置处到结尾处取出一行,并且打印出来.
- 而我们写入的信息在指针的上方,并不在指针的下方,因此之前的那行代码并不能输出我们写过的信息.
- 为了输出我们写过的信息,需要调整指针回到初始位置,从初始位置再进行逐行遍历.就能把文件全部的信息打印输出.增加一行代码fo.seek(0).
注意:指针位置对文件的影响
1.6单元小结
2.实例11:自动轨迹绘制
2.1"自动轨迹绘制"问题分析
- 之前学过turtle库其中的函数以及语句,绘制图形.用程序写代码的形式,来绘制图形.
- 数据脚本自动化是非常重要的过程.
2.2"自动轨迹绘制"实例讲解
list(map(eval,line.split(",")))就是列表中的元素,都去掉了字符串的引号,变成了数字.之后用append放到datals列表.通过for in 逐一循环,去绘制我们的图形.
- 代码如下:
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])
t.fd(datals[i][0])
if datals[i][1]:
t.right(datals[i][2])
else:
t.left(datals[i][2])
-
输出结果如下:
-
数据文件,命名为data.txt,存储在当前运行的程序同一目录:
300,0,144,1,0,0
300,0,144,0,1,0
300,0,144,0,0,1
300,0,144,1,1,0
300,0,108,0,1,1
184,0,72,1,0,1
184,0,72,0,0,0
184,0,72,0,0,0
184,0,72,0,0,0
184,1,72,1,0,1
184,1,72,0,0,0
184,1,72,0,0,0
184,1,72,0,0,0
184,1,72,0,0,0
184,1,720,0,0,0 -
Python eval() 函数
- 描述
eval() 函数用来执行一个字符串表达式,并返回表达式的值 - 返回值
返回表达式计算结果。 - 实例
以下展示了使用 eval() 方法的实例:
- 描述
>>>x = 7
>>> eval( '3 * x' )
21
- python map()函数
- 描述
map() 会根据提供的函数对指定序列做映射。
第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表。
语法 - map() 函数语法:map(function, iterable, ...)
- 参数
function -- 函数,有两个参数
iterable -- 一个或多个序列 -
返回值
Python 3.x 返回迭代器。
- 实例
以下实例展示了 map() 的使用方法:
- 描述
>>>def square(x) : # 计算平方数
... return x ** 2
...
>>> map(square, [1,2,3,4,5]) # 计算列表各个元素的平方
[1, 4, 9, 16, 25]
>>> map(lambda x: x ** 2, [1, 2, 3, 4, 5]) # 使用 lambda 匿名函数
[1, 4, 9, 16, 25]
# 提供了两个列表,对相同位置的列表数据进行相加
>>> map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])
[3, 7, 11, 15, 19]
2.3"自动轨迹绘制"举一反三
- 绘图就是一种功能.绘制的进行由数据进行驱动.数据驱动是数据运行很重要的方法.这也是自动化思维的一种体现.
- 如何设置一种格式文件,使程序的交互变得很容易.使用逗号,分割数字,做接口的格式化设计
-
使用二维列表,表达数据文件.简化了程序与接口之间的关系.
- 接口设计:除了画笔的颜色,可以增加画笔的粗细,以及左转右转的其他转向方式.可以设置跳转区域到某一行中.
- 功能设计:除了左转右转,是否可以增加弧形等功能.
- 应用需求:轨迹绘制的基础绘制是线条,我们能否由线条组成小的图形.自动轨迹绘制变成动画绘制.这也是需求的改变.而动画绘制,数据驱动是更重要的思想方法.
3.一维数据的格式化和处理
3.1单元开篇
掌握一维数据存储以及处理等相关操作能力.
3.2数据组织的维度
一组数据可以采取线性方式的组织,还是采用二维方式的组织.这就构成了不同的数据组织形式.
比如:2017中国大学排行榜.
比如:中国大学排行榜有分为2016年以及2017年的排行榜,有时间维度的拓展,就变成了多维数据.
字典类型存在高维数据.
3.4一维数据的表示
使用集合以及列表就可以表达一维数据.
3.5一维数据的存储
一维数据存储在硬盘或文件中.
无论是逗号分割还是空格分割,还是特殊符合的分割.都有缺点,都不可以在元素中出现与分割符相同的.字符.通用性较差,但是一维数据都是采用这样的思路
3.6一维数据的处理
这里说的处理指的是列表与集合等方式的转换.
比如:从空格中的文件读入数据,表示列表形式.
- Python split()方法
- 描述
Python split() 通过指定分隔符对字符串进行切片,如果参数 num 有指定值,则仅分隔 num 个子字符串 - 语法
split() 方法语法:str.split(str="", num=string.count(str)). - 参数
str -- 分隔符,默认为所有的空字符,包括空格、换行(\n)、制表符(\t)等。
num -- 分割次数。 - 返回值
返回分割后的字符串列表。 - 实例
- 描述
#!/usr/bin/python
str = "Line1-abcdef \nLine2-abc \nLine4-abcd";
print str.split( );
print str.split(' ', 1 );
以上实例输出结果如下:
['Line1-abcdef', 'Line2-abc', 'Line4-abcd']
['Line1-abcdef', '\nLine2-abc \nLine4-abcd']
- Python join()方法
-
描述
Python join() 方法用于将序列中的元素以指定的字符连接生成一个新的字符串。 -
语法
join()方法语法:
-
str.join(sequence)
-
参数
sequence -- 要连接的元素序列。
返回值
返回通过指定字符连接序列中元素后生成的新字符串。 -
实例
str = "-";
seq = ("a", "b", "c"); # 字符串序列
print str.join( seq );
以上实例输出结果如下:
a-b-c
3.7单元小结
4.二维数据的格式化和处理
4.1单元开篇
4.2二维数据的表示
这里的列表不是普通的列表,是指二维列表.其中每个数据代表二维数据的一行,或者一列.若干行若干列形成的外围列表,就构成了我们所说的二维列表.二维列表可以处理几乎所有相关的二维列表相关的数据操作.
使用两层for循环遍历每一个元素.
4.3CSV格式与二维数据存储
用逗号分割词的一种存储方式.
如果csv元素有逗号(,),则在数据两侧加引号,这个逗号不是分割元素的逗号.所以在判断程序的时候,在判断程序的外侧是否有引号.还有另一种方法,在数据有逗号的地方,增加转义符/.
先行后列获得其中的元素.
4.4二维数据的处理
4.5单元小结
5.所有代码汇总
#AutoTraceDraw.py
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])
t.fd(datals[i][0])
if datals[i][1]:
t.rt(datals[i][2])
else:
t.lt(datals[i][2])