day3-Python集合、函数、文件操作,python包的概念
本节大纲:
1 python程序由包(package)、模块(module)和函数组成。包是由一系列模块组成的集合。模块是处理某一类问题的函数和类的集合。
2 包就是一个完成特定任务的工具箱。
3 包必须含有一个__init__.py文件,它用于标识当前文件夹是一个包。
4 python的程序是由一个个模块组成的。模块把一组相关的函数或代码组织到一个文件中,一个文件即是一个模块。模块由代码、函数和类组成。导入模块使用import语句。
5 包的作用是实现程序的重用
一:在执行list()函数或者dict()函数首先是调用list()函数或者dict()方法会自动调用该函数的__init__方法进行数据的初始化,list()函数通过一个可迭代的对象,用for循环进行遍历插值。
1 list_test=list((1,2,3,)) 2 print(list_test) 3 [1, 2, 3]
上述的过程:首先list()函数调用本身的__init__方法进行数据的初始化,通过for循环,把元组(1,2,3,) 遍历插入列表[1,2,3,]
二:集合
集合是无序数据类型,元素不可以重合。如果集合内元素重复会自动去重。用大括号表示和字典表示一样,字典是无序的数据类型,但是key-value的映射。
1 set_a=set([1,2,2,3,]) 2 print(set_a) 3 4 {1, 2, 3}
可以通过内部函数set()对集合进行转换。字典、字符串、列表都可以转换成集合。
1 set_b=set({'name':'evil',}) 2 set_c=set('evil') 3 set_d=set([1,2,3,]) 4 print(set_b,set_c,set_d) 5 6 {'name'} {'i', 'l', 'e', 'v'} {1, 2, 3}
1、操作集合
1)add()函数。添加元素给集合。
1 s_tets=set() 2 s_tets.add(456) 3 s_tets.add(456) 4 s_tets.add(456) 5 print(s_tets) 6 {456}
应用场景:爬虫。在返回url保存的时候可以用集合操作,默认去除重复的元素。
2)difference()函数。比如a.difference(b)表示a存在元素b不存在元素。但是a和b本身的集合不发生改变。
1 s1_testa={1,2,3,} 2 s2_testb={2,5,6,} 3 print(s1_testa.difference(s2_testb)) 4 print(s2_testb.difference(s1_testa)) 5 print(s2_testb,s1_testa) 6 7 {1, 3} 8 {5, 6} 9 {2, 5, 6} {1, 2, 3}
3、symmetric_difference()函数,比如a.symmetric_difference(b)表示a和b集合去掉交集部分的结合。并不能改变集合a和b的值。
s1_testa={1,2,3,} s2_testb={2,5,6,} print(s1_testa.symmetric_difference(s2_testb)) print(s2_testb,s1_testa) {1, 3, 5, 6} {2, 5, 6} {1, 2, 3}
3)上述的操作不能修改原集合的值。如果想修改原集合的值。用如下函数:a.difference_update(b)函数。会修改集合a的值。b值不变。a值会变成。a存在的元素且b不存在的元素的值。
1 set_a={1,2,3,4,} 2 set_b={'c',6,3,5,} 3 set_a.difference_update(set_b) 4 print(set_a) 5 print(set_b) 6 {1, 2, 4} 7 {'c', 3, 5, 6}
4)同样a.symmetric_difference_update(b)函数也会修改a的值,使a的值变为,a、b集合的去除公共元素的集合。
1 set_a={1,2,3,4,} 2 set_b={'c',6,3,5,} 3 set_a.symmetric_difference_update(set_b) 4 print(set_a) 5 print(set_b) 6 {1, 2, 4, 5, 6, 'c'} 7 {3, 5, 6, 'c'}
5)删除集合指定元素。discard()函数。如果该元素不存在不会报错。
1 set_a={1,2,3,4,} 2 set_a.discard(1) 3 print(set_a) 4 set_a.discard(111) 5 print(set_a) 6 {2, 3, 4} 7 {2, 3, 4}
同样也可以用remove()函数,但是不存在元素会报错。KeyError: 111
1 set_a={1,2,3,4,} 2 set_a.remove(111) 3 print(set_a) 4 set_a.remove(111) 5 KeyError: 111 6 7 set_a={1,2,3,4,} 8 set_a.remove(4) 9 print(set_a) 10 {1, 2, 3}
也可以用pop()函数删除元素。但是随即删除一个元素。
1 set_a={1,2,3,4,5,6,7,8} 2 set_a.pop() 3 print(set_a) 4 5 {2, 3, 4, 5, 6, 7, 8}
6)批量添加元素。用update()函数。通过for循环对迭代的对象(比如说列表,字符串,字典的keys以及字典的value值),进行add()操作添加。
1 1 set_a=set() 2 2 list_a=[1,2,3,4,5,4] 3 3 set_a.update(list_a) 4 4 print(set_a) 5 5 {1, 2, 3, 4, 5} 6 7 set_a=set() 8 set_b=set() 9 list_a={'name':'evil','age':22} 10 list_b={'name':'evil','age':22} 11 set_a.update(list_a)##默认对key值进行迭代。 12 print(set_a) 13 set_b.update(list_b.values()) 14 print(set_b) 15 {'name', 'age'} 16 {'evil', 22}
7)当我们在执行一些列表或者其他操作的时候,会调用list()函数的一些方法。比如:
1 list_a=[1,2,3] ##调用list的__init__方法 2 print(list_a[0])##调用list的__getitem__方法 3 list_a[0]=44##调用list的__setitem__方法 4 del list_a[2]##调用list的__delitem__方法
8)在写列表或者字典、集合、元组的时候,进行最后元素加个逗号,在以后django学习的过程中不加逗号有时候会报错。
1 list_a=[1,2,3,] 2 dict_a={'a':2,'b':3,} 3 tuple_a=(1,2,3,)
9)集合的并集、交集。
交集函数:a.intersection(b)和a.intersection_update(b)前一个函数不改变原先集合(a,b)的值,后一个更新被交集的集合(a)。
1 s1_testa={1,2,3,} 2 s2_testb={2,5,6,} 3 s3=s1_testa.intersection(s2_testb) 4 print(s3,s1_testa,s2_testb) 5 {2} {1, 2, 3} {2, 5, 6} 6 s1_testa={1,2,3,} 7 s2_testb={2,5,6,} 8 s1_testa.intersection_update(s2_testb) 9 print(s1_testa,s2_testb) 10 {2} {2, 5, 6}
并集函数:a.union(b)
1 s1_testa={1,2,3,} 2 s2_testb={2,5,6,} 3 s3=s1_testa.union(s2_testb) 4 print(s3,s1_testa,s2_testb) 5 {1, 2, 3, 5, 6} {1, 2, 3} {2, 5, 6}
10)练习:
在cmdb日常资产管理的时候,日常服务器检测硬件信息收集中,如果一个服务器4个内存插槽,#1、#2、#4插槽分别插,4G、8G、16G。如果现在变化#1插槽变为16G,#2不变,3#插槽插4G的,#4不插。该如何更新信息呢?
1、该删除那个元素?
2、该更新那个元素?
3、那个元素变了,需要更新?
1 dict_old={ 2 '#1':4, 3 '#2':8, 4 '#4':16, 5 } 6 dict_new={ 7 '#1':4, 8 '#2':8, 9 '#3':4, 10 }
答案:
1 set_old=set(dict_old.keys())##生成keys值得集合 2 set_new=set(dict_new.keys()) 3 del_item=set_old.difference(set_new)##old有的new没有的 4 print('delete item %s'%del_item) 5 up_item=set_new.difference(set_old)##new有的old没有 6 print('add item %s'%up_item) 7 a=set_old.intersection(set_new)## old和new的集合 8 for i in a: 9 if dict_new[i]!=dict_old[i]: 10 print('update item: %s'%i)##交集的元素value值不相当,需要更新的。
三:函数:函数组成:
def functionname(parameter):###由关键字def进行定义,然后函数名字(functionname)和函数参数。
#function description ###函数的描述,作用;参数作用;
function body ##函数体,执行代码
return value## 函数返回值。缺省值是None。
以下是发邮件代码:
1 def sendmail(): 2 try: 3 import smtplib 4 from email.mime.text import MIMEText 5 from email.utils import formataddr 6 msg = MIMEText('邮件内容', 'plain', 'utf-8') 7 msg['From'] = formataddr(["xxx",'xx@126.com']) 8 msg['To'] = formataddr(["走人",'xx@qq.com']) 9 msg['Subject'] = "主题" 10 11 server = smtplib.SMTP("smtp.126.com", 25) 12 server.login("username", "password") 13 server.sendmail('xxx@126.com', ['xxx@qq.com',], msg.as_string()) 14 server.quit() 15 except: 16 # 发送失败 17 return "失败" 18 else: 19 # 发送成功 20 return "cc" 21 22 ret = sendmail() 23 print(ret) 24 if ret == "cc": 25 print('发送成功') 26 else: 27 print("发送失败")
执行顺序:
python在执行py文件的时候从上到下依次执行。上面的sendmail.py文件,首先执行1:定义一个函数sendmail() 并不执行函数体。而是往下执行,遇到函数依然这样执行,首先让解释器知道定义这个函数,到第2部分的时候,也就是函数的调用部分的时候,
解释器会跳到该程序sendmail()函数部分,并给sendmail的形参传入相应的参数值。执行函数体,也就是标记的3部分。当函数体执行完之后,返回函数值赋值给ret值。然后程序往下执行,第4部分。
1)函数一旦执行return语句的时候,函数立即终止。不会执行函数体下面的代码。
1 def test(): 2 print(1+1) 3 return True 4 print(222) 5 6 if __name__=='__main__': 7 test() 8 2
2)函数的参数:
1、普通参数(严格按照顺序,讲实际参数赋值给形式参数)
2、默认参数(必须放置在参数列表的最后)
3、指定参数(将实际参数赋值给指定形式参数)
4、动态参数:
* 默认传入的参数。全部放在元组中。
** 默认传入的参数。全部放在字典中。
1、有限的形参。
1 def mon(x,y):###其中x,y是形参。 2 a=x+y 3 return a 4 res=mon(1,2)##给函数mon()传入实参。并执行函数体a=1+2 并返回a的值。赋值给res 5 print(res) 6 3
执行顺序:
1)首先读取程序定义函数mon()部分。
2)然后执行mon(1,2)函数调用部分并给函数mon(x,y)的形参传入实参(1,2)再执行3部分的函数体,执行函数体并函数返回a的值 。
3)返回a的值 并赋值给res变量,这是执行第4步。
4)然后执行第5部分打印输出res变量。
需要注意的是:
1)在有限的形参的函数,在给传入实参的时候,实参的个数和形参的个数必须一致。
2)实参和形参 是一一对应的。如果没有默认参数的情况下,数目必须一致。
否则会报错:TypeError: mon() missing 1 required positional argument: 'y'。
2、默认参数:
在函数的定义的过程中,可以给形参定义缺省值。如果该形参没有传入实参的时候会用缺省值。如果传入的实参个数和形参的个数一致的时候,不会使用缺省值。
1 def mon(x,y=9): 2 a=x+y 3 return a 4 res=mon(1) 5 res1=mon(1,4) 6 print(res) 7 print(res1) 8 10 9 5
默认情况未指定实参数位置,实参传入会从左到右 一次匹配形参。如果你指定默认参数位置的时候,未指定参数按默认形式匹配,指定的参数会按指定匹配。如下所示。
1 def mn(a,b=2,c=2): 2 SUM=a+b+c 3 return SUM 4 5 res=mn(1,2) 6 res1=mn(1) 7 res2=mn(1,c=3)####默认是从形参的开头从左到右一次匹配。 8 print(res,res1,res2) 9 10 5 5 6
需要注意:
默认参数的位置必须在最后,比如上面的 不可以这么写:def mon(y=9,x)这样会报错!!
3)指定参数:
当我们用形参的时候,在传入实参的时候不指定位置的时候,会依次对应。如果在传入实参的指定参数的时候,实参的位置的可以无序的。比如:
1 def mon(x,y=9): 2 a=x+y 3 return a 4 res=mon(x=1) 5 res1=mon(x=1,y=4) 6 res2=mon(y=2,x=4) 7 print(res) 8 print(res1) 9 print(res2) 10 10 11 5 12 6
4)不固定参数。*args
1 def mn(*args): 2 print(args,type(args)) 3 mn(1,2,3,4,) 4 mn([1,2,3,4,]) 5 6 7 def mn_1(args): 8 print(args,type(args)) 9 mn_1([1,2,3,]) 10 11 (1, 2, 3, 4) <class 'tuple'> 12 ([1, 2, 3, 4],) <class 'tuple'> 13 [1, 2, 3] <class 'list'>
如果想传入的参数是字典。该怎么办呢???
1 def mn(*args): 2 return args 3 4 dic={'a':2,'b':3} 5 res=mn(*dic) 6 print(res) 7 8 ('b', 'a') ###这种情况 只能传入字典的key值 形式元组。
同样如果这么处理的话,传入的列表。不在是由传入列表组成的元组。而是把列表中的元素 变为元组的元素。
1 def mn(*args): 2 return args 3 4 list_1=[1,2,3,4,]####传入的是列表的实参 直接转成元组的。而不是([1,2,3,4,]) 5 res=mn(*list_1) 6 print(res) 7 8 (1, 2, 3, 4)
也就是说,在形参不带*和不带*区别:
1)args:不带*的参数,在传入实参的时候 ,传入的实参的个数也是一个。需要数目一致。传入的实参的数据类型是什么,赋值之后数据类型就不会改变。
2)*args:带*的参数,在传入实参的时候,实参的个数可以是一个,多个。没有个数的限制。但是传入的实参,最后赋值之后,会形式一个元组形式的元素组成,,无论你传入是字符串、数字、列表还是字典。元素保持传入实参的数据类型,比如是列表,传入时候元组是由列表元素组成。
1 def mn(*args): 2 print(args,type(args)) 3 mn(1,2,3,4,) 4 mn([1,2,3,4,],2) 5 mn({ 6 'name':'evil', 7 'age':22, 8 }) 9 10 11 (1, 2, 3, 4) <class 'tuple'> 12 ([1, 2, 3, 4], 2) <class 'tuple'> 13 ({'age': 22, 'name': 'evil'},) <class 'tuple'>
5)带**形参形式。
这种形式的参数必须要传入这种形式的:key=value。否则报错。形参赋值之后是由元素的组成的字典。
1 def mk(**args): 2 return args 3 4 res=mk(a=2,) 5 res1=mk(op={ 6 'age':21, 7 'name':'tom', 8 }) 9 print(res,type(res)) 10 print(res1,type(res1)) 11 {'a': 2} <class 'dict'> 12 {'op': {'name': 'tom', 'age': 21}} <class 'dict'>
如果传入的实参是字典,不是key=value 该如何处理呢???
1 def mn(**kwargs): 2 return kwargs 3 4 dic={'a':2,'b':3} 5 res=mn(**dic)#####需要注意进行调用的时候进行**形式进行形参的赋值。 6 print(res) 7 8 9 {'a': 2, 'b': 3}
6)万能参数:(格式*在**前面)
1 def mn(*args,**kwargs): 2 return args 3 def mn1(*args,**kwargs): 4 return kwargs 5 6 res=mn(1,2,3,) 7 print(res,type(res)) 8 res_1=mn1(a=2) 9 print(res_1,type(res_1)) 10 11 (1, 2, 3) <class 'tuple'> 12 {'a': 2} <class 'dict'>
也就说,当形参:(*args,**kwargs)形式的时候,当传递参数不固定的字符串、列表、字典等,则赋值给形参args并形成一个元组。而传递实参是key=value形式的时候,则赋值给:kwargs 形成一个字典。
我们称这种形参方式叫做万能参数(自己称呼)。
1 def mn(*args,**kwargs): 2 print(args) 3 print(kwargs) 4 5 res=mn(1,2,3,a=2,c=3,) 6 7 (1, 2, 3) 8 {'c': 3, 'a': 2}
也就是说:
按上图的所示进行实参的赋值。
3)format()函数字--符串的初始化:
2种形式:
1、
1 name='evil' 2 age='22' 3 id=1318 4 pre=''' 5 This is %s information: 6 NAME:%s 7 AGE:%s 8 ID:%s 9 '''%(name,name,age,id) 10 print(pre) 11 12 this is evil information: 13 NAME:evil 14 AGE:22 15 ID:1318
2:用formate()函数进行初始化。如上的例子修改为:
1 name='evil' 2 age='22' 3 id=1318 4 pre=''' 5 This is {0} information: 6 NAME:{1} 7 AGE:{2} 8 ID:{3} 9 '''.format(name,name,age,id) 10 print(pre) 11 12 This is evil information: 13 NAME:evil 14 AGE:22 15 ID:1318
其中有{num}比如上面的{0},{1}....是占位符。与后面的变量的依次对应。
需要注意的是其中0,1,2,3的数字对应后面的变量(name,name,age,id)所形成的元组的索引或者是字典的key值。不能随便修改成下面。会报错的或者显示的效果不是我们想要的。
1 name='evil' 2 age='22' 3 id=1318 4 pre=''' 5 This is {1} information: 6 NAME:{2} 7 AGE:{2} 8 ID:{3} 9 '''.format(name,name,age,id) 10 print(pre) 11 12 This is evil information: 13 NAME:22 14 AGE:22 15 ID:1318
或者报错:
name='evil' age='22' id=1318 pre=''' This is {1} information: NAME:{2} AGE:{2} ID:{4} '''.format(name,name,age,id) print(pre) Traceback (most recent call last): File "C:/xx", line 9, in <module> '''.format(name,name,age,id) IndexError: tuple index out of range
format()函数结构:
所以根据可以传递列表、key=value形式:
1 info=['evil',22] 2 print('my name is {0} and age is {1}'.format(*info)) 3 4 my name is evil and age is 22
用*info形式的进行传入实参。列表info会转换成('evil',22)的元组。然后进行索引的对应。
1 info={'name':'evil','age':22} 2 print('my name is {name} and age is {age}'.format(**info)) 3 4 my name is evil and age is 22
注意这种形式实参传入,其中的占位符是字典的key值,而不是索引!!! 传入的是字典不是元组了。也就是用format()函数的**kwargs参数。
4)关于函数的返回值。
一个函数的返回值是任意的可以是一个列表、一个字典、一个布尔值、数字、或者没有返回值。没有返回值的情况,缺省值是None。
返回值布尔值:如下简单登陆验证。
1 dic_a={ 2 'name':'evil', 3 'password':'22', 4 } 5 def login(username,password): 6 if username==dic_a['name'] and password==dic_a['password']: 7 return True 8 else: 9 return False 10 if __name__=='__main__': 11 user=input('Entre your username:') 12 paswd=input('password:') 13 res=login(user,paswd) 14 if res: 15 print('Welcome to python') 16 else: 17 print('sorry login fail bye!') 18 19 20 Entre your username:evil 21 password:22 22 Welcome to python
返回值列表:
1 def chek(): 2 user=input('entre your username:') 3 age=input('entre your age:') 4 addr=input('entre your adrr:') 5 return [user,age,addr] 6 if __name__=='__main__': 7 res=chek() 8 print('name:{0} age:{1},addr:{2}'.format(*res)) 9 10 entre your username:tom 11 entre your age:22 12 entre your adrr:LianoNing 13 name:tom age:22,addr:LianoNing
返回值字典:
1 def chek(): 2 user=input('entre your username:') 3 age=input('entre your age:') 4 addr=input('entre your adrr:') 5 return { 6 'name':user, 7 'age':age, 8 'addr':addr 9 } 10 if __name__=='__main__': 11 res=chek() 12 print('name:{name} age:{age},addr:{addr}'.format(**res)) 13 14 entre your username:evil 15 entre your age:22 16 entre your adrr:;LiaoNing 17 name:evil age:22,addr:;LiaoNing
没有返回值:
1 def mn(x,y): 2 a=x+y 3 4 res=mn(1,2) 5 print(res) 6 None
5)相同函数名字执行顺序:
1 def mn(x,y): 2 a=x+y 3 return a 4 def mn(x,y): 5 a=x*y 6 return a 7 res=mn(1,2) 8 print(res) 9 2
相同的名字的函数,执行 临近函数调用最近的函数定义,如上。
6)函数传入给给形参的引用,形参引用实参,而不是内存中重新开辟一个值,赋给形参。
1 def mn(x): 2 x.append(999) 3 list_1=[1,2,3,4] 4 mn(list_1) 5 print(list_1) 6 7 [1, 2, 3, 4, 999]
当x进行操作的时候,添加元素999的时候,会更新list_1.
7)函数的变量:
全局变量:所有作用域都可读。
对全局变量进行重新赋值,需要global
全局变量要大写。比如:NAME .....
私有变量:在函数里的变量是私有的,作用域只在函数体内。
全局变量作用域全局,如上所示。
私有变量:
1 def sum(x,y): 2 a=2 3 b=a+x+y 4 print(b) 5 return b 6 def a(x,y): 7 print(b) 8 sum(1,2) 9 a(1,2) 10 11 NameError: global name 'b' is not defined 12 5
如果私有变量超出函数体的时候,别的函数调用这个变量会出现错误。如上所示。
可以把私有变量变为全局变量,如下所示:
1 def sum(x,y): 2 a=2 3 global b 4 b=a+x+y 5 print(b) 6 return b 7 def a(x,y): 8 print(b) 9 sum(1,2) 10 a(1,2) 11 5 12 5
注意:global 变量名,变量名赋值。这种写法,不要:先变量名,然后global 变量。这样会抛出一个warning 异常。
1 def sum(x,y): 2 a=2 3 b=a+x+y 4 global b 5 print(b) 6 return b 7 def a(x,y): 8 print(b) 9 sum(1,2) 10 a(1,2) 11 12 SyntaxWarning: name 'b' is assigned to before global declaration global b 13 5 14 5
8)函数的注释:
注释:包括函数的功能。参数的说明。以及返回值的说明。好的description帮助别人能快速了解你的代码。
1 USER_INFO={ 2 'name':'evil', 3 'age':'22', 4 } 5 def login(username,password): 6 ''' 7 用户登录 8 :param username:用户名字 9 :param password:用户密码 10 :return:True表示登录成功,False表示登录失败。 11 ''' 12 if username==USER_INFO['name'] and password==USER_INFO['age']: 13 return True 14 else: 15 return False 16 17 if __name__=='__main__': 18 user=input('Entre your login:') 19 paswd=input('Entre your password:') 20 res=login(user,paswd) 21 if res: 22 print('Welcome to Python!!') 23 else: 24 print('sorry login fail!!') 25 Entre your login:evil 26 Entre your password:22 27 Welcome to Python!!
9)三元运算(是针对if else来说)
我们常用的:
1 if 1==1: 2 a=2 3 print(a) 4 else: 5 a=3 6 print(a) 7 2
用三元运算可以这么写:
1 a=2 if 1==1 else 3 2 print(a) 3 2
lamdba表达式:
1 sum=lambda x,y:x+y 2 print(sum(1,2)) 3 3
之前的写法:
1 def sum(x,y): 2 return x+y 3 print(sum(1,2)) 4 5 3
lamdba 是适用于简单的运算和判断,不适用于复杂的判断逻辑。
10)常用函数:
1:all()当所有元素为真才为真。
2:any()至少其中一个元素为真才为真。
1 m=all([1,2,3,4,]) 2 print(m) 3 n=any([None,False]) 4 print(n) 5 6 True 7 False
1 m=all([1,2,3,0,]) 2 print(m) 3 n=any([None,True]) 4 print(n) 5 False 6 True
3:abs() 求绝对值:
1 print(abs(-1)) 2 1
3:bool() 求布尔值。
1 print(bool(1)) 2 True
4:bytes()字符串转换字节。需要指定转换编码比如:utf-8 ,gbk.
1 a='evil' 2 print(bytes(a,encoding='utf-8')) 3 b='汉武帝' 4 print(bytes(b,encoding='utf-8')) 5 b'evil' 6 b'\xe6\xb1\x89\xe6\xad\xa6\xe5\xb8\x9d'
那字节怎么转换成字符串呢?同样用str()函数。但是必须指定相应的编码才可以哦。不正确的编码会报错哦。
1 print(str(b'\xe6\xb1\x89\xe6\xad\xa6\xe5\xb8\x9d',encoding='utf8')) 2 3 汉武帝
11)文件操作:
操作文件时候需要2个步骤:1)打开文件。2)操作文件。
1:打开文件模式有:
1 f=open('haproxy','r',encoding='utf-8')##以只读模式,以utf-8编码打开文件 2 f1=open('haproxy','w',encoding='utf-8')##以写模式,以utf-8编码打开文件,如果文件存在则直接清空,如果没有则创建。 3 f2=open('haproxy','x',encoding='utf-8')##在python3中新加的,文件存在报错,不存在则创建并写入内容。 4 f3=open('haproxy','a',encoding='utf-8')###文件追加内容。
r+,w+,a+表示既可读也可以写。
'b'模式以二进制形式打开文件。rb,wb,ab.
如果平时open打开文件是乱码,一般是编码有问题。现在一般使用编码utf-8编码。
注意:在使用open()函数打开文件的时候,在文件操作完毕的时候需要把文件句柄关闭即:
1 f=open('xxx','mod',encoding='xx') 2 xxxxx 3 f.close()
由于这么操作的时候容易忘记关闭文件句柄。用with as 函数来管理上下文件。文件操作完毕自动关闭文件。
1 with open('haproxy.txt','r',encoding='utf-8') as file_obj: 2 pass
在python2.7以后with函数可以同时操作多个文件。最常用的操作就是:一个文件在读,一个文件在写。
1 with open(1.txt','r',encoding='utf-8') as file_obj,open('1.back','w',encoding='utf-8')as file_obj1: 2 for i in file_obj.readlines(): 3 i.replace('evil','tom') 4 file_obj1.write(i)
2:操作文件:
文件在硬盘以2进制存储,默认情况当python在以(r+,w+,a+等模式)读的时候,在不指定编码的时候,以pytho解释器默认编码,编码成字符串,供程序员进行读写。
如果以rb,wb,ab方式是不用python默认编码,直接以字节方式进行访问,存储的方式2进制,所以要把字符串写入文件,需要把字符串转化成字节才能写入。
1)常用的操作文件的函数。
file.fulsh(),强制把内存的内容刷进硬盘。
实验:
用input()交互方式,在等待用输入的时候,看文件是否内容。
1 with open('test.txt','a') as f1: 2 f1.write('this is test!') 3 dengdai=input('entre your NUM:')
运行该程序,查看文件。文件缓存区的内容没有写入磁盘内,加上file.fulsh(),我们在看下。
1 with open('test.txt','a') as f1: 2 f1.write('this is test!') 3 f1.flush() 4 dengdai=input('entre your NUM:')
发现文件句柄没释放,已经把文件内容写入文件里。
2) file.read()在指定字节大小,可以读指定字节,在没指定,读取文件整个内容。
1 with open('test.txt','r') as f1: 2 for i in f1.read(5): 3 print(i) 4 5 1 6 1 7 1 8 1 9 t
文件内容:
1111this is test!
3)file.readline()仅读取文件一个行。
1 with open('test.txt','r') as f1: 2 for i in f1.readline(): 3 print(i)
4)file.readlines()读取文件,一行为单位,并根据换行来保存值列表,这个函数很常用。
1 with open('test.txt','r') as f1: 2 for i in f1.readlines(): 3 print(i) 4 5 1111this is test!
5)file.seek()指定文件指定到指定位置(字节)。
1 with open('test.txt','r') as f1: 2 f1.seek(4) 3 for i in f1.readlines(): 4 print(i) 5 6 this is test!
文件内容:1111this is test!
将文件指针移到第四个字节。然后操作读。
6)file.tell()获取文件当前指针。
1 with open('test.txt','r') as f1: 2 f1.seek(4) 3 for i in f1.readlines(): 4 print(i) 5 print(f1.tell()) 6 7 this is test! 8 17
因为文件读完,文件指针在文件的末尾。
7)file.truncate (),根据文件指针位置,在文件指针位置以后被清空。
1 with open('test.txt','r+') as f1: 2 f1.seek(4) 3 f1.truncate() 4 1111
上述文件内容,指定文件指针位置,文件指针位置以后都清除。
8)file.write()写数据,有b按字节写入,没指定按字符串写入。
1 with open('test.txt','r+') as f1: 2 f1.seek(4) 3 f1.write('goodbye!') 4 1111goodbye!
9)需要注意,在读文件的时候,最好用如下方式进行读,这种方式是生成迭代器,效率较高。相比read(),readline(),readlines()
1 with open('test.txt','r',encoding='utf-8') as f1: 2 for i in f1: 3 print(i)