第三章:Python文件其他操作+函数入门
上一章主要讲了文件最基本的操作,这一章将要学习几个文件的函数:
文件
关于open 模式:
w 以写方式打开, a 以追加模式打开 (从 EOF 开始, 必要时创建新文件) r+ 以读写模式打开 w+ 以读写模式打开 (参见 w ) a+ 以读写模式打开 (参见 a ) rb 以二进制读模式打开 wb 以二进制写模式打开 (参见 w ) ab 以二进制追加模式打开 (参见 a ) rb+ 以二进制读写模式打开 (参见 r+ ) wb+ 以二进制读写模式打开 (参见 w+ ) ab+ 以二进制读写模式打开 (参见 a+ )
基本读文件:
# f=open('a.txt','r',encoding='utf-8')
# print(f.read(3)) #读前3个字符
#
# f=open('a.txt','rb')
# print(f.read(6).decode('utf-8'))#如果以utf-8的编码对str进行解码得到的结果,将无法还原原来的字符串内容
# print(f.read(3).decode('utf-8'))
# print(f.read(3)) #以rb模式打开,读取的是类似于2进制的内容
# f.closed
Python文件操作常用函数:
1、seek
seek():移动文件读取指针到指定位置
seek()的三种模式:
(1)f.seek(p,0) 移动当文件第p个字节处,绝对位置
(2)f.seek(p,1) 移动到相对于当前位置之后的p个字节
(3)f.seek(p,2) 移动到相对文章尾之后的p个字节
2、tell
tell():返回文件读取指针的位置
# f=open('a.txt','rb') # print(f.read(3)) #以二进制文件读取 # print(f.tell()) #文件的 # f.seek(3,0) #移动文件读取指针到3个字节位置 # print(f.tell()) #返回文件读取指针的位置 # print(f.read(3).decode('utf-8')) # b'123' # 3 # 3 # 456 # f=open('a.txt','rb') # print(f.read(3)) # print(f.tell()) # f.seek(3,1) 移动到相对于当前位置之后的3个字节 # print(f.tell()) # print(f.read().decode('utf-8')) # b'123' # 3 # 6 # # 654321 # # f=open('a.txt','rb') # f.seek(0,2) # print(f.tell()) # print(f.read()) # 14 # b'' #什么都没有读取到数据,指针说明已经在最后
练习:
下面来使用PY3写一个类似于命令tail -f /tailf 的功能,可以实时的观察文件的数据变化:
使用方法python3 tail.py -f access.log
#python3 tail.py -f access.log # [0] [1] [2] import time import sys with open(r'%s' %sys.argv[2],'rb') as f: f.seek(0,2) while True: line=f.readline() if line: print(line) else: time.sleep(0.2) #acess.log
使用下面代码测试:
# with open('acess.log','a') as f: # f.write('1111\n')
函数
函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内建函数,比如print()。但你也可以自己创建函数,这被叫做用户自定义函数。
定义一个函数:
你可以定义一个由自己想要功能的函数,以下是简单的规则:
1、函数代码块以 def 关键词开头,后接函数标识符名称和圆括号()。
2、任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数。
3、函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
4、函数内容以冒号起始,并且缩进。
5、return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。
函数的使用:
1 先定义
2 再调用
#函数的定义与变量的定义类似,没有事先定义变量,而直接引用变量,会报错
#没有事先定义函数,而直接调用,就相当于在引用一个不存在的变量名
# #定义阶段 # def foo(): # print('from foo') # bar() # # print(foo) # def bar(): # print('from bar') # # # #调用阶段 # foo()
语法:
def functionname( parameters ): "函数_文档字符串" function_suite return [expression]
默认情况下,参数值和参数名称是按函数声明中定义的的顺序匹配起来的。
函数调用
定义一个函数只给了函数一个名称,指定了函数里包含的参数,和代码块结构。
这个函数的基本结构完成以后,你可以通过另一个函数调用执行,也可以直接从Python提示符执行。
如下实例调用了printme()函数:
#!/usr/bin/python # -*- coding: UTF-8 -*- # 定义函数 def printme( str ): "打印任何传入的字符串" print str; return; # 调用函数 printme("我要调用用户自定义函数!"); printme("再次调用同一函数");
函数参数(传参)
#形参:在定义函数时,括号内的参数成为形参
#特点:形参就是变量名
# def foo(x,y): #x=1,y=2 # print(x) # print(y)
#实参:在调用函数时,括号内的参数成为实参
#特点:实参就是变量值
# foo(1,2)
#在调用阶段实参(变量值)才会绑定形参(变量名)
#调用结束后,解除绑定
参数的分类
#位置参数:按照从左到右的顺序依次定义的参数
1、位置形参:必须被传值,并且多一个不行,少一个也不行
2、位置实参:与形参按照位置一一对应
# def foo(x,y): # print(x) # print(y) # # foo('egon',1,2)
#关键字实参:指的是按照name=value的形式,指名道姓地给name传值
# def foo(name,age): # print(name) # print(age)
关键字实参需要注意的问题是:
1、问题一:语法规定位置实参必须在关键字实参的前面
foo('egon',sex='male',age=18)
2、问题二:一定不要对同一个形参传多次值
foo('egon',sex='male',age=18,name='egon1')
默认形参:在定义阶段,就已经为形参赋值,意味在调用阶段可以不用传值
# def foo(x,y=1111111): # print(x) # print(y)
默认参数:需要注意的问题
1、问题一:默认参数必须放在位置参数之后
# def foo(y=1,x): ##语法错误,× # print(x,y)
2、问题二:默认参数只在定义阶段赋值一次,而且仅一次
# x=100 # def foo(a,b=x): # print(a,b) # # x=111111111111111111111111111111 # foo('egon') ###print后b输出的值不变:一直是100.
3、问题三:默认参数的值应该定义成不可变类型
# def foo(a,b=100): # print(a,b)
函数的返回值
大前提:函数的返回值没有类型限制:int、list、set都可以返回。
1、没有return:返回None,等同于return None
2、return 一个值:返回该值
3、return val1,val2,val3:返回(val1,val2,val3) 返回多个值。
def func(x,y): if x > y: return x else: return y print(func(1,2))
#函数是第一类的对象:指的是函数可以被当做数据传递
def foo(): print('from foo') #1 被赋值 # f=foo #被赋值的时候是函数名,不是函数体 # print(f) # f() #2 可以当做参数传入 # def wrapper(func): # # print(func) # func() # wrapper(foo) #3 可以当做函数的返回 def wrapper(func): return func # res=wrapper(foo) # print(res) #4 可以当做容器类型的元素 # cmd_dic={ # 'func':foo # } # # print(cmd_dic) # # cmd_dic['func']()
可变长参数:
针对实参在定义时长度不固定的情况,应该从形参的角度找到可以接收可变长实参的方案,这就是可变长参数(形参)
而实参有按位置和按关键字两种形式定义,针对这两种形式的可变长,形参也应该有两种解决方案,分别是*args,**kwargs
注意:
1、可变长参数指的是实参的个数(不固定)多了
2、实参无非位置实参和关键字实参两种
3、形参必须要两种机制来分别处理按照位置定义的实参溢出的情况:*
4、跟按照关键字定义的实参溢出的情况:**
==>位置实参:
def func(x,y,*args): # args=(4,5,6,7) print(x) print(y) print(args) func(1,2,3,4,5,6,7) 打印的值: 结论:func多出的参数就会给'*'处理,存储成元祖的形式赋值给args def func(x,y,*args): #把参数去掉就会 print(x) print(y) print(args) func(1,2) 输出一个空元祖。 *args的扩展用法: def func(x,y,*args): # *args=*(3,4,5,6,7) print(x) print(y) print(args) func(1,2,*(3,4,5,6,7)) #等价于func(1,2,3,4,5,6,7) def func(x,y,): print(x) print(y) func(1,*(2,)) #等价于func(1,2) def func(x,y=1,*args): #问题:有默认参数y ,这样使得y没有意义。 print(x) print(y) print(args) func('sheng',101,2,3,4,5,6) func('sheng',101,2,3,4,5,y=2) #报错,同一个参数传2次值
==>关键字实参:
def func(x,y,**kwargs): print(x) print(y) print(kwargs) func(x=1,y=2,c=3,d=4,e=5,f=6) 结论:func多出的参数就会给'**'处理,存储成字典的形式赋值给kwargs def func(x,y): print(x) print(y) func(**{'x':1,'y':3}) #==》func(x=1,y=3) #实参也可以有**的方式传参 注意: def foo(*args,x): print(x) print(args) foo(1,2,3,4,5,) #无法为x传值,都传给了args 应该修改成: def foo(*args,x): print(x) print(args) foo(1,2,3,4,5,x=33) #无法为x传值,都传给了args def foo(x,*args,**kwargs): #args=(1,2,3,4,5),kwargs={'a':22,'b':33} #正常的定义方式 print(x) print(args) print(kwargs) foo(1,2,3,4,5,a=22,b=33) 这两定义方式*args,**kwargs干什么使用: def register(name,age,sex='female'): print(name) print(age) print(sex) def foo(*args,**kwargs): #args=(1,2,3,4,5),kwargs={'a':22,'b':33} register(*args,**kwargs) foo('sheng',age=28)

浙公网安备 33010602011771号