文件处理
mode | 打开文件方式 |
---|---|
r | 读(默认) |
w | 写 |
x | 创建并写 |
a | 追加 |
r | 读写 |
w | 写读 |
x | 创建并写读 |
a | 追加读 |
#w a r 三种纯净模式
#如果是windows平台一般还要加上一个小r,意思是取消路径中/的转义功能(不用写//了)
#默认t,指的是文本文件,文本里面存放的是字符,因此涉及到字符编码,如果不指定使用什么字符编码打开就按默认操作系统默认编码打卡,windows默认GBK
f=open(r'a.txt','r',encoding='utf-8')
#读
#这一步说明发送了一个请求给操作系统,把某个文件已什么字符编码打开,同时还拿到了一个变量f
#写 w模式
f=open(r'a.txt','w',encoding='utf-8')
#w打开文件,光标在首行,文件不存在直接创建,存在直接将原来清空
#writable判断是否可写
print(f.writable())
#返回True说明文件可写
f.write('1111n')
f.write('2222n')
#writelines以元祖和列表的方式写
代码语言:javascript复制f.writelines(['3333n','444n'])
f.close()
#写 a模式 追加 #a模式打开后光标直接移动到文件末尾 #文件不存在则创建
代码语言:javascript复制f=open(r'a.txt','a',encoding='utf-8')
print(f.writable())
f.write('555n')
#r模式
# f=open(r'a.txt','r',encoding='utf-8')
#read一次全读取,如果文件大内存可能承受不了
# print(f.read())
#readlines包文件内容全读取,但是放到列表里面去
# print(f.readlines())
# ['1111n', '2222n', '3333n', '444n', '555n']
#readline一次只读一行,print自带换行
代码语言:javascript复制# print(f.readline(),end='')
# print(f.readline(),end='')
# 1111
# 2222
# f.close()
#!使用for循环读取每行内容,无序再用readline
代码语言:javascript复制# with open('a.txt','r',encoding='utf-8') as f:
# for line in f:
# print(line)
#b:bytes #rb模式直接把文件在硬盘上的二进制读取出来 #只有在文件存在的情况下才可以用
#使用图片举例
代码语言:javascript复制# with open('01.jpg','rb') as f:
# print(f.read())
#也可以读取文本文件 #注意了,文本文件可以使用decode进行解码,显示出文本内容
代码语言:javascript复制# with open('a.txt','rb') as f:
# print(f.read())
#不解码
# b'1111rn2222rn3333rn444rn555'
#print(f.read().decode())解码
# 1111
# 2222
# 3333
# 444
# 555
#wb
代码语言:javascript复制# with open('b.txt','wb') as f:
# # f.write('你好'.encode('utf-8'))
# res='你好'.encode('utf-8')
# print(res,type(res))
# f.write(res)
# b'xe4xbdxa0xe5xa5xbd' <class 'bytes'>
#ab 追加
代码语言:javascript复制# with open('b.txt','ab') as f:
# res='你好n'.encode('utf-8')
# print(res,type(res))
# f.write(res)
#小练习,模拟linux系统cp命令
代码语言:javascript复制# import sys
# _,scr_file,dst_file=sys.argv
#
# with open(scr_file,'rb') as read_f,
# open(dst_file,'wb') as write_f:
# for line in read_f:
# write_f.write(line)
文件的修改
代码语言:javascript复制import os
with open('info.txt','r',encoding='utf-8') as read_f,
open('.info.txt.swap','w',encoding='utf-8') as write_f:
data=read_f.read()
write_f.write(data.replace('alex','sb'))
os.remove('info.txt')
os.rename('.info.txt.swap','info.txt')
#上面这种方法直接把文件全部读到内存中,有缺陷
#第二种方法 参考1:
代码语言:javascript复制import os
with open('info.txt','r',encoding='utf-8') as read_f,
open('.info.txt.swap','w',encoding='utf-8') as write_f:
data=read_f.read()
write_f.write(data.replace('alex','sb'))
for line in read_f: #第一种
write_f.write(line.replace('sb', 'alex'))
for line in read_f: #第二种
if 'alex' in line:
line=line.replace('alxe','sb')
write_f.read(line)
os.remove('info.txt')
os.rename('.info.txt.swap','info.txt')
参考2:
代码语言:javascript复制import os
with open('userlist.txt','r',encoding='utf-8') as read_f,
open('.userlist.txt.swap','w',encoding='utf-8') as write_f:
for line in read_f:
if 'dzm' in line:
line=line.split(':')
line[1]='99'
line=':'.join(line)
write_f.write(line)
os.remove('userlist.txt')
os.rename('.userlist.txt.swap','userlist.txt')
format
#format可以用{}进行占位,如果文件里有{}了,可以在外面再加一层{}进行转义(例如{{}})
#例:根据模板文件生成信息数据文件
#模板文件内容(nginx.conf.tpl)
{user}
#使用方式:
#定义变量
user = 'dzm'
fhandler = open('nginx.conf.tpl','r')
tpl = fhandler.read()
fhandler.close()
fhandler = open('nginx.conf','w')
fhandler.write(tpl.format(user=user))
fhandler.close()
结果模板文件中的{user}就会变成dzm
了解知识点
文件内光标的移动
#只有一种情况光标以字符为单位:文件以rt方式打开,例如read(3)
代码语言:javascript复制# with open('info.txt','r',encoding='utf-8') as f:
# # print(f.read(6))
# f.seek(3)#这里移动的是字符
# print(f.read())
# print(f.tell())
#b以字节为单位移动 0模式为从文件开头为参照,只有0模式能在t模式下操作
代码语言:javascript复制# with open('info.txt','rb') as f:
# f.seek(6,0) #光标从0个字符(文件开头)移动到第六个字节
# print(f.tell())
# 6
#1模式以当前位置为参照物 #2模式参照物为文件的末尾 #0,1,2模式都以字节为参照物,但0模式比较特殊,能够用在t模式下
seek(0)就是把光标移动到文件开始位置
代码语言:javascript复制# with open('info.txt','rb') as f:
# f.seek(0,2)#2模式,光标直接移动到了文件末尾
# print(f.tell())
#模拟tail -f
代码语言:javascript复制# import time
# with open('info.txt','rb') as f:
# f.seek(0, 2)
# while True:
# line=f.readline()
# if line:
# print(line.decode('utf=8'))
# else:
# time.sleep(0.5)
截断文件
代码语言:javascript复制# with open('access.log','a',encoding='utf-8') as f:
# f.truncate(3)
#从文件开始算起 #按照字符截断,第三个字符后面的内容就会被删除
函数
#自定义函数 #语法:
代码语言:javascript复制# def 函数名 (参数1,参数2):
# '''注释'''
# 函数体
# return 返回值
def auth():
name=input('>>: ')
password=int(input('>>: '))
if name == 'dzm' and password == 123:
print('登录成功')
else:
print('user or pass error')
auth()
#定义函数阶段,只检测语法,不执行代码
#函数的使用要遵循先定义后使用的原则 #使用是指调用这个函数时,函数是否已经定义过 #定义阶段有参数,调用阶段必须有参数 #定义函数的三种类型 #第一种无参函数 #第二种有参函数 #第三种空函数
#有参函数
代码语言:javascript复制# def auth(name,password):
# if name == 'dzm' and password == '123':
# print('login successfulll')
# else:
# print('user or password err')
#
# def interactive():
# name=input('name>>: ').strip()
# password=input('password>>: ').strip()
# auth(name,password)
#
# interactive()
#空函数
代码语言:javascript复制# def ls():
# pass
函数的返回值 #return:函数里可以有多个return,但只能执行一次return #执行return函数就立即结束,并且把return的值当做本次调用的结果返回 #函数没有return 默认返回None #return返回多个值会把多个值放入元祖中返回
#return返回的值没有类型限制
#返回值和返回函数的内存地址之间的区别
代码语言:javascript复制# def name():
# return 'dzm'
#
# def password():
# print('123')
# return name
#
# print(password())
# <function name at 0x000001B19DF02E18>
# def password2():
# print('123')
# return name()
# print(password2())
# dzm
#上面的例子是引用函数时带括号和不带括号的区别,带括号表示函数的返回值,不带括号表示函数本身的内存地址
#函数调用的三种形式
代码语言:javascript复制#res=my_max(1,2)
#res=my_max(1,2)*10
#res=my_max(my_max(1,2),3) #把函数调用结果当做另一个函数的参数
函数的参数
#形参:在定义阶段括号内指定的参数,相当于变量名 #实参:在调用阶段括号内传入的值称为实参,相当于值 #在调用阶段,实参的值会绑定给形参,在调用结束后解绑
#参数分类
#1.位置参数
#位置形参:从左至右依次定义参数 #位置实参:与形参一一对应传值
#2.关键字参数
#关键字实参和位置实参可以混用,但关键字实参要在位置实参后面 #不能为同一个参数赋多次值
#3.默认参数,在函数定义阶段就已经为形参赋值
#定义阶段已经有值以为着调用阶段可以不用传值 #注意: ##1.默认参数必须放到位置形参后面
代码语言:javascript复制## def register(name,age,sex='male'):
## print(name,age,sex)
##2.默认参数的值只在定义阶段被赋值一次 ##3.默认参数通常为不可变类型
#4.可变长参数:在函数调用时,实参值的个数不固定 #实参的形式有:位置实参和关键字实参 #形参的解决方案:*,**
#只接受位置传参多余的参数,并将多余的传参转换为元祖形式保存 #args是约定俗成的写法
代码语言:javascript复制# def foo(x,y,*args): #args=(3, 4, 5)
# print(x,y)
# print(z)
# foo(1,2,3,4,5)
# 结果
# 1 2
# (3, 4, 5)
#实参当中的 #实参当中碰到就代表位置传参,将后面的内容转成原型理解即可,如下例
代码语言:javascript复制# foo(1,2,*[3,4,5,6]) #foo(1,2,3,4,5,6)
# foo(*[1,2,3,4,5,6]) #foo(1,2,3,4,5,6)
#*后面的内容直接就是位置参数
只接受关键字传参多余的参数,并将多余的传参转换为字典形式保存 kwargs也是约定俗成的写法
代码语言:javascript复制# def foo(x,y,**kwargs): #kwargs={'a': 3, 'b': 4, 'c': 5}
# print(x,y)
# print(kwargs)
# foo(y=2,x=1,a=3,b=4,c=5)
#结果
# 1 2
# {'a': 3, 'b': 4, 'c': 5}
#实参当中的
#将实参当中后面的内容理解成关键字传参即可
# foo(y=2,**{'c':5,'b':4,'a':3}) #等同于foo(y=2,c=5,a=3,b=4)
#举例 #下面这种写法可以把一个函数得到的传参以原封不动的形式传给它内部的另外一个函数
代码语言:javascript复制def bar(x,y,z):
print(x,y,z)
代码语言:javascript复制#*一定要在**之前
def wrapper(*args,**kwargs): #args=(1),kwargs={'y':2,'z':3}
bar(*args,**kwargs) #bar(1,y=2,z=3) #又打回了原型
wrapper(1,y=2,z=3)
#了解即可 #命名关键字参数,指的是定义在后面的参数,该参数必须被传值(除非它有默认值),并且必须以key=value的方式传值 #args也算,后面的就都是命名关键字参数了
函数对象
#函数是第一类对象:指的是函数可以当做数据传递 #1.可以被引用 x=1,y=x
代码语言:javascript复制# def func(x,y)
# print(x,y)
#
# f=func#把函数本身赋值
# f(1,2)
#2.可以当做函数的参数传入
代码语言:javascript复制# def foo():
# print('from foo')
# def bar(func):
# func()
#
# bar(foo)
#
#3.可以当做函数的返回值
代码语言:javascript复制# def foo():
# print('from foo')
# def bar(func):
# return func
#
# f=bar(foo)
# f()
#4.可以当做容器类型的元素
代码语言:javascript复制# def foo():
# print('from foo')
# def bar(f):
# return foo
#
# l=[foo,bar]
# l[0]()
#到了列表里也是函数
代码语言:javascript复制# def ls():
# print('ls')
#
# func_dic={
# 'ls':ls,
# }
#
# name=input('>>: ').strip()
# if name in func_dic:
# func_dic[name]()
函数的嵌套
#函数的嵌套调用
代码语言:javascript复制def my_max(x,y):
if x >= y:
return x
else:
return y
def my_max2(a,b,c,d):
res1=my_max(a,b)
res2=my_max(res1,c)
res3=my_max(res2,d)
return res3
#函数的嵌套定义 #在函数内部定义的函数只能在函数内部使用
代码语言:javascript复制# def f1():
# def f2():
# print('from f2')
# def f3():
# print('from f3')
# f3()
# f2()
#
# f1()
名称空间与作用域
#内置名称空间:python解释器内置的名字,len,print等 #python解释器启动就有
#全局名称空间 #执行python文件时才生效 #顶着头写的名字就是全局空间
代码语言:javascript复制# x=1
# def func():pass
# import time
#局部名称空间:函数内部定义的 #函数被调用时才会执行函数内的代码,函数内局部名称空间的名称才会生效,调用结束失效
#加载顺序:内置---》全局---》局部名称空间 #访问名字的顺序:局部名称空间---》全局---》内置
作用域
#1、作用域即范围 #- 全局范围(内置名称空间与全局名称空间属于该范围):全局存活,全局有效 #- 局部范围(局部名称空间属于该范围):临时存活,局部有效 #2、作用域关系是在函数定义阶段就已经固定的,与函数的调用位置无关,如下
代码语言:javascript复制x=1
def f1():
def f2():
print(x)
return f2
x=100
def f3(func):
x=2
func()
x=10000
f3(f1())
#使用global x这样的形式可以把局部名称定义为全局名称 #使用nonlocal x这样的形式可以把局部名称向上覆盖上一级函数相同名称,但出不了整个函数
#3、打破函数层级限制来调用函数 #例
代码语言:javascript复制# def outter():
# def inner():
# print('inner')
# return inner
#
# f=outter()
#
# def bar():
# f()
# bar()
#4、查看作用域:globals(),locals()
#LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> builtins #locals 是函数内的名字空间,包括局部变量和形参 #enclosing 外部嵌套函数的名字空间(闭包中常见) #globals 全局变量,函数定义所在模块的名字空间 #builtins 内置模块的名字空间
闭包函数
#一 什么是闭包?
#内部函数包含对外部作用域而非全局作用域的引用
#通常将闭包函数用return返回,然后可以在任意使用
#提示:之前我们都是通过参数将外部的值传给函数,闭包提供了另外一种思路 #举例:
代码语言:javascript复制# def outer():
# x=1
# y=2
# def inner():
# print(x,y)
# return inner
#
# f=outer()
#
# def bar():
# x=111112
# y=33333
# f()
#
# bar()
#二 闭包的意义与应用 #闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域 #应用领域:延迟计算(原来我们是传参,现在我们是包起来)
代码语言:javascript复制# import requests
#
# def outter(url):
# def get():
# response = requests.get(url)
# if response.status_code == 200:
# print(len(response.text))
# return get
#
# baidu=outter('https://www.baidu.com')
#
# baidu()
装饰器
#无参装饰器 #开放封闭原则:对修改封闭,对扩展开放 #强调装饰器的原则:1 不修改被装饰对象的源代码 2 不修改被装饰对象的调用方式 #装饰器的目标:在遵循1和2的前提下,为被装饰对象添加上新功能
代码语言:javascript复制# import time
# def index():
# time.sleep(3)
# print('welcome to index')
#
# def timmer(func):
# def inner():
# start=time.time()
# func()
# stop=time.time()
# print('run time is %s' %(stop-start))
# return inner
#
# index=timmer(index)
# index()
#装饰器语法:@装饰器名
代码语言:javascript复制# import time
#
# def timmer(func):
# def inner():
# start=time.time()
# func()
# stop=time.time()
# print('run time is %s' %(stop-start))
# return inner
#
# #py解释器遇到@就会把@timmer下面的函数名当成参数传给timmer这个函数,并且把结果重新命名给index
# @timmer #index=timmer(index)
# def index():
# time.sleep(3)
# print('welcome to index')
# return 111
# index()
#装饰器改进1 #理解上面的装饰器,会想到一个问题,如果函数index有返回值的话,那么按照上面的写法就无法实现返回index的返回值,因为index()实际执行的是inner(),而inner()返回值为空 #按照下面改进,可以解决这个问题
代码语言:javascript复制#import time
# def timmer(func):
# def inner():
# start=time.time()
# res=func() #这里执行的是原始的index函数
# stop=time.time()
# print('run time is %s' %(stop-start))
# return res
# return inner
#
# @timmer #index=timmer(index)
# def index():
# time.sleep(3)
# print('welcome to index')
# return 111
#
# res=index()
# print(res)
#装饰器改进2 #这个改进解决了传参问题
代码语言:javascript复制# import time
#
# def timmer(func):
# def inner(*args,**kwargs):
# start=time.time()
# res=func(*args,**kwargs) #这里执行的是原始的index函数
# stop=time.time()
# print('run time is %s' %(stop-start))
# return res
# return inner
#
# @timmer #index=timmer(index)
# def index(name):
# time.sleep(3)
# print('welcome %s to index' %name)
# return 111
#
# res=index('dzm')
# print(res)
有参装饰器
代码语言:javascript复制 import time
def auth2(engine='file'):
def auth(func): # func=index
def inner(*args,**kwargs):
if engine == 'file':
name=input('name>>: ').strip()
password=input('password>>: ').strip()
if name == 'egon' and password == '123':
print('login successful')
return func(*args,**kwargs)
else:
print('login err')
elif engine == 'mysql':
print('mysql auth')
elif engine == 'ldap':
print('ldap auth')
else:
print('engin not exists')
return inner
return auth
#碰到函数加括号优先执行,先不要管@符号
@auth2(engine='mysql') #@auth #index=auth(index) #index=inner
def index(name):
time.sleep(1)
print('welecome %s to index' %name)
return 1111
res=index('egon') #res=inner('egon')
print(res)
wraps补充
代码语言:javascript复制from functools import wraps
import time
def timmer(func):
@wraps(func)
def inner(*args,**kwargs):
start=time.time()
res=func(*args,**kwargs)
stop=time.time()
print('run time is %s' %(stop-start))
return res
# inner.__doc__=func.__doc__
# inner.__name__=func.__name__
return inner
@timmer
def index(name): #index=inner
'''index 函数。。。。。'''
time.sleep(1)
print('welecome %s to index' %name)
return 1111
# res=index('egon')
# print(res)
print(help(index))