一,文件操作基本流程。
打开文件方法一
文件句柄 = open(‘文件路径’,‘模式’, '字符编码')
1 #1. 打开文件open,得到文件句柄并赋值给一个变量 2 f=open('a.txt','r',encoding='utf-8') #默认打开模式就为r 3 4 #2. 通过句柄对文件进行操作 5 data=f.read() 6 7 #3. 注意关闭文件,防止占用资源 8 f.close()
打开文件方法二
# 单个文件操作,as后为变量名称 with open("一首诗",mode="r",encoding="UTF-8") as f: pass # 可多文件进行操作 with open("一首诗", mode="r", encoding="UTF-8") as f,open("一首词", mode="w", encoding="UTF-8"): pass
encoding,用字符编码,可防止打开的文件乱码!
二、文件的打开模式
#1. 打开文件的模式有(默认为文本模式): r ,只读模式【默认模式,文件必须存在,不存在则抛出异常】 w,只写模式【不可读;不存在则创建;存在则清空内容】 a, 只追加写模式【不可读;不存在则创建;存在则只追加内容】 #2. 对于非文本文件,我们只能使用b模式,"b"表示以字节的方式操作(而所有文件也都是以字节的形式存储的,使用这种模式无需考虑文本文件的字符编码、图片文件的jgp格式、视频文件的avi格式) rb wb ab 注:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型,不能指定编码 #3,‘+’模式(就是增加了一个功能) r+, 读写【可读,可写】 w+,写读【可写,可读】 a+, 写读【可写,可读】 #4,以bytes类型操作的读写,写读,写读模式 r+b, 读写【可读,可写】 w+b,写读【可写,可读】 a+b, 写读【可写,可读】
三,文件操作方法。
常用的操作方法
read(3):
1. 文件打开方式为文本模式时,代表读取3个字符
2. 文件打开方式为b模式时,代表读取3个字节
其余的文件内光标移动都是以字节为单位的如:seek,tell,truncate
注意:
1. seek有三种移动方式0,1,2,其中1和2必须在b模式下进行,但无论哪种模式,都是以bytes为单位移动的
2. truncate是截断文件,所以文件的打开方式必须可写,但是不能用w或w+等方式打开,因为那样直接清空文件了,所以truncate要在r+或a或a+等模式下测试效果
1 f = open("一首诗",mode="r",encoding="UTF-8") 2 b = f.read() 3 print(b) # 人生若只如初见,何事悲风秋画扇 4 f.seek(3) # 光标移动都是以字节为单位 5 b = f.read() 6 print(b) # 生若只如初见,何事悲风秋画扇 7 print(f.tell()) # 43 光标位置 8 print(f.readline()) #一行一样读 9 print(f.readlines()) # 一次性读取整个文件,自动将文件内容分析成一个行的列表 10 f.close()
四、文件的修改
1 f = open("一首诗",mode="w",encoding="UTF-8") 2 f.write("****") # 只写模式【不可读;不存在则创建;存在则清空内容】
1 with open("小美女",encoding='UTF-8') as a ,open('小美女_the',"w",encoding="UTF-8") as a1 : 2 for i in a: 3 if "小红" in i: 4 i = i.replace("小红","大白") # 小红修改为大白 5 a1.write(i) # 写入 a1 6 import os 7 os.remove("小美女") # 删除文件 8 os.rename('小美女_the',"小美女") # 从新命名文件
五、函数
5.1函数的表现形式
def 函数名(参数1,参数2,xx) '''注释
参数表示的意义
return:xxx
''' 函数体 return 返回的值 #函数名要反映其意义,函数即“变量”,“变量”必须先定义后引用。未定义而直接引用函数,就相当于在引用一个不存在的变量名!
5.2函数的返回值(return)
没有返回值
1 #没有返回值,不写return,或者写return None 2 def mylen(): 3 """计算s1的长度""" 4 s1 = "hello world" 5 length = 0 6 for i in s1: 7 length = length+1 8 print(length) 9 # 函数调用 10 str_len = mylen() 11 # 因为没有返回值,此时的str_len为None 12 print('str_len : %s' % str_len)
返回一个值
#返回一个值只需在return后面写上要返回的内容即可 def mylen(): """计算s1的长度""" s1 = "hello world" length = 0 for i in s1: length = length+1 return length #函数调用 str_len = mylen() print('str_len : %s'%str_len)
返回多个值
1 def ret_demo2(): 2 ''' 返回多个值 ''' 3 return 1,['a','b'],3,4 4 #返回多个值,用一个变量接收 5 ret2 = ret_demo2() 6 print(ret2) 7 '''返回多个值,用多个变量接收 8 因为python中把用逗号分割的多个值就认为是一个元祖 9 所以可以用多个值接收返回值返回几个值,就用几个变量接收''' 10 a,b,c,d = ret_demo2() 11 print(a,b,c,d)
5.3函数的参数
实参形参和传参
1 #函数定义,s1为形参 2 def mylen(s1): 3 """计算s1的长度""" 4 length = 0 5 for i in s1: 6 length = length + 1 7 return length 8 # 函数调用,s2为实参 9 s2 = "hello python" 10 str_len = mylen(s2) 11 print('str_len : %s' % str_len) 12 #整个过程称为传参
传递多个参数
def mymax(x,y): #参数可以传递多个,多个参数之间用逗号分割 the_max = x if x > y else y return the_max ma = mymax(10,20) print(ma)
位置参数
正确用法
一:位置参数必须在关键字参数的前面
二:对于一个形参只能赋值一次
1 def mymax(x, y): 2 # 此时x=10,y=20 3 the_max = x if x > y else y 4 return the_max 5 ma = mymax(10, 20) # 按照位置传参, 6 print(ma) 7 ma1 = mymax(x=10, y=20) # 按照关键字传值 8 print(ma1) 9 ma2 = mymax(10, y=20) # 位置、关键字形式混着用 10 print(ma2) 11 ma3 = mymax() 12 print(ma3) # 报错,位置参数必须穿值
默认参数,将变化比较小的值设置成默认参数
1 def stu_info(name, sex="男"): 2 """打印名字,因为大多数都是男生 3 所以可以将sex设置为默认参数 4 """ 5 print(name, sex) 6 stu_info('小明') # 结果为:小明 男 sex为默认为男 7 stu_info('小红', '女') # 结果为:小红 女 8 stu_info('小红', sex='女') # 结果为:小红 女
参数陷阱:默认参数是一个可变数据类型
1 def defult_param(a,l = []): 2 l.append(a) 3 print(l) 4 5 defult_param('小明') 6 defult_param('小红')
动态参数
按位置传值多余的参数都由args统一接收,保存成一个元组的形式
1 def mysum(*args): 2 the_sum = 0 3 for i in args: 4 the_sum+=i 5 return the_sum 6 7 the_sum = mysum(1,2,3,4) 8 print(the_sum) 9 #args求和函数应用
按位置传值多余的参数都由args统一接收,保存成一个字典的形式
1 def stu_info(**kwargs): 2 print(kwargs) 3 print(kwargs['name'],kwargs['sex']) 4 5 stu_info(name = '小明',sex = '男')
参数排放顺序:位置参数-->*args-->默认参数-->**kwargs
六、命名空间和作用域
6.1 命名空间
命名空间分为三种:
全局命名空间------全局命名空间为:顾名思义,除def函数外的变量名称
局部命名空间------局部命名空间为:def函数内部的变量名称
内置命名空间------内置命名空间为:python解释器中内置的函数名称
三种命名空间之间的加载顺序:
加载顺序:内置命名空间(程序运行前加载)->>>>全局命名空间(程序运行中:从上到下加载)->>>>全局命名空间(程序运行中:调用时才加载)
三种命名空间之间的取值顺序:
在局部调用:局部命名空间->>>>全局命名空间->>>>内置命名空间
在全局调用:全局命名空间->>>>内置命名空间
6.2作用域
作用域就是作用范围,按照生效范围可以分为全局作用域和局部作用域。
局作用域:包含内置名称空间、全局名称空间,在整个文件的任意位置都能被引用、全局有效
局部作用域:局部名称空间,只能在局部范围内生效
global关键字
1 a = 10 2 def func(): 3 global a # 引用全局的变量a 4 a = 20 5 6 print(a) # 10 7 func() 8 print(a) # 20
globals() 函数会以字典类型返回当前位置的全部全局变量。
1 a='runoob' 2 print(globals()) 3 4 '''globals 函数返回一个全局变量的字典,包括所有导入的变量。 5 {'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, 'a': 'runoob', '__package__': None}'''
locals() 函数会以字典类型返回当前位置的全部局部变量。
1 def runoob(arg): # 两个局部变量:arg、z 2 z = 1 3 print (locals()) 4 5 runoob(4) # {'z': 1, 'arg': 4}, 返回一个名字/值对的字典
七、函数的嵌套
7.1函数的嵌套调用
def max2(x,y): m = x if x>y else y return m def max4(a,b,c,d): res1 = max2(a,b) res2 = max2(res1,c) res3 = max2(res2,d) return res3 print(max4(1,5,6,8,)) # 8
7.2函数的嵌套定义
1 def f1(): 2 def f2(): 3 def f3(): 4 print("in f3") 5 print("in f2") 6 f3() 7 print("in f1") 8 f2() 9 f1() 10 ''' 11 输出为 12 in f1 13 in f2 14 in f3 15 '''
八、函数的作用域链
nonlocal关键字
1.外部必须有这个变量
2.在内部函数声明nonlocal变量之前不能再出现同名变量
3.内部修改这个变量如果想在外部有这个变量的第一层函数中生效
1 def f1(): 2 a = 1 3 def f2(): 4 nonlocal a 5 a = 2 6 f2() 7 print('a in f1 : ',a) 8 9 f1() # a in f1 : 2
九、函数名称的本质
函数名本质上就是函数的内存地址
1.可以被引用
1 def func(): 2 print('in func') 3 4 f = func 5 print(f)
2.可以被当作容器类型的元素
1 def f1(): 2 print('f1') 3 def f2(): 4 print('f2') 5 def f3(): 6 print('f3') 7 l = [f1,f2,f3] 8 d = {'f1':f1,'f2':f2,'f3':f3} 9 #调用 10 l[0]() 11 d['f2']()
3.可以当作函数的参数和返回值,当普通变量用
第一类对象(first-class object)指
1.可在运行期创建
2.可用作函数参数或返回值
3.可存入变量的实体
十、闭包
1 def func(): 2 name = 'eva' 3 def inner(): 4 print(name) 5 return inner 6 7 f = func() 8 f()
闭包函数:
内部函数包含对外部作用域而非全剧作用域名字的引用,该内部函数称为闭包函数
#函数内部定义的函数称为内部函数
判断闭包函数的方法__closure__
1 #输出的__closure__有cell元素 :是闭包函数 2 def func(): 3 name = 'eva' 4 def inner(): 5 print(name) 6 print(inner.__closure__) 7 return inner 8 9 f = func() 10 f() 11 12 #输出的__closure__为None :不是闭包函数 13 name = 'egon' 14 def func2(): 15 def inner(): 16 print(name) 17 print(inner.__closure__) 18 return inner 19 20 f2 = func2() 21 f2()
闭包嵌套
1 def wrapper(): 2 money = 1000 3 def func(): 4 name = 'eva' 5 def inner(): 6 print(name,money) 7 return inner 8 return func 9 10 f = wrapper() 11 i = f() 12 i()
小结
命名空间:
一共有三种命名空间从大范围到小范围的顺序:内置命名空间、全局命名空间、局部命名空间
作用域(包括函数的作用域链):
小范围的可以用大范围的
但是大范围的不能用小范围的
范围从大到小(图)
在小范围内,如果要用一个变量,是当前这个小范围有的,就用自己的
如果在小范围内没有,就用上一级的,上一级没有就用上上一级的,以此类推。
如果都没有,报错
函数的嵌套:
嵌套调用
嵌套定义:定义在内部的函数无法直接在全局被调用
函数名的本质:
就是一个变量,保存了函数所在的内存地址
闭包:
内部函数包含对外部作用域而非全剧作用域名字的引用,该内部函数称为闭包函数