零.文章出处
https://blog.csdn.net/Eastmount/article/details/108737755
- 文本仅仅是个人对于杨老师的文章的学习笔记总结,请支持原文
一.文件操作
-
文本文件编码方式包括ASCII格式、Unicode码、UTF-8码、GBK编码等。
-
文件的操作流程为“打开文件-读写文件-关闭文件“。
1.打开文件
打开文件调用open()函数实现,其返回结果为一个文件对象,函数原型如下:
<variable> = open(<name>, <mode>)
-<name>表示打开文件名称
-<mode>表示文件打开模式
123
其中mode常见参数包括:
-
r: 只读,文件指针将会放在文件的开头
-
w:只写,如果文件已存在则打开文件,并从开头开始编辑。
w模式下原有内容会被删除;如果该文件不存在,创建新文件
- a: 打开一个文件用于追加,如果该文件已存在,文件指针将会放在文件的结尾;如果该文件不存在,创建新文件进行写入
a模式是追加内容,新的内容在文件的最后面,不存在和w相同,都会创建新的文件。
b表示二进制
-
rb: 只读二进制文件,一般用于非文本文件如图片等
-
wb: 只写二进制文件,一般用于非文本文件如图片等
-
ab: 以二进制格式打开一个文件用于追加
-
w+: 打开一个文件用于读写
open()函数的完整语法如下:
- open(file, mode=‘r’, buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
help(open)
注意文件用什么编码格式编码的,就要用什么编码格式打开。
可以发现第一不设置,打开的编码,发现对象的编码类型是cp936,第二次设置打开编码为encoding=utf8’就会报错
举一个简单的例子:
infile = open("test.txt","r")
有打开文件对象就要有close()关闭文件对象,不然会占用内存。
2.读写文件
(1) 读文件
常用文件读取方法包括:
- read()一次性读取所有文件,对象的返回值s整个文本内容的一个字符串
- readline()一次读取指针所在一行,返回值为文件内容的下一行内容的字符串
- readlines()一次读取所有内容,且将所有的内容阿a返回值为整个文件内容的列表,列表中每项为一行字符串
示例如下:
infile = open("test.txt","r",encoding="utf8")
data = infile.read()
print(data)
print("")
infile = open("test.txt","r",encoding="utf8")
list_data = infile.readlines()
print(list_data)
输出结果如下图所示:
(2) 写文件
从计算机内存向文件写入数据,方法包括:
- write(),每次写入一个字符串文件把
- writelines(),每次写入一个列表文件,针对列表操作,接收一个字符串列表参数,并写入文件
outfile1 = open('test.txt','a+',encoding="utf8")
str1 = '\nhello\n'
str2 = 'world\n'
outfile1.write(str1)
outfile1.write(str2)
outfile1.close()
outfile2 = open('test02.txt','w',encoding="utf8")
outfile2.writelines(['hello',' ','world'])
outfile2.close()
针对test.txt文件完成追加写入操作,针对test02.txt文件完成新建及写入操作,同时调用write()和writelines()不同方法写入数据。
3.关闭文件
-
文件写入操作结束后,需要对文件执行关闭操作。
-
如果没有关闭文件,可能导致程序崩溃,不再写入文件,也可能导致写入的文件丢失。
-
老师建议使用try-except-finally异常捕获语句,在finally子句中关闭文件。
try:
#文件操作
except :
#异常处理
finally:
file.close()
其他方法包括:
- file.flush():刷新文件内部缓冲
- file.next():返回文件下一行
- file.seek(offset[, whence]):设置文件当前位置
offset - 这是文件中读/写指针的位置。
whence - 这是可选的,默认值为0,表示绝对文件定位,其他值为1,表示相对于当前位置的查找,2表示相对于文件结尾的查找。
文件读取后,指针会跟着移动,可以用这个方法定义指针的位置,再读取文件。
- file.tell():返回文件当前位置
- file.truncate([size]):截取文件,截取的字节通过size指定
4.循环遍历文件
在数据爬取或数据分析中,常常会涉及到文件遍历,通常采用for循环遍历文件内容,一方面可以调用read()函数读取文件循环输出,另一方面也可以调用readlines()函数实现。其两种方法的对比代码如下所示:
infile = open('test02.txt', 'r', encoding="utf8")
for line in infile.readlines():
print(line)
print(infile.close())
infile = open('test02.txt', 'r', encoding="utf8").read()
for line in infile:
print(line)
print(infile.close())
输出结果《静夜思》如下图所示,包含TXT文件和输出值。
二.CSV文件操作
CSV,逗号分隔符,值与值之间用分号分隔。Python小阳台导入CSV扩展包使用,包括写入文件和读取文件。
1.CSV文件写
基本流程如下:
- 导入CSV模块
- 创建一个CSV文件对象
- 写入CSV文件
- 关闭文件
# -*- coding: utf-8 -*-
import csv
c = open("test-01.csv", "w", encoding="utf8") #写文件
#需要创建一个csv的写入对象
writer = csv.writer(c)
#讨论过写入对象写入数据
writer.writerow(['序号','姓名','年龄']) #按照行写入,row
#先将要写的一行数据放进一个列表
tlist = []
tlist.append("1")
tlist.append("小明")
tlist.append("10")
#再将数据写入
writer.writerow(tlist)
print(tlist,type(tlist))
del tlist[:] #清空所有数据
tlist.append("2")
tlist.append("小红")
tlist.append("9")
writer.writerow(tlist)
print(tlist,type(tlist))
c.close()
老师输出结果如下图所示:
我的数据。。。。。。。。。。。。。。。。。。。。。。。。。
注意,此时会出现多余空行,我们需要进行简单的处理,加入参数“newline=‘’”解决。
- c = open(“test-01.csv”, “w”, encoding=“utf8”, newline=’’)
2.CSV文件读
基本流程如下:
- 导入CSV模块
- 创建一个CSV文件对象
- 读取CSV文件
- 关闭文件
# -*- coding: utf-8 -*-
import csv
c = open("test-01.csv", "r", encoding="utf8") #读文件
reader = csv.reader(c)
for line in reader:
print(line[0],line[1],line[2])
c.close()
1234567
输出结果如下图所示:
在文件操作中编码问题是最让人头疼的,尤其Python2的时候。但只需要环境编码一致,注意相关转换也能有效解决,而Python3文件读写操作写清楚encoding编码方式就能正常显示。如果是数据库、网页、后台语言,三者编码方式需要一致,比如utf8或gbk等,具体问题具体解决吧!后续作者会结合爬虫讲解CSV文件的操作。
三.面向对象基础
传统的编程方式是面向过程的,根据业务逻辑从上到下执行,而面向对象编程是另一种编程方式,此种编程方式需要使用“类”和“对象”来实现,将函数进行封装,更接近真实生活的一种编程方式。
面向对象是将客观事物看做属性和行为的对象,通过抽象同一类对象的共同属性和行为,形成类,通过对类的继承和多态实现代码重用等。对象(Object)是类(Class)的一个实例,如果将对象比作房子,那么类就是房子的设计图,并在类中定义了属性和方法。
面向对象的三个基本特征为:
- 封装:把客观事物封装成抽象的类,类中数据和方法让类或对象进行操作。
- 继承:子类继承父类后,它可以使用父类的所有功能,无需重新编写原有类,并且可以对功能进行扩展。
- 多态:类中定义的属性或行为,被特殊类继承后,可以具有不同的数据类型或表现不同的行为,各个类能表现不同的语义,实现的两种方法为覆盖和重载。
在Python中,类就是一个模板,模板里可以包含多个函数,函数里实现一些功能;对象则是根据模板创建的实例,通过实例对象可以执行类中的函数。如下:
#创建类
class 类名:
#创建类中的函数,self特殊参数,不能省略
def 函数名(self):
#函数实现
#根据类创建对象obj
obj = 类名()
12345678
假设需要编写一个计算长方形面积和周长的程序,其思想是定义两个变量长和宽,然后再在类中定义计算面积和周长的方法,实例化使用。代码如下:
#-*- coding:utf-8 -*-
class Rect:
def __init__(self, length, width):
self.length = length;
self.width = width;
def detail(self):
print(self.length, self.width)
def showArea(self):
area = self.length * self.width
return area
def showCir(self):
cir = (self.length + self.width) * 2
return cir
#实例化
rect1 = Rect(4,5)
#调用函数
rect1.detail()
area = rect1.showArea()
cir = rect1.showCir()
print('面积:', area)
print('周长:', cir)
123456789101112131415161718192021222324
输出结果面积为20,周长为18。对于面向对象的封装来说,其实就是使用构造方法将内容封装到对象中,然后通过对象直接或者self间接获取被封装的内容。
整体而言,面向对象是站在事物本身的角度去思考解决问题,如果上面采用面向过程定义函数的形式实现,当出现多个形状时,你需要对每一种形状都定义一种方法,而面向对象只需把这些形状的属性和方法抽象出来,形成各种形状,更符合真实情况。
注意:为了更简明快速的让读者学习Python数据爬取、数据分析、图像识别等知识,本系列中的代码很少采用定义类和对象的方式呈现,而是直接根据需要实现的功能或案例,直接编写对应的代码或函数实现。这是不规范和不合理的,在实际开发或更加规范的代码中,更推荐大家采用面向对象的方法去编程,但本系列更想通过最简洁的代码告诉你原理,然后你再去提升和锻炼自己的能力。
设计模式中的面向对象
再举个例子:为了方便儿童学习编程,X公司开发了一套Racing Car模拟器,使用这个模拟器每个孩子都可以用一种简单的语言来控制一辆赛车,例如right、left等。请设计一种简单的语言,给出它的语法以及该语言的类图。这就是我们实际编程中联系到生活的问题,它涉及到了设计模式相关知识,其中我采用的方法是“命名模式”实现的,客户端是定义Children和Car,请求者是Children发出的Right、Left、Up、Down命令,接受者是Car执行Move(),抽象命令是上下左右的抽象接口,具体命令是Car的上下左右。我制作的类图如下:
在这个例子中,我们使用了面向对象的思想,站在事物本身的角度去思考解决问题,而不是面向过程定义函数的形式实现。如果又出现一个空陆两地车,它不仅能上下左右移动,还能飞行,传统的方法还需要再写四个上下左右移动的方法,而面向对象直接继承Car,补充一个飞行新方法即可(不含方向),这就是面向对象的好处。同样,通过这个例子我不是想证明所采用的命令模式或画的类图是否正确,我想阐述的是我们学习面向对象知识主要是用来解决实际生活中的问题,让它更加高效地解决问题和优化代码。同时,面向对象思想要适应需求的变化,解决用户的实际需求,在设计时就要尽量考虑到变化,会涉及到抽象、封装变化(重点)、设计模式等知识。