文件处理
f = open(‘a.txt’,’r’)
f.read()
open是在打开一个文件,是在哪里发起的请求?是在.py文件里面发起的,是自己写的应用程序,应用程序能直接操作硬件吗?所以这一步是在向操作系统发起一个请求,是不是要打开一个文件
打开一个文件,最后赋值给f,这个f被应用程序的内存拿着,其实就是python变量的赋值操作,但是不仅仅拿到了f,操作系统还打开了一个文件对应着,用户可以直接拿着f,用f.read()执行读操作,这是系统调用,向操作系统发起了请求,正好对应操作系统打开的文件,操作系统接到read指令后,会到硬盘上读内容,然后返回给程序
字符编码
什么是字符编码
把人类的字符翻译成计算机能认识的数字
什么是字符编码表
就是一张字符与数字对应关系的表
Ascii
Gbk
Utf-8
Unicode
Unicode-->encode(‘utf-8’)-->bytes
Bytes---->decode(‘utf-8’)---->unicode
内存用的都是unicode,为的是保证速度,硬盘用utf-8,用gbk都行,为的是存储容量越小越好
原则:
字符以什么格式编码的就要以什么格式解码
补充:
写程序和编辑普通文件没有什么区别,最后保存在硬盘上,运行是交给cpu运行,
硬盘如何让cpu去运行呢?首先要把文件中的内容整体先加载到内存中,再谈执行的问题
那么硬盘中以utf-8编码的往内存中里面走,应该是解码成unicode.
python3中的字符串分为两种 x='egon' 存成unicode y=x.encode('utf-8') 存成bytes ---------------------------------- python2中的字符串也分为两种 x = u'egon' 与python3中的字符串一样 y = 'alex' 与python3的bytes一样
#r文本模式的读,在文件不存在时,不会创建新文件 f=open('a.txt','r',encoding='utf-8') print(f.read())
print(f.readline())
print(f.readlines()) f.close() #rb模式即直接从硬盘中读取bytes f=open('a.txt','rb') # 因为是直接从硬盘中读取的二进制,所以不需要encoding print(f.read()) #b'xe4xbdxa0xe5xa5xbdxe5x95x8aalex' print(f.read().decode('utf-8')) #你好啊
#wb模式
f=open('a.txt','wb')
#f.write('你好啊') #会报错
f.write('你好啊'.encode('utf-8')) # Python3的字符串是unicode类型,unicode转为bytes需要encode
#python3 copy.py a.jpg b.jpg 拷贝文件,文本文件(字符编码),非文本文件(编码有问题,所以只能采取二进制模式拷贝文件)。采用二进制,无论什么格式,都不会乱码 --------------------------------------------- import sys #python copy.py source.file target.file # print(sys.argv) # sys.exit() if len(sys.argv) < 3: # 需要三个参数 print('Usage:python3 copy.py source.file target.file') sys.exit() #r'c:UsersAdministratorPycharmProjectspyhton18' #python copy.py C:source.file D: arget.file #处理windows路径的方式 with open(r'%s' % sys.argv[1],'rb') as read_f, open(r'%s' % sys.argv[2],'wb') as write_f: for line in read_f: write_f.write(line)
文件其他操作
#w文本模式的写,文件存在则清空,不存在则创建 f=open('a.txt','w',encoding='utf-8') f.write('你好 ') f.writelines(['1111 ','222 '])
#a文本模式的追加,文件存在,光标跳到文件末尾,文件不存在则创建 f=open(‘b.txt’,'a',encoding='utf-8') print(f.writable()) #True
print(f.readable()) #Falese
打开文件并不是应用程序自己的事情,打开文件后,我们拿到了变量名f,对应着一个值,这个f是应用程序拿着,操作系统还拿着打开的文件,如果要回收,应该是两个都要回收掉
f=open('a.txt','wb') f.write('你好啊'.encode('utf-8'))
print(f) # <_io.BufferedWriter name='a.txt'>
f.close() # 向操作系统发起请求,关闭掉打开的文件,操作系统回收掉打开的文件,
print(f) #<_io.BufferedWriter name='a.txt'>,虽然关掉了文件,但是f是应用程序级别定义的变量,这个变量是在这个变量f对应的值没有引用了才会被回收掉
print(f.read) # 方法依然还有
print(f.readable) # 方法依然还有
f.read() # 不能运行,向操作系统发请求,操作系统已经关掉了这个文件,所以会报io出错
#del f # 回收掉了应用程序级别的
# a.txt 你好啊1 你好啊2 你好啊3 f=open('a.txt','r',encoding='utf-8') print(f.read(3)) #文件打开方式为文本模式时,代表读取3个字符 #你好啊
# a.txt 你hello好啊1 你好啊2 你好啊3 f=open('a.txt','r',encoding='utf-8') print(f.read(3)) #文件打开方式为文本模式时,代表读取3个字符 #你he
# a.txt 你hello好啊1 你好啊2 你好啊3 f=open('a.txt','rb') print(f.read(3)) #文件打开方式为二进制模式时,代表读取3个字节 #b'xe4xbdxao'
print(f.read(3).decode('utf-8'))
# 你 三个字节,unicode是三个字节存一个中文
print(f.read(2)) # b'xe4xbd'
print(f.read(2).decode('utf-8')) #报错 2个字节无法解出一个中文
一.read(3):
1.文件打开方式为文本模式时,代表读取3个字符 # 只有read的文本模式可以读字符,除此以外全是以字节为单位,不管文件打开模式是什么模式,都是以字节为单位
2.文件打开方式为b模式时,代表读取3个字节
#a.txt 你好啊alex
f=open('a.txt','r',encoding='utf-8')
print(f.read())
f.seek(3)
print(f.tell())
print(f.read())
# 你好啊alex
# 3
# 好啊alex
f=open('a.txt','r',encoding='utf-8')
print(f.read(3))
print(f.tell()) #以字节为单位显示
print(f.read(1))
f.seek(6)
print(f.read(1))
# 你好啊
# 9
# a
# 啊
二.其余文件内光标移动都是以字节为单位,如seek,tell,truncate
1.seek有三种移动方式,0.1.2,其中1和2必须在b模式下进行,但无论哪种模式,都是以bytes为单位移动的
f.seek(6,0) f.seek(6,1) f.seek(6,2) # 0,1,2 指定的参照物不一样
0 默认参照物为文件开头,
1 以当前光标所在的位置为参照物
2 从结尾位置为参照物
f=open('a.txt','rb') 1和2必须在b模式下进行
f.read(3) read了三个字符,正好是三个中文字符,9个字节 f.seek(2,1) 当前光标是在第9个字节,在第9个字节往后seek了2个字节,所以光标现在在第11个字节
f=open('a.txt','rb') print(f.read(3)) # 读了3个字节 print(f.tell()) # 3 f.seek(3,0) print(f.tell()) # 3 print(f.read(1)) #读的是第4个字节
f=open('a.txt','rb')
print(f.read(3)) # b'xe4xbdxa0'
print(f.tell()) # 3
f.seek(3,1) # 基于当前光标往后移动了3个字节
print(f.tell()) # 6
# a.txt
你好啊alex
f=open('a.txt','rb')
f.seek(0,2) #相对于文件末尾seek 0个位置
print(f.tell()) # 13,文件的结尾
f.seek(-1,2) #向左切一个字节
print(f.read()) # b'x'
2.truncate(没有用)是截断文件,所以文件的打开方式必须可写,但是不能用w或w+等方式打开,因为会直接清空文件,所以truncate要在r+或a或a+等模式下测试
with open('a.txt','r+',encoding='utf-8') as f: f.truncate(9) # 从文件开头开始截9个字节
#你好啊
模拟linux的tail 命令
#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.decode('utf-8'),end='') else: time.sleep(0.2) 追加 # access.log with open('access.log','a') as f: f.write('1111 ')
函数
问题:
1.复杂度增大
2.组织结构不清晰
3.可读性差
4.代码冗余
5.可扩展性差
如何解决问题:
1.工具就是具备某一种功能的物件,就是程序中函数的概念
2.事先准备工具的过程称为函数的定义
3.遇到特定的场景拿来就用称为函数的调用
分类:
1.内置函数(解释器自带的)
2.自定义函数
1.先定义
函数的定义与变量的定义类似,没有事先定义变量,而直接引用变量
会报错,没有事先定义函数,而直接调用,就相当于在引用一个不存在的变量名
def foo(): print('from foo')
2.再调用
foo() #先根据foo这个名字找到foo对应的值,然后这个值加上()运行
函数定义阶段,只检测语法,不执行代码
def bar(): print('from bar') def foo(): print('from foo') bar() foo()
#定义阶段 def foo(): print('from foo') bar() def bar(): print('from bar') #调用阶段 foo() # 不会报错
# from foo
# from bar
函数定义语法
def 函数名(arg1,arg2,arg3): '''注释''' 函数体 return 返回值 函数名一般是动词
定义的三种形式
无参
应用场景仅仅只是执行一些操作,比如与用户交互,打印
有参
需要根据外部代码传进来的参数,才能执行相应的逻辑
def my_max(x,y): if x > y: print(x) else: print(y) my_max(1,2)
# 2
def my_max(x,y):
if x > y:
print(x)
else:
print(y)
res=my_max(1,2)
print(res)
#2
#None
def foo():
print('-----')
return 123 # 函数内可以有多个return,但只能执行一次,整个函数就结束掉,并且会把return后的值作为函数执行的结果返回
print('-----')
foo()
#-----
空函数
设计代码结构
def select(sql):
'''select function''' print(sql)
#sql=['select','*','from','mysql.user;']
def insert(sql):
'''insert function'''
pass
def update(sql):
'''update function'''
pass
def delete(sql):
'''delete function'''
pass
# select * from mysql.user;
def main():
while True:
sql=input('>>: ').strip()
if not sql:continue
cmd_info=sql.split()
cmd=cmd_info[0]
if cmd == 'select':
select(cmd_info)
elif:
.....
main()
文件补充:
#一行一行打印,同一时间,内存中只有一行内容 with open('a.txt','r',encoding='utf-8') as f: for line in f: print(line)
def func(): print('from func') return [1,2,3],'a',1,{'a':3} res = func() print(res) return的返回值没有类型限制 没有return,返回None,等同于return None return 一个值,返回该值 return val1,val2,val3;返回(val1,val2,val3)
什么时候该有返回值?
调用函数,经过一系列的操作,最后要拿到一个明确的结果,则必须要有返回值
通常有参函数需要有返回值,输入参数,经过计算,得到一个最终结果
什么时候不需要有返回值?
调用函数,仅仅只是执行一系列的操作,最后不需要得到什么结果
则无需要有返回值
函数调用的三种形式
def my_max(x,y): if x > y: return x else: return y res = my_max(1,2) #语句形式 res1 = my_max(1,2)*10 #表达式形式 res2 = my_max(my_max(1,2),3) #函数调用可以当作另外一个函数的参数
def func(): print('from func') return [1,2,3],'a',1,{'a':3} res = func() print(res)
函数参数:
#在定义函数时,括号内的参数称为形参,不占内存空间
def foo(x,y): #x,y是形参, x=1,y=2 形参就是变量名 print(x) print(y) #在调用函数时,括号内的参数称为实参,真正占内存空间的 foo(1,2) #1,2是实参 实参就是变量值
#在调用阶段,实参(变量值)才会绑定形参(变量名),调用结束后,解除绑定
参数的分类:
位置参数:按照从左到右的顺序依次定义的参数
1.位置形参:必选参数,多一个不行,少一个不行
2.位置实参:与形参按照位置一一对应
def foo(name,age): print(name) print(age) foo('tom',1)
关键字参数
def foo(name,age): print(name) print(age) foo(age=1,name='tom')
默认形参
x=100 def foo(a,b=x): #定义阶段 print(a,b) x=0 foo('egon') # egon 100 默认参数只在定义阶段赋值一次,而且仅一次 默认参数的值应该定义成不可变类型
可变长参数:实参的个数不固定
def foo(x,y,*args): print(x) print(y) print(args) foo(1,2,3,4,5,6,7)
def foo(x,y,**kwargs): print(x) print(y) print(kwargs) foo(x=1,y=2,z=3,a=1,b=2)
#装饰器的前身
import time def register(name,age,sex='male'): print(name) print(age) print(sex) time.sleep(3)
#统计register函数运行了多长时间,前提是不能更改register内部的源代码 def wrapper(*args,**kwargs): start_time=time.time() register(*args, **kwargs) stop_time=time.time() print('run time is %s' %(stop_time-start_time))
wrapper('egon',age=18) #但是函数的调用方式变了,由调用register(),改为调用wrapper(),目前只能到这里,到装饰器时再把调用方式改为register()
命名关键字参数:在*后面定义的形参称为命名关键字参数,
必须是以关键字实参的形式传值
def foo(name,age,*,sex): print(name) print(age) print(sex) foo('egon',18,sex='male')
def foo(name,age,*,sex='male',group): print(name) print(age) print(sex) print(group) foo('egon',18,group='group1',sex='male')
def foo(name,age,*args,sex='male',group): print(name) print(age) print(args) print(sex) print(group) foo('egon',18,19,20,300,group='group1')
# egon
# 18
# (19, 20, 300)
# male
# group1
顺序很重要,但是没有全放在一起的场景
def foo(name,age=18,*args,sex='male',group,**kwargs): pass
函数对象
函数是第一类的对象,指的是函数可以被当作数据传递
1.被赋值
def foo(): print('from foo') f=foo print(f) # 就是foo那个函数 f() # 相当于执行foo()
2.可以当作参数传入
def wrapper(func): print(func) #打印函数foo的内存地址 func() #运行foo函数 wrapper(foo) # foo对应的内存地址传给func
3.可以当作函数的返回值
def wrapper(func): return func res=wrapper(foo) print(res) #返回foo的内存地址
4.可以当作容器类型的元素
cmd_dic={ 'func':foo #返回的是字典,{'func': <function foo at 0x00000250CA033E18>} } print(cmd_dic) cmd_dic['func']() #运行foo函数
def select(sql): '''select function''' print('select--->',sql) def insert(sql): '''insert function''' print('insert--->',sql) def update(sql): '''update function''' print('update--->',sql) def delete(sql): '''delete function''' print('delete--->',sql) cmd_dic = { 'insert':insert, 'update': update, 'delete': delete, 'select': select } def main(): while True: sql=input('>>: ').strip() if not sql:continue cmd_info=sql.split() cmd=cmd_info[0] if cmd in cmd_dic: cmd_dic[cmd](cmd_info) else: print('cmd not exists') main()
匿名函数lambda
待补充
内建函数
待补充
函数的递归调用
待补充
二分法
待补充
文件补充
with open('a.txt','r',encoding='utf-8') as f: l = f.readlines() for line in l: print(line,end='')
一次性把文件全部都到内存里,若文件很大,会撑爆内存
with open('a.txt','r',encoding='utf-8') as f: for line in f: print(line,end='')
同一时间,内存里只有一行内容