python文件操作函数_python基础之文件操作,集合,函数

文件操作:

打开文件的方法:

第一种:打开文件执行完命令后,需要关闭文件,否则会一直占用内存空间

f=open('/data/1.txt','r+') #后面的r+ 表示打开文件的模式是读写

#命令

f.close #关闭文件

第二种:这种会自动关闭文件,不用我们手动关闭,这种写法被称为python中的语法糖。

with open('/data/1.txt','r+') as f:

#命令

##################

打开文件的模式:

r : 只读模式,默认如果不加模式就是只读模式

r+: 读写模式,读,写,追加,如果文件不存在会报错。

w:只写模式 ,会覆盖文件内容,如果文件不存在会创建

w+: 写读模式 ,会覆盖文件内容,如果文件不存在会创建

a:追加模式 ,如果文件不存在会创建

a+:和a的意思一样

b :二进制(字节)模式处理文件。 当需要处理二进制文件时,需要加一个b,比如rb,wb,ab, 需要注意的是b的方式在打开或写入时不能指定编码格式,只能打开后加.decode('utf-8')进行解码, 用wb方式写入时需要将字符串转化为字节

###########################################################

小例子:编码错误

#!/usr/bin/env python#encoding:utf-8

f= open('歌词','r')

data=f.read()

f.close()print(data)#执行结果:

UnicodeDecodeError: 'gbk' codec can't decode byte 0x80 in position 22: illegal multibyte sequence

#分析

当时编辑 '歌词' 这个文件时,我的编辑器的编码是utf-8 , 所以 '歌词'这个文件编码就是utf-8, 现在用open()函数打开,open()函数会去找系统的默认编码,windows的系统一般是gbk编码格式的,所以会报错,而mac默认编码就是utf-8,打开就不会报错了,这里的解决办法是在打开文件时,指定编码格式#指定编码格式

f = open('歌词','r',encoding='utf-8')

data=f.read()

f.close()print(data)

小例子: 二进制模式读取文件

#错误示例:

f = open('666.txt','rb',encoding='utf-8')

data=f.read()

f.close()print(data)#执行结果

ValueError: binary mode doesn't take an encoding argument

#二进制模式处理文件时,不能用encoding 指定编码

#正确示例:

f = open('666.txt','rb')

data=f.read()

f.close()print(data)#执行结果:

b'66666\r\n2312313'

#注意windows 中的换行符是 \r\n 而linux中是\n 开头的b表示字节

#特别注意:当666.txt 这个文件里有中文,这个时候print (data) 会出现 xe4\xb8 这种16进制的,无法看到中文,这个时候需要用.decode()解码,print(data.decode())

小例子:二进制模式写文件

#错误示例

txt1='''又一年花如绣,山中雪埋红豆。

曾是谁把盏问,可饮一杯否。'''f=open(txt1.log,'wb')

f.write(txt1)

f.close()#执行结果

TypeError: a bytes-like object is required, not 'str'

#字符串不能用b写入,必须转化成字节

#正确示例

f=open('txt1.log','wb')

f.write(txt1.encode(encoding='utf-8'))

f.close()

#分析:因为用b写文件必须转成字节格式,所以用encode()编码,encode()里面可以指定编码格式,我这里是utf8,特别注意,前面说过b模式不能指定编码格式,说的是用open()函数打开的时候不能指定,我在打开后指定的

#bytes() 函数也可以转换成字节,bytes(txt1,encoding='utf-8')

#字符串 ---------- encode() -----------> 字节 ,编码过程

#字节 ---------- decode() -----------> 字符串 ,解码过程

下面来看用with处理文件的小例子:

txt1='''又一年花如绣,山中雪埋红豆。

曾是谁把盏问,可饮一杯否。'''with open('123.txt','a') as f:

f.write(txt1)

with open('123.txt','r') as f:

a=f.read()

with open('123.txt','r') as f:

b=f.read(9)print(a)print(b)#执行结果:

又一年花如绣,山中雪埋红豆。

曾是谁把盏问,可饮一杯否。

又一年花如绣,山

上面这段代码会把txt1中的内容追加到123.txt这个文件中。 然后用read()读出全部赋值给a并打印出来,也可以指定读取的字符长度,赋值给b打印出来。但是:如果文件大的话不要用read()这种方法,可能不能全部读出来

特别注意:文件操作中除了read()方法 是读取的字符,其他方法都是读取的字节,在utf-8编码中,一个汉字占3个字节

除了用read读之外还好有其他方式,下面来介绍:

with open('123.txt','r') as f:

line1=f.readline()print (line1)

line1的结果: 又一年花如绣,山中雪埋红豆。

说明readline()只读了一行。 如果要读全部内容那就用循环去一行一行的读呗,如下方法:

with open('123.txt','r') as f:whileTrue:

line1=f.readline()if len(line1) ==0:break

print (line1)

readline()用这种循环的方法就把全部内容都读了出来!

with open('123.txt','r') as f:

line2=f.readlines()print (line2)

line2的结果:['又一年花如绣,山中雪埋红豆。\n', '曾是谁把盏问,可饮一杯否。\n']

说明readlines() 全读出来了,但读出来的是一个列表。 当文件很大的时候不建议用这种 ,可能会出现卡住的情况

小例子:write写文件的时候只能写字符串 , writelines 可以写列表,但是列表中的元素必须是字符串

f = open('1.txt','w',encoding='utf-8')#用write写的时候只能写字符串

f.write('11111111111\n')#如果不加换行符,会写在一行里

f.write('2222222222222\n')#用writelines 可以写列表,但是列表中的元素必须是字符串

f.writelines(['1\n','2\n'])

f.close()

获取真正的换行符

#前面的例子说过,二进制模式rb读取文件时,可以看到windows系统的换行符是 \r\n#假如不用二进制模式打开,用默认的文本模式打开看到换行符不是 \r\n

f= open('1.txt','r')

data=f.readlines()

f.close()print(data)#执行结果:

['11111111111\n', '2222222222222\n', '1\n', '2\n']#分析,因为python 会处理来自不同系统的文件,所以python内部做了转换,统一把换行符转成 \n ,如果要显示真实的换行符 可以在打开文件时加 newline=''

f= open('1.txt','r',newline='')

data=f.readlines()

f.close()print(data)#执行结果:

['11111111111\r\n', '2222222222222\r\n', '1\r\n', '2\r\n']

文件游标

with open('333.txt','w') as f:

f.write(txt3)

with open('333.txt','r') as f:print(f.tell())print (f.readline().strip()) #strip表示去掉换行符和空格

print(f.readline().strip())print(f.tell())

f.seek(0)print(f.readline().strip())#执行结果:

0121212121233qwertyu23

121212121233

说明:tell() 方法会显示当前的指针(游标)位置,第一次肯定是0,然后读了两行,那指针位置就是在两行之后,然后用seek(0)方法把指针位置调整到0,seek()方法控制指针的位置。再次读取一行,还是读取的第一行,因为指针在哪,就从哪里开始读。

seek()方法的高级用法

seek() 方法的作用就是控制指针的位置

seek() 方法其实有三种模式,分别是 0 , 1 , 2我下面会举例说明

第一种 0模式,从头开始(默认的模式)

text= '''123333456789

qwertyuio

我是好人

666'''f= open('seek.log','w',encoding='utf-8')

f.write(text)

f.close()

f= open('seek.log','r',encoding='utf-8')print(f.tell())

f.seek(5)print(f.tell())

f.seek(6,0)print(f.tell())print(f.read())

f.close()#执行结果:

05

6

456789qwertyuio

我是好人666

#分析: 第一个f.tell() 肯定是0, 因为文件开头指针肯定是0, 然后f.seek(5)把指针从开头往后移动了5个字节, 那现在的f.tell()就是5, 然后又f.seek(6,0)从头开始移动6个字节, 现在的f.tell() 指针位置就是6, 最后f.read()的结果就是把指针后面的全部读取, 指针在6, 所以把第6个字节后面的全部读取#这种模式就是0模式, 可以写成 f.seek(5,0), 因为0可以省略, 一般就写 f.seek(5) 就行了

第二种, 1模式,相对路径

f= open('seek.log','rb')print(f.tell())

f.seek(5)print(f.tell())

f.seek(6,1)print(f.tell())print(f.read().decode())

f.close()#执行结果:

05

11

9qwertyuio

我是好人666

#分析: 第一个f.tell() 肯定是0, 因为文件开头指针肯定是0, 然后f.seek(5)这是第一个seek(), 把指针从开头往后移动了5个字节, 那现在的f.tell()就是5, 然后又f.seek(6,1)从当前指针的位置, 也就是第5个字节的位置又移动6个字节, 现在的f.tell() 指针位置就是11, 最后f.read()的结果就是把指针后面的全部读取, 指针在11, 所以把第11个字节后面的全部读取

#特别注意,因为seek()操作的是字节,字节既是二进制模式,除了默认的0模式可以不用b打开,其他两种模式都得用b打开

第三种, 2模式, 倒序

f= open('seek.log','rb')

f.seek(-10,2)print(f.tell())print(f.read().decode())

f.close()#执行结果:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa5 in position 0: invalid start byte

#分析: 因为倒数第10个字节在 好 字上,一个汉字占3个字节,好 恰好占了倒数 9,倒数10, 倒数11这三个字节, 不能把汉字拆开,所以报错

f= open('seek.log','rb')

f.seek(-11,2)print(f.tell())print(f.read().decode())

f.close()#执行结果:

31好人666

#分析:倒数第11个字节, 也就是从头开始的指针是31, 把倒数第11个字节后的或者说是正序第31个字节后的全部读取, 需要注意换行符是 \r\n 占了两个字节#特别注意,因为seek()操作的是字节,字节既是二进制模式,除了默认的0模式可以不用b打开,其他两种模式都得用b打开

文件截取truncate()

text = '''我们是共产主义接班人'''with open('test.log','w') as f:

f.write(text)

with open('test.log','r+') as f:

f.truncate(6)#查看test.log,发现文件内容是 我们#分析,在utf-8的编码中一个汉字占3个字节,除了read()是字符,其他方法都是字节。#注意:文件截取 truncate(6) 必须是可写的模式打开,但不能是w,因为w直接重新创建文件了,可以是 r+ 或者 a+

再来看文件操作的最后一个例子:

txt2='''请欣赏一首现代诗

黑夜给了我黑色的眼睛

我却用它寻找光明'''with open('new.txt','w') as f:

f.write(txt2)

with open('new.txt','r') as f:

first_line=f.readline() #读取第一行内容,指针会移动到第一行的后面,再读的时候就会去第一行后面开始读

print('first_line:',first_line)print('分割线'.center(50,'-')) #表示以'分割线'为中心,用-补齐50个长度

data=f.read() #读取剩下的内容,

print(data)#执行结果:

first_line: 请欣赏一首现代诗-----------------------分割线------------------------黑夜给了我黑色的眼睛

我却用它寻找光明

##########################

其他常用文件操作:

f.name #打印文件名字

f.flush() #把文件内容从内存刷到硬盘

f.closed #文件如果关闭则返回True

f.encoding #查看使用open()打开文件的编码, 二进制模式的没有此方法

############################

集合:

集合是一个无序的,不重复的数据类型。

list1=[1,2,3,4,5,6,7,7,7,8,9]

list1=set(list1) #集合会去重print (list1,type(list1))

结果是:{1, 2, 3, 4, 5, 6, 7, 8, 9}

结果看上去像排序了的,其实是无序的,数据多了就会看出是无序的。有点像字典,但类型是集合。

集合的方法:

1,增加

list1.add('a') #增加一个元素,可以重复添加相同的值,但是没用,集合去重的

list1.update(['b','c','d']) # 增加多个元素

2, 删除元素

list1.remove('a') #删除元素a,直接写要删除的元素名称就可以 ,但元素不存在时报错

list1.discard('a') #删除元素a,直接写要删除的元素名称就可以 ,元素不存在时不报错

list1.pop() #随机删除一个元素,因为集合是无序的

3,判断成员身份

list1=[1,2,3,4,5,6,7,7,7,8,9]

list1=set(list1)print (2 inlist1) #正确就返回Trueprint (2 not in list1) #正确就返回True

并集

list1=[1,2,3,4,5,6,7,7,7,8,9]

list1=set(list1)

list2=[1,'a',5,'b',9]

list2=set(list2)#方法一:

list3=list1|list2print(list3)#方法二:

list3=list1.union(list2)print (list3)

返回结果: {1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b'} 把两个集合的所有元素合并,然后去掉重复的

交集

list1=[1,2,3,4,5,6,7,7,7,8,9]

list1=set(list1)

list2=[1,'a',5,'b',9]

list2=set(list2)#方法一:

list3=list1 &list2print(list3)#方法二:

list3=list1.intersection(list2)print (list3)

返回结果:{1, 5, 9} 把两个集合的公共的部分取出来

差集

list1=[1,2,3,4,5,6,7,7,7,8,9]

list1=set(list1)

list2=[1,'a',5,'b',9]

list2=set(list2)#方法一:

list3=list1 -list2print(list3)#方法二:

list3=list1.difference(list2) #求list1对list2的差集,就是把list1有的,但list2没有的取出来print (list3)

返回结果:{2, 3, 4, 6, 7, 8} 求list1对list2的差集,就是把list1有的,但list2没有的取出来

子集与父集

list1=[1,2,3,4,5,6,7,7,7,8,9]

list1=set(list1)

list2=[1,5,9]

list2=set(list2)print(list2.issubset(list1)) #判断list2是否是list1的子集,也就是说list2的元素是否list1都有,如果是就返回Trueprint (list1.issuperset(list2)) #判断list1是否是list2的父集,也就是说list2的元素是否list1都有,如果是就返回True

###############################

函数

函数的作用:

1,减少代码重复性

2,使程序变得可扩展

3,使程序变得易维护

定义函数

1,

deffunc1(): #用def这个关键字去定义函数,func1 是函数名print ("hello,world") #函数里面的内容

func1() #用函数名加括号的方式去调用这个函数

2,

deffunc1():print ("this is func1")return0 #返回一个0,注意return代表函数结束,即使后面还有命令也不会执行。deffunc2():print ("this is func2")return 1,"哈哈",[1,2,3],{1:'a'} #看上去返回一堆东西,把return赋值给一个变量后,实际上打印出来的是一个元组,用元组包了起来deffunc3(a,b): #这个函数有参数,叫做形参

res=a**breturnres #返回res的值

x=func1() #执行func1函数并把return的返回值赋值给x,如果没有return,返回的是None

y=func2() #执行func2函数并把return的返回值赋值给y,如果没有return,返回的是None

z=func3(2,3) #执行func3(a,b)函数,并把2传递给a,把3传递给b,执行完命令后把结果res赋值给z,刚才说的a和b叫形参,那么2和3叫实参,就是实际传递的参数print(x)print(y)print (z)

3,默认参数

def stu(name,age,country='china'): #设置country这个参数的值是默认的,有默认参数必须放在最后print ("your name is %s" %name)print ("your age is %s" %age)print ("your country is %s" %country)

stu("zhang",18)

#执行函数时如果不指定第三个参数,那第三个参数就用默认的,如果指定了,那就按照你指定的传参,实参也可以指定固定的,比如stu("zhang",agr=19) 同样,指定的实参也必须放在后面。

#正常情况,给函数传参要按照顺序来的,不按顺序会出错,比如stu("zhang",name="li") 这样会出错,因为zhang已经传递给形参name了,再给name传递一个肯定不行了。

4,非固定参数(如果不确定用户要传入多少参数,就用非固定参数)

def stu(name,age,*args): # args 把用户传入的参数形成一个元组的形式print ("your name is %s" %name)print ("your age is %s" %age)print(args)

stu("zhang",18,'china','you are a good man')

返回结果:

your nameiszhang

your ageis 18('china', 'you are a good man')

如果传入的值是类似这种的sex="male",那 *args 就不能处理了,这就用到了 **kwargs

def stu(name,age,**kwargs): #kwargs 会把用户传递的参数形成字典形式print ("your name is %s" %name)print ("your age is %s" %age)print(kwargs)

stu("zhang",18,sex="male",country='china')

返回的结果:

your nameiszhang

your ageis 18{'country': 'china', 'sex': 'male'}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值