day3-文件读取、函数、字符编码转换、全局变量与局部变量
1.函数
==============第一个函数=================
def fun1(): # this is my first function print('Hello Function!') return 0
---》》第一个函数,def定义函数,无参数,返回值为0,打印‘Hello Function’
==============第一个过程=================
def proce1(): # this is my first procedure print('Hello Procedure')
---》》函数和过程的区别是,过程没有返回值。。。函数也可以没有返回值啊?擦!咋区别?
==============函数的返回值=================
''' 函数返回值: 1.无return,返回none 2.return一个值,返回object(值本身,python所有值都可以看作一个对象) 3.return多个值,返回一个tuple 为什么要有返回值: 我想要整个函数执行的结果,后面的程序需要根据这个执行结果进行不同的操作 ''' # 无返回值 def test_none(): print('this is test_none'.ljust(50,'-')) #返回值为0 def test_num(): print('this is test_num'.ljust(50,'-')) return 0 #返回一个tuple def test_tuple(): print('this is test_tuple'.ljust(50,'-')) return 3,'champions',[1,'中金所','随便'],{'name':'yang','age':'secret'} #此为高阶函数,返回要给函数 def test_high(): print('this is test_high'.ljust(50,'-')) return test_num #返回test_num函数的内存地址 print(test_none()) print(test_num()) print(test_tuple()) print(test_high())
==============局部变量与全局变量=================
school='天庭' #全局变量,全局生效 def change_name(name): print('Before change:',name) school='花果山' #局部变量,函数内生效 print('Local variable:',school) name='齐天大圣' #局部变量,调用函数时,实现改名字功能 print('After change:',name) name='孙悟空' #全局变量 change_name(name) print('Global variable:',school)
=============需要传参的函数=================
def func_arg(x,y): print(x,y) #func_arg(1,2) #func_arg(1) #func_arg() missing 1 required positional argument: 'y' # func_arg(1,2,3) #func_arg() takes 2 positional arguments but 3 were given ''' x=1 #此x为实参,换成a=1,会不会直观点,哈哈 y=2 #次y为实参,换成b=2,会不会直观点,哈哈 func_arg(x=x,y=y) ''' #func_arg(1,2) #位置参数调用,与形参位置一一对应 #func_arg(y=1,x=2) # 关键字参数调用,与形参位置无关 #func_arg(x=1,2) #不可以,positional argument follows keyword argument #func_arg(1,y=2) #可以,关键字参数必须在最后 #func_arg(1,x=2) #不可以,x有多个值,test1() got multiple values for argument 'x' ''' def test1(x,y,z):#形参 print(x) print(y) print(z) #test1(1,y=2,3) #不可以,positional argument follows keyword argument test1(1,2,z=3) #可以 test1(3,z=6,y=9) #可以 '''
===============需要传参的函数,参数带默认值================
''' default argument特点: 1.调用函数的时候,默认参数可不传 应用场合: 1.默认安装 2.数据库链接字符串 ''' def test1(x,y=2): print(x) print(y) #test1(1) #test1(1,y=3) #test1(1,3)
===============一个函数,若参数数目不固定,则使用参数组================
''' 针对形参数量不固定,下面隆重介绍:参数组 ''' # def test1(*args): #接收N个位置参数,转换成元组的方式,不能接受关键字参数 # print(args) #封装为元组 # #print(*args) #不封装 # # test1(1,2,3,4,5) #多个实参放到一个元组里 # test1([7,8,9,0]) #列表作为元组的一个元素 # test1(*[7,8,9,0]) #同多个实参放到一个元组里 # test1({'name':'weixiaobao','age':16},1,2) #字典作为元组的一个元素 # def test2(x,*args): # print(x) # print(args) #参数封装成元组输出 # # test2(1,2,3,4,5,6) #字典 #把N个关键字参数转换成字典的方式 # def test3(**kwargs): #接受关键字参数,转换成字典方式 # print(kwargs) # print(kwargs['name']) # print(kwargs['age']) # print(kwargs['sex']) # test3(name='bajie',age=500,sex='f') # test3(**{'name':'bajie','age':500,'sex':'f'}) #综合使用 # def test4(organization,**kwargs): # print(organization) # print(kwargs) #test4('tianting',name='neza',age=300,sex='x') #完美传参 #test4('diyu') #最懒传参,字典为空 #test4('renjian',6) #错误传参,test4() takes 1 positional argument but 2 were given #终极综合使用 # def test5(organization,position,*args,**kwargs): #参数组一定要往后放 # print(organization) # print(position) # print(args) # print(kwargs) #test5('tianting','33tian',1,2,3,name='change',age=18) #完美调用 #test5('renjian','saodi') #最懒调用,元组和字典都为空 #一个函数中引用其他函数 # def test6(organization,position=33,*args,**kwargs): # print(organization) # print(position) # print(args) # print(kwargs) # logger('test6') # def logger(source): # print('from %s',source) # test6('diyu') #接下来给你一个错误示例 # def test6(organization,position=33,*args,**kwargs): # print(organization) # print(position) # print(args) # print(kwargs) # logger('test6') # test6('diyu') #name 'logger' is not defined,从上到下执行,此时logger还未定义 # def logger(source): # print('from %s',source) #最最最使用传参方式,随你咋搞都不报错 def test7(*args,**kwargs): print(args) print(kwargs) test7() test7(1) test7(name='wukong') test7(1,name='wukong')
===============高阶函数,初识================
#higher order function # ads 内置函数 def add(a,b,f): print(a) print(b) return f(a)+f(b) res=add(2,3,abs) print(res)
===============递归函数================
''' recursion,递归函数 1.必须要有个明确的结束条件 2.每次进入更深一层时,问题规模相对上次都应有所减少 3.递归效率不高,递归层次过多会导致栈溢出 ''' def recur_calc(n): print(n) if int(n/2)>0: return recur_calc(n/2) print('--->>',n) recur_calc(10)
===============函数尾声================
''' 函数优点: 1.代码重用 2.程序容易扩展 3.代码一致性 ''' import time def addlog(): time_format='%Y-%m-%d %X' time_current=time.strftime(time_format) with open('log','a+',encoding='utf-8') as f: f.write('%s this is used add log...\n' %time_current) def test1(): print('this is test1') addlog() def test2(): print('this is test2') addlog() test1() test2()
2.集合(set)
list_1=[1,3,5,7,9] list_1=set(list_1) list_2=[2,4,6,8,9,0] list_2=set(list_2) print(list_1,list_2) #交集 print('交集intersection方法:',list_1.intersection(list_2)) print('交集\'&\'运算符:',list_1 & list_2) #并集 print('并集union方法:',list_1.union(list_2)) print('并集\'|\'运算符:',list_1 | list_2) #差集 print('差集difference方法1-2:',list_1.difference(list_2)) #in list_1 but not in list_2 print('差集difference方法2-1:',list_2.difference(list_1)) #in list_2 but not in list_1 print('差集\'-\'运算符1-2:',list_1-list_2) #子集 list_3=set([1,3,5]) print('list_3是list_1的子集:',list_3.issubset(list_1)) #list_3是list_1子集 print('list_1是list_3的父集:',list_1.issuperset(list_3)) #对称差集 print('对称差集symmetric方法:',list_1.symmetric_difference(list_2)) #去掉交集元素 print('对称差集\'^\'运算符:',list_1 ^ list_2) print('----------------------') list_4=set([5,6,7,8]) print(list_3.isdisjoint(list_4)) #return True if tow sets have a null intersection. # 添加一项 list_1.add('222') print(list_1) # 添加多项 list_1.update([555,666,777]) print(list_1) # 删除一项 list_1.remove('222') print(list_1) # set的长度 print(len(list_1)) # 判断元素是否在集合中 if 666 in list_1: print('666 is a element of set!') if 222 not in list_1: print('222 is not a element of set!') # 浅copy list_1_copy=list_1.copy() print('list_1的浅copy:',list_1_copy)
3.文件操作
==============先来个Example,登录=================
''' 通过读取文件的方式登陆,文件格式如下: sunwukong,swk123 zhubajie,zbj123 jiabaoyu,jby123 ''' usernames=[] passwords=[] fobj=open('login.txt','r') username=input('username:') password=input('password:') while True: lines=fobj.readline().strip() if not lines: break t_names,t_pwds=[str(s) for s in lines.split(',')] usernames.append(t_names) passwords.append(t_pwds) if username in usernames: pwd_index=usernames.index(username) if password==passwords[pwd_index]: print('welcome login...') else: print('Invalid password!') else: print('User non-exsitent!')
==============步步推进,先来个简单的文件opration吧=================
1. Somehow, it seems the love I knew was always the most destructive kind 2. 不知为何,我经历的爱情总是最具毁灭性的的那种 3. Yesterday when I was young 4. 昨日当Alex年少轻狂 5. The taste of life was sweet 6. 生命的滋味是甜的 7. As rain upon my tongue 8. 就如舌尖上的雨露 9. I teased at life as if it were a foolish game 10. 我戏弄生命 视其为愚蠢的游戏
---》》以上为文件的内容
f=open('song','r',encoding='utf-8') #打开文件,以只读的方式,采用‘utf-8’编码(操作系统默认gbk) first_line=f.readline() #读取第一行 print(first_line) second_line=f.readline() #读取第二行 print(second_line) third_line=f.readline() #读取第三行 print(third_line) print('我是分割线'.center(50,'-')) data=f.read() #读取剩下的全部,文件大时不要用 print(data) f.close() #关闭文件
---》》试试f.read()后,再使用f.read()或者f.readlines(),打印出结果,看看会发生什么。
==============向前走,先来看9种操作模式的前3式(r,w,a)=================
# file opr # r:只读 # w: 只写 # a: 追加 # with open('song','r',encoding='utf-8') as f: # line=f.readline() #读取一行 # data=f.read() #读取剩下的全部 # lines=f.readlines() #啥也都不到,只剩一个空列表 # print(line) # print(data) # print(lines) # with open('song','w',encoding='utf-8') as f: # str='自在飞花轻似梦,无边丝雨细如愁' # f.write(str) #删除文件原有内容,写入str内容,慎重使用!!! # with open('song','a',encoding='utf-8') as f: # str='\n自在飞花轻似梦,无边丝雨细如愁' # f.write(str) #在原有内容末尾添加
==============继续走,再来看9种操作模式的中间3式(r+,w+,a+)=================
# file opr # r+ 可读、可写,文件若不存在,则报IOError # w+ 写读,首先创建一个新文件,再在新文件中写 # a+ 追加读写 # with open('song','r+',encoding='utf-8') as f: # ############ read ############ # # line=f.readline() # # print(line) # # data=f.read() # # print(data) # # lines=f.readlines() # # print(lines) # ############ write ############ # str = '噫嘘唏!蜀道难,难于上青天!' # f.write(str) #写入时,使用str从头开始替换原文件内容 # with open('song','w+',encoding='utf-8') as f: #写读,如果文件不存在就创建一个 # str='自在飞花轻似梦,无边丝雨细如愁' # f.write(str) #清空原有内容,然后写入str # data=f.read() #明明有内容,为啥都出来为空?有毛用!!! # print(data) # with open('song','a+',encoding='utf-8') as f: #a+w 可写,可追加,文件不存在就创建 # data=f.read() # print(data) #读不出来,不可读? # str = '\n自在飞花轻似梦,无边丝雨细如愁' # f.write(str) #追加可以
==============最后走,再来看9种操作模式的最后3式(rb,wb,ab)=================
# file opr # rb:读二进制文件 # wb:写二进制文件 # ab: 追加二进制文件 # with open('song','rb') as f: #二进制读 # line=f.readline() # print(line) #打印出的结果以b打头,代表bytes类型 # with open('song','wb') as f: #二进制写 # binary='Hello Binary'.encode() #字符串转换为二进制 # f.write(binary) with open('song','ab') as f: #二进制追加 # line=f.readline() #好吧,次模式不支持和read,报“io.UnsupportedOperation: read” # print(line) binary='自在飞花轻似梦,无边丝雨细如愁'.encode() f.write(binary) #追加到源文件内容末尾
==============以为只有9中,你错了骚年,再来看(rb+,wb+,ab+)=================
pass
==============模式汇总=================
''' 模式 描述 r 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。 rb 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。 r+ 打开一个文件用于读写。文件指针将会放在文件的开头。 rb+ 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。 w 打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 wb 以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 w+ 打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 wb+ 以二进制格式打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 a 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 ab 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 a+ 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。 ab+ 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。 '''
==============文件的循环读取=================
# 循环读取 # 第一种简单循环 # with open('song','r',encoding='utf-8') as f: # for line in range(5): # print(f.readline()) # 转换为列表,使用readlines方法 # with open('song','r',encoding='utf-8') as f: # for line in f.readlines(): #readlines 列表,每行为一个列表元素,相当于循环读取一个列表 # print(line.strip()) # 可以表示每行的序号,以0开始 # with open('song','r',encoding='utf-8') as f: # data=f.readlines() # for index,line in enumerate(data): # # print(index,line.strip()) # if index==5: # print('我是分割线'.center(50,'-')) # print(line.strip()) # hign bg 效率最高,f变为迭代器 # with open('song','r',encoding='utf-8') as f: # count = 0 # for line in f: # if count == 5: # print('我是分割线'.center(50, '-')) # count += 1 # #break # continue # print(line.strip()) # count += 1
==============文件的修改=================
#使用此方式无法修改 # with open('song','r+',encoding='utf-8') as f: # if f.readable() and f.writable(): # print(f.readline().strip()) # print(f.readline().strip()) # f.write('-----噫嘘唏,蜀道难,难于上青天!------') #想在第二行后插入,结果追加到了末尾 # print(f.readline().strip()) # print(f.tell()) #统计打印了多少个字符 # f.seek(10) #指针回到第十个字符后 # print(f.tell()) # print(f.readline().strip()) #从第10个字符后,开始打印
---》》以上方式无法修改
==============只好用以下方式修改=================
''' # 修改一个文件 1.像vim一样,先将文件加载到内存里,修改完成后,写回到硬盘 2.打开一个文件A-read,再打开一个文件B-write,将A-read文件的内容逐行写入的B-write, 当遇到A-read中需要修改的内容时,直接将修改的内容写入到B-write,A-read中内容不变,然后 接着将A-read中后续内容,写入到B-write. ''' with open('song_read','r',encoding='utf-8') as f_read: with open('song_write','w',encoding='utf-8') as f_write: str='昨日当Alex年少轻狂' if f_read.readable(): for line in f_read: if str in line: line=line.replace(str,'昨日当wo年轻狂') f_write.write(line) else: print('song_read is not readable')
---》》with打开两个文件,一个用于读取,一个用于写入;
---》》一行行,边读边写,检索到需要修改的行后(if str in line),修改内容后写入
---》》line.replace()进行修改
==============文件的常用方法=================
''' 各种方法--->> # tell方法:read后,返回读取到的字符数 # seek方法:seek(0),返回到最前,光标定位0个字符后 print(f.tell()) print(f.readline().strip()) print(f.readline().strip()) print(f.readline().strip()) #print(f.read(50)) #读取50个字符,无法确定行数 print(f.tell()) #返回读取到的字符数 print(f.seek(0)) #返回第一行,只能返回到第一行,试试seek(10),前10个字符不会打印 print(f.readline()) #打印返回后的行 # encoding,打印文件的编码格式 print(f.encoding) # 文件编号,操作系统编的。。。 print(f.fileno()) # 是否为终端设备,跟打印机等交互的时用 print(f.isatty()) # 不是所有的文件都可以seek的,像终端文件就无法seek print(f.seekable()) # 判断文件是否可读 print(f.readable()) # 判断文件是否可写 print(f.writable())
==============flush方法,写入硬盘=================
# flush刷新,写入硬盘 >>> f=open('test.txt','w') >>> f.write('hello1\n') 7 >>> f.flush() >>> f.write('hello2\n') 7 >>> f.flush() >>>