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:白色

 

 

 

 

posted @ 2017-12-06 23:42  yomi_note  阅读(279)  评论(0编辑  收藏  举报