Python笔记-3
一、文件的操作
1、文件的读、写、新增
读文件的获取句柄的语法:f=open('path/file')
句柄的理解:
<_io.TextIOWrapper name='/root/myfile/test_directory/file1' mode='r' encoding='utf-8'>
文件句柄包含硬盘位置,文件大小,字符集等信息 封装成一个内存对象给这个变量,句柄如光标只能往下移动
文件全文读:read()
f=open('tmpfile') f1=open('tmpfile') print(f) x=f.read() print(f) print(x) print('------------------------------------------') print(x) print('------------------------------------------') print(f1.read()) print('------------------------------------------') print(f1.read()) print('------------------------------------------')
*******************************************************************************************************
<_io.TextIOWrapper name='tmpfile' mode='r' encoding='utf-8'>
<_io.TextIOWrapper name='tmpfile' mode='r' encoding='utf-8'>
Doe, a deer, a female deer
Ray, a drop of golden sun
Me, a name I call myself
Far, a long, long way to run
Sew, a needle pulling thread
La, a note to follow Sew
Tea, a drink with jam and bread
That will bring us back to Do (oh-oh-oh)
Do-re-mi-fa-so-la-ti-do
So-do!
------------------------------------------
Doe, a deer, a female deer
Ray, a drop of golden sun
Me, a name I call myself
Far, a long, long way to run
Sew, a needle pulling thread
La, a note to follow Sew
Tea, a drink with jam and bread
That will bring us back to Do (oh-oh-oh)
Do-re-mi-fa-so-la-ti-do
So-do!
------------------------------------------
Doe, a deer, a female deer
Ray, a drop of golden sun
Me, a name I call myself
Far, a long, long way to run
Sew, a needle pulling thread
La, a note to follow Sew
Tea, a drink with jam and bread
That will bring us back to Do (oh-oh-oh)
Do-re-mi-fa-so-la-ti-do
So-do!
------------------------------------------
------------------------------------------
此代码的注意点:句柄被read()后,指向了文末,此时要再调用次句柄对文本进行read()则无法读到新内容。我们可以将句柄的初始状态赋值给一个变量来方便多次读取。一个文件可以打开多次获得多个句柄,如代码中的f、f1。默认在不指定方法的时候,文件以r方式打开。
文件逐行读与显示行号的方法;readline()、readlines()、for i in f
f=open('tmpfile','r',encoding='utf-8') f1=open('tmpfile','r',encoding='utf-8') f2=open('tmpfile','r',encoding='utf-8') print(f) x=f.readlines() w=f1.readline() print(''.center(50,'-')) print(x) print(''.center(50,'-')) print(w) print(''.center(50,'-')) for i in x : print(i.strip()) for i ,j in enumerate(x): print(i,j.strip()) count=0 for i in f2: print(count,i.strip()) count+=1
》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
<_io.TextIOWrapper name='tmpfile' mode='r' encoding='utf-8'>
--------------------------------------------------
['Doe, a deer, a female deer\n', '\u3000\u3000Ray, a drop of golden sun\n', '\u3000\u3000Me, a name I call myself\n', '\u3000\u3000Far, a long, long way to run\n', '\u3000\u3000Sew, a needle pulling thread\n', '\u3000\u3000La, a note to follow Sew\n', '\u3000\u3000Tea, a drink with jam and bread\n', '\u3000\u3000That will bring us back to Do (oh-oh-oh)\n', '\u3000\u3000Do-re-mi-fa-so-la-ti-do\n', '\u3000\u3000So-do!\n']
--------------------------------------------------
Doe, a deer, a female deer
--------------------------------------------------
Doe, a deer, a female deer
Ray, a drop of golden sun
Me, a name I call myself
Far, a long, long way to run
Sew, a needle pulling thread
La, a note to follow Sew
Tea, a drink with jam and bread
That will bring us back to Do (oh-oh-oh)
Do-re-mi-fa-so-la-ti-do
So-do!
0 Doe, a deer, a female deer
1 Ray, a drop of golden sun
2 Me, a name I call myself
3 Far, a long, long way to run
4 Sew, a needle pulling thread
5 La, a note to follow Sew
6 Tea, a drink with jam and bread
7 That will bring us back to Do (oh-oh-oh)
8 Do-re-mi-fa-so-la-ti-do
9 So-do!
0 Doe, a deer, a female deer
1 Ray, a drop of golden sun
2 Me, a name I call myself
3 Far, a long, long way to run
4 Sew, a needle pulling thread
5 La, a note to follow Sew
6 Tea, a drink with jam and bread
7 That will bring us back to Do (oh-oh-oh)
8 Do-re-mi-fa-so-la-ti-do
9 So-do!
此代码的注意点:readline()为逐行读,readlines()可以将文本转换为列表。通过列表的特性,我们可以轻易的输出文本及行号。同时使用for i in f句柄的方式我们也可以逐行输出文本。
文件的写入操作
文件的读和写操作是分开的,在获得文件句柄的时候需要标注方法,如果没有写,默认为r,读的方法。同时需要强调一袋奶w方法属于新建,会清空文本的所有内容需要非常注意。
f2=open('/root/myfile/test_directory/file2','w',encoding='utf-8')
f=open('writetmp','w',encoding='utf-8') f.write('abc') f.write('def') f.write('\nggg')
------------------------------------------------------- [root@VM_61_212_centos my_python_file]# cat writetmp abcdef ggg
该代码的注意点:write文件不存在会新建,文件存在会情况重写,如果没有手工换行,每次write将直接连着写入
文件的追加:w的方式处理文件,原有的内容会被清空重新写,使用a的方式处理文件,可以在保留文本内容的情况下在文档后进行追加
f=open('writetmp','a',encoding='utf-8') f.write('111') f.write('222') f.write('\n333') ******************************************* [root@VM_61_212_centos my_python_file]# cat writetmp abcdef ggg [root@VM_61_212_centos my_python_file]# ./tmp_1.py [root@VM_61_212_centos my_python_file]# cat writetmp abcdef ggg111222 333
with获得句柄的方法:with open('file') a f:,使用次方法在with接受后,句柄能自动close()
2、了解文件的组合型打开方式
打开文件的模式有:
- r,只读模式(默认)。
- w,只写模式。【不可读;不存在则创建;存在则删除内容;】
- a,追加模式。【可读;不存在则创建;存在则只追加内容;】
"+" 表示可以同时读写某个文件
- r+,可读写文件。【可读;可写;可追加】
- w+,写读
- a+,同a
"U"表示在读取时,可以将 \r \n \r\n自动转换成 \n (与 r 或 r+ 模式同使用)rU
- r+U
"b"表示处理二进制文件(如:FTP发送上传ISO镜像文件,linux可忽略,windows处理二进制文件时需标注)
- rb
- wb
- ab
3、文件的替换、判断、定位、转换等操作
输出文档名:使用f.name,注意f.name,name后面无需加()
with open('tmpfile') as f: print(f.name)
批量修改文档内容:使用字符串replace()
#!/bin/env python3.6 f=open("/root/myfile/test_directory/jueqi",'r',encoding='utf-8') f_new = open("/root/myfile/test_directory/jueqi.new",'w',encoding='utf-8') for i in f: if '崛起' in i: i = i.replace("崛起","***崛起***") f_new.write(i) f.close() f_new.close()
此代码的说明:打开两个文件,读一行写一行来节省内存使用率
对于句柄的定向移动:使用seek()、tell()来定位
>>> f=open('/root/myfile/my_python_file/tmpfile') >>> f.readline() 'Doe, a deer, a female deer\n' >>> f.tell() 27 >>> f.readline() '\u3000\u3000Ray, a drop of golden sun\n' >>> f.tell() 59 >>> f.readline() '\u3000\u3000Me, a name I call myself\n' >>> f.tell() 90 >>> f.seek(27) 27 >>> f.readline() '\u3000\u3000Ray, a drop of golden sun\n' >>> >>> f.close() >>> f1=open('/root/myfile/my_python_file/tmpfile','a',encoding='utf-8') >>> f1.tell() 319 >>> f1.seek(27) 27 >>> f1.tell() 27 >>> f1.write('----------------------') 22 >>> f1.tell() 341 >>> f=open('/root/myfile/my_python_file/tmpfile') >>> f.readline() 'Doe, a deer, a female deer\n' >>> f.readline() '\u3000\u3000Ray, a drop of golden sun\n' >>> f.readline() '\u3000\u3000Me, a name I call myself\n' >>> f.readline() '\u3000\u3000Far, a long, long way to run\n' >>> f.readline() '\u3000\u3000Sew, a needle pulling thread\n' >>> f.readline() '\u3000\u3000La, a note to follow Sew\n' >>> f.readline() '\u3000\u3000Tea, a drink with jam and bread\n' >>> f.readline() '\u3000\u3000That will bring us back to Do (oh-oh-oh)\n' >>> f.readline() '\u3000\u3000Do-re-mi-fa-so-la-ti-do\n' >>> f.readline() '\u3000\u3000So-do!\n' >>> f.readline() '----------------------' >>> f.readline() '' >>> f.readline() '' >>> f2=open('tmpxxx','w',encoding='utf-8') >>> f2.write('hello\n') 6 >>> f2.write('world\n') 6 >>> f2.tell() 12 >>> f2.seek(6) 6 >>> f2.tell() 6 >>> f2.write('hi\n') 3 >>> f3=open('tmpxxx','r',encoding='utf-8') >>> f3.read() 'hello\nworld\n' >>> f2.write('hi\n') 3 >>> f2.write('hi\n') 3 >>> f2.write('hi\n') 3 >>> f2.write('hi\n') 3 >>> f3.read() '' >>> f3.seek(0) 0 >>> f3.read() 'hello\nworld\n' >>> f2.tell() 21 >>> exit() [root@VM_61_212_centos my_python_file]# cat tmpxxx hello hi hi hi hi hi
该代码的注意点:使用seek()和tell()的时候,对于a方式打开的文件,动作依然是追加,不会因为seek到上文而在文中添加。做write操作的时候因为内容保存在内存中还未flush到硬盘的原因,在查看文件的时候会出现没有修改成功的假象
对于句柄权限的判断:writealbe(),readable()、seekable(),判断句柄是否可读、可写、可跳(seek)
print(f.seekable(),"如果句柄可跳回则打印true,如果不行则返回false,seekable") print(f.readable(),"如果句柄可读则打印true,如果不行则返回false,readable") print(f.writable(),"如果句柄可写则打印true,如果不行则返回false,writable")
硬盘实时刷新:flush()的使用,在我们对硬盘文件进行操作的过程中,我们操作的内容是保存在内存中的,系统按照一点的规律将内容在保存到硬盘,在一些对修改时效性要求比较高的场景下,我们要求将修改实时同步到硬盘。此时需要刷新硬盘,flush()
import sys
import time
for i in range(20): sys.stdout.write('#') #此处不是print sys.stdout.flush() time.sleep(0.2) print("100%")
----------------------------------------------
####################100%
此代码的说明:需要使用两个模块,sys和time。对比flush()和没有flush()的情况。没有flush()的时候,进度条是一口气输出的。
文档内列表字典列表的转换:eval(),我们可以将一个大型的列表、字典、字符串按照格式写在文件中。通过eval进行赋值,用以程序使用。
f_str=open('str_tmp') f_list=open('list_tmp') f_dic=open('dic_tmp') x=f_str.read().strip() y=f_list.read().strip() z=f_dic.read().strip() print(type(x),type(y),type(z)) #x=eval(x) y=eval(y) z=eval(z) print(x,y,z,type(x),type(y),type(z))
-------------------------------------------------------
<class 'str'> <class 'str'> <class 'str'>
we are ready ['a', 'b', 'c', 'd', 1, 2, 3, 4] {'1': {'1.1': '1.1.1'}, '2': {'2.2': '2.2.2'}, '3': {'3.3.': '3.3.3'}} <class 'str'> <class 'list'> <class 'dict'>
-----------------------------------------------------------
[root@VM_61_212_centos my_python_file]# cat list_tmp
['a','b','c','d',1,2,3,4]
[root@VM_61_212_centos my_python_file]# cat dic_tmp
{'1':{'1.1':'1.1.1'},'2':{'2.2':'2.2.2'},'3':{'3.3.':'3.3.3'}}
[root@VM_61_212_centos my_python_file]# cat list_tmp
['a','b','c','d',1,2,3,4]
本代码的注意点:代码注释部分,将str转为str会报错,因为本身就已经是str
4、 encoding='utf-8'的理解
[root@VM_61_212_centos my_python_file]# cat xxx.txt אτ [root@VM_61_212_centos my_python_file]# python3.6 Python 3.6.3 (default, Nov 14 2017, 15:55:17) >>> f=open('/root/myfile/my_python_file/xxx.txt',encoding='gbk') >>> print(f.encoding) gbk >>> x=f.read() >>> print(x) 中文 [root@VM_61_212_centos my_python_file]# cat tmp_1.py #!/bin/env python3.6 with open('xxx.txt',encoding='gbk') as f: x=f.read().strip() print(x,type(x)) with open('bbb','w',encoding='utf-8') as f: f.write(x) with open('ccc','w',encoding='gbk') as f: f.write(x) [root@VM_61_212_centos my_python_file]# cat xxx.txt אτ [root@VM_61_212_centos my_python_file]# cat bbb 中文 [root@VM_61_212_centos my_python_file]# cat ccc אτ
此代码的说明:
- xxx.txt是用windows写的一个gbk格式的文件,发送到linux中,使用cat打开后,由于xshell是utf-8格式,所以显示为乱码。此时可以调整xshell的显示格式,可以正常显示文字
- 使用python3.x打开此文件,encoding=gbk,用来告诉python此文件的格式以及需要把这个文件最后处理为什么格式
- 本代码中,将xxx.txt打开后,分别保存为utf-8以及gbk格式的文件bbb、ccc。在xshell中调整编码,分别cat来查看及验证。
二、函数的概念及使用
定义: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可
特性:
- 减少重复代码
- 使程序变的可扩展
- 使程序变得易维护
1、定义函数:def
import time
_custom=('%Y-%m-%d %X')
def func1(): x=time.strftime(_custom) time.sleep(1) print(x,'func1 is ok') def func2(): x=time.strftime(_custom) time.sleep(1) print(x,'func2 is ok') func1() func2()
-----------------------------------------------------
2017-12-06 20:38:28 func1 is ok
2017-12-06 20:38:29 func2 is ok
此代码的注意点:time.strftime()指令需要制定一个输出格式的模板,如果没有模板会报错,先记住%Y-%m-%d %X这种格式即可
2、函数返回值:5种情况:有一个返回值/无返回值/有一大串返回值/返回值为函数/返回值为函数运行结果。
import time def fun1(): return 1,'hello',[1,2,3,4,5],{'123':"666",'222':"hello"} def fun2(): return fun1 def fun3(): return fun2() #如果有括号则返回调用函数的函数值 def fun4(): time.sleep(0.1) x=fun1() y=fun2() z=fun3() i=fun4() print(x) print(y) print(z) print(i)
此代码的说明:func1为一大串返回值,则结果为一个元组、func2为返回一个函数,则返回这个函数在内存中的地址、func3返回值为函数的运行结果。func4无指定返回值故放回null、/3
3、函数的参数及传入
函数的参数有形参、实参、非固定参( *args *.kwargs) 及参数传入。
形参:定义函数时的占位替代,实参:实际传入函数中被使用的。默认参数(定义函数的时候写入,不赋值则保持默认)关键参数:赋值的另外一种形式 ,不按照顺序
*.args的使用:两种赋值方式,一种为直接写,一种为*[]或*()
def test1(x,y,*args): print(x,y) print(args) test1(1,2,3,4,5) test1('a','b','c','d',[1,2,3,4,5],[6,7],{'a1':'aa','b1':'xxx'})
test1('a','b','c','d',*[1,2,3,4,5],*(6,7),{'a1':'aa','b1':'xxx'})
--------------------------------------------------------------------
1 2
(3, 4, 5)
a b
('c', 'd', [1, 2, 3, 4, 5], [6, 7], {'a1': 'aa', 'b1': 'xxx'})
('c', 'd', 1, 2, 3, 4, 5, 6, 7, {'a1': 'aa', 'b1': 'xxx'})
此程序的注意点:*.argv在参数传入的时候会将参数转换为一个元组,参数可以是列表或字典。如果再列表和元组前面加上*,则元素会被单独提取出来
需要和sys.argv对比,sys.argv,sys.argv是将参数转换为列表
import sys x=sys.argv print(x) [root@VM_61_212_centos my_python_file]# ./tmp_1.py 1,2,3,4 ['./tmp_1.py', '1,2,3,4']
**kwagrs的使用:两种赋值方式,一种key=“value”一种**+字典,输入之后就是字典
def test1(**kwargs): print(kwargs) def test2(name,**kwarg2): print(name) print(kwarg2) def test3(name,age=18,**kwargs): print(name) print(age) print(kwargs) def test4(name,age=18,*args,**kwargs): print(name) print(age) print(args) print(kwargs) test1(name="yomi",age='123') test1(**{'name':'360yomi','age':"567"}) test2('tom',k1='hello',k2='world') test3('xxx',3,hobby='badminton',car='aodi') test3('yyy',hobby='football',car='tesla',age=66)#用关键字的形式来传递这个参数 test4('xiaoming',22,company='360') test4('xiaodong',52,1,2,3,4,5,company='qq',lang="ok")
----------------------------------------------------------------------------
{'name': 'yomi', 'age': '123'}
{'name': '360yomi', 'age': '567'}
tom
{'k1': 'hello', 'k2': 'world'}
xxx
3
{'hobby': 'badminton', 'car': 'aodi'}
yyy
66
{'hobby': 'football', 'car': 'tesla'}
xiaoming
22
()
{'company': '360'}
xiaodong
52
(1, 2, 3, 4, 5)
{'company': 'qq', 'lang': 'ok'}
4、局部变量与全局变量
- 全局变量,可以在函数中直接引用,不用传入
- 局部变量,在函数体内可以和全局变量同名,在函数体内生效
- 退出函数后,局部变量对全局变量的赋值不生效
- 函数内定义的局部变量,退出函数后不能使用
- 可以在函数中使用global来定义变量,则影响全局(包括新建变量)
- 不能将形参定义为global
- 大部分情况下,不要再函数中去更改全局变量的值
school = '北大' name = '马云' print('进入函数前的name和school:',name,school) def change_name(name): global school print('进入函数'.center(50,'*')) print('befor change',name,school) name = "马化腾" school ="清华" print('after change',name,school) global age age = 25 print('school:',school,'age:',age) print('退出函数'.center(50,'*')) change_name(name) print('退出函数后的name和school:',name,school,age)
-----------------------------------------------------------------------------------
进入函数前的name和school: 马云 北大
***********************进入函数***********************
befor change 马云 北大
after change 马化腾 清华
school: 清华 age: 25
***********************退出函数***********************
退出函数后的name和school: 马云 清华 25对于字典和列表的局部操作:
a=[1,2,3,4,5] b='kkk' c={1:'aaa',2:'bbb'} def myprint(): global b b=b.replace('k','q') #不能再函数内对全局变量本身进行改变,除非用globe a[1]=6 c[1]='good' print('befor change:') print(b,a,c) print('after change:') myprint() print(b,a,c)
-----------------------------------------------------------
befor change:
kkk [1, 2, 3, 4, 5] {1: 'aaa', 2: 'bbb'}
after change:
qqq [1, 6, 3, 4, 5] {1: 'good', 2: 'bbb'
此代码的注意点:在函数内,我们可以通过下标或关键字的方式去给列表和字典进行修改,能作用到全局,但是,如果是进行新建,则不会作用到全局,此处应和浅copy机制相结合,深入理解python中变量在内存中的形式。对比下面的代码
a=[1,2,3,4,5] b='kkk' c={1:'aaa',2:'bbb'} def myprint(): b='xxxooo' a=[8988,891823,122] c={1:'xxx',2:'ooo'} print(b,a,c) myprint() print(b,a,c) --------------------------------------------------------- xxxooo [8988, 891823, 122] {1: 'xxx', 2: 'ooo'} kkk [1, 2, 3, 4, 5] {1: 'aaa', 2: 'bbb'}
5、函数的嵌套与递归
在函数内部,可以调用其他函数,这种方式叫函数的嵌套,如果一个函数在内部调用自身本身,这个函数就是递归函数。
def digui(n): print(n,'准备执行digui(%s)'%int(n/2)) if n > 0: return (digui(int(n/2))) print('--> ok!') def digui1(n): print(n) if n > 0: return (int (n/2)) #----->直接返回值函数退出 不打印 print('--> ok!') x=10 digui(x) digui1(x)
-------------------------------------------------
10 准备执行digui(5)
5 准备执行digui(2)
2 准备执行digui(1)
1 准备执行digui(0)
0 准备执行digui(0)
--> ok!
10
此代码的注意点:函数在有明确的返回值后,就不会再进行下一步操作。 如图中标记的print ok,为什么没有被打印出来。
6、高阶函数
高阶函数->使主函数本身很简洁
变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
def double_x(a): i=a*2 return i def gaojie(x,y,z): result = z(x)+z(y) print(result) gaojie(100,200,double_x)#此处double_x不用加()
-------------------------------------------------------
600
三、补充一点:字体颜色的操作
语法:print("\033[31;1m余额不足,当前余额为%s\033[0m"%(salary))
\33[0m 关闭所有属性
\33[1m 设置高亮度
\33[4m 下划线
\33[5m 闪烁
\33[7m 反显
\33[8m 消隐
\33[30m -- \33[37m 设置前景色
字颜色:30-----------37
30:黑
31:红
32:绿
33:黄
34:蓝色
35:紫色
36:深绿
37:白色
\33[40m -- \33[47m 设置背景色
字背景颜色范围:40----47
40:黑
41:深红
42:绿
43:黄色
44:蓝色
45:紫色
46:深绿
47:白色
\33[90m -- \33[97m 黑底彩色
90:黑
91:深红
92:绿
93:黄色
94:蓝色
95:紫色
96:深绿
97:白色