Python自动化运维 - day3 - 文件处理 - 函数part1
文件处理
1、读取文件
f = file('/etc/passwd','r') ----> Python 3.x 里面没有file,统一用open for line in f.readlines(): line = line.strip('\n').split(':') print line
结果:
['root', 'x', '0', '0', 'root', '/root', '/bin/bash'] ['bin', 'x', '1', '1', 'bin', '/bin', '/sbin/nologin']
以指定编码格式打开文件:
f = open('/etc/password',encoding = 'UTF-8')
我们把这个 f 成为文件句柄(用来标识一个文件的内存对象),包含文件名,字符集,大小,硬盘上的起始位置等等。
f在这里就变成了一个文件迭代器,我们可以通过使用for line in f ,去循环的读取文件的每一行内容
2、文件方法
r:只读打开
w:只写模式打开(不能读) 如果选择这个模式打开,那么在执行write的时候,会覆盖源文件(非追加)
a:只追加模式打开(不能读)
r+: 读写模式(写是追加) --->常用
a+: 追加读写
w+:写读模式(写同样是追加) ---->不常用
rb:二进制读模式(一般用来做网络传输数据的时候,因为网络传输都是基于二进制格式的,所以必须用b) python 2.x 是可以用str传输的
r+b:以二进制读写模式打开
w+b:以二进制写读模式打开
a+b:以二进制追加及读模式打开
b:使用二进制模式(适合在windows上使用,例如windows上的回车符和Linux不同)
注:
U:表示在读取的时候,可以将‘\r\n’ 转换成 \n (与r或r+模式连用)这样的好处是方便windows上到Linux的使用
因为回车符在windows上表示为\r\n 而Linux上 表示为\n
二进制只是一个文件的编码格式,并不带表文件的内容都是01010。所以我们一个str类型的文件也是可以当成二进制文件来处理的,只不过我们把str写入文件的时候需要转换成二进制格式,才能写入:
f = open('test.txt','rb') f.write('你好'.encoding())
通过encoding就可以转换成二进制
3、文件对象方法
fd.closed():判断文件是否被关闭,若被打开提示False,没有的话提示True
fd.flush():把修改的内容,强制刷新到文件中去
fd.isatty:判断是否是一个终端文件
fd.mode:查看文件的打开模式
fd.name:查看文件的名称
fd.next:迭代的方法,和readline很像,区别是,next读到末尾会报错,readline会继续返回空
fd.read:一次性读取所有内容,以字符串的方式存取
fd.readable():判断文件是否可读
fd.readlines:一次性读取所有内容,以列表的方式存取(适合操作小文件)
fd.readline():每次读取一行内容
fd.seek(0):调整文件读取的指针位置
fd.seekable():判断文件是否可以调整指针位置(tty,磁盘等文件是不能被seek的),可以被seek则返回真,否则返回假 --Python3.x
fd.tell():查询文件目前读取位置(以字符为单位)
fd.truncate():截取文件,从开头开始截取,不指定指针位置的话,那么会清空文件
fd.write:把一个字符串写入到文件中去
fd.writelines():把字符串列表写入文件中
fd.xreadlines():读一行打印一行,针对大文件非常适用 -----> Python 2.x 中适用,3.x中已经取消
fd.encoding:查看文件的编码
fd.writeable():判断文件是否可以写
fd.fileno(): 返回文件在操作系统上的文件描述符(默认会打开三个:0表示 stdin、1表示 stdout,2表示stderr)
fd.name:打印文件名称
函数
面向过程和函数式编程的最主要的区别是,过程是没有返回值的函数,Python中给过程隐士的定义了返回值为none,所以过程和函数式在Python中没什么区别
函数的定义:
def fun(arg,*args,**kargs) pass
参数:
arg,函数可以有参数也可以没有
传递参数:
1、关键字调用(无序的)
2、位置参数调用(有序的)
3、二者混用,关键字调用必须放在参数列表的末尾(关键字参数不能放在位置参数前)
默认参数:
def func(arg = 'value'),表示如果arg没有传值,那么它默认等于values,如果对某个参数设定了默须放在参数列表中的最后。
特点:调用参数的时候非默认传递,可以根据默认值来预先编写函数逻辑
注意:默认参数最好指向不变的对象
对默认参数进行赋值的时候,可以用位置参数进行赋值,也可以用关键则参数进行赋值
可变参数(参数组):
*args:表示参数可能是多个的,函数内部使用元祖tuple来存储这些参数
关键字参数:
**kargs:也表示参数是多个的,只是函数内部使用dict来存储这些参数,适用于var = value(关键字)的方式传值!
主要区别:
1、*args接受的是N个位置参数,用元祖存储
2、**kwargs接受的是N个关键字参数,用字典存储
注意:
1、当函数接受可变参数的时候,如果我们刚好有一个list 或者tuple,可以直接在前面加上*,把元素变成可变参数进行传递
a = [1,2,3]
test(*a)
2、如果已有字典要传递给函数的话,可以在传递的时候加上**,把字典的key,value变成关键字参数进行传递
3、三个参数的位置不能调换,若同时存在arg,*argv,**kargv,必须先给arg赋值(除非它有默认值),然后才能给*argv和**kargv赋值。
命名关键字参数:
我们可以指定命名关键字参数进行传递,如果传如的关键字参数没有包含命名关键字参数,那么将会报错。
如果函数有可变参数,那么可以在后面直接定义命名关键字参数,如果函数只有位置参数,那么命名关键字参数之前就需要添加*,来隔开,表示后面的为命名关键字参数
def func(name,age,*,city,job): print(name,age,city,job) >>> func('daxin',22,city='beijing',job='linux') daxin 22 beijing linux
这里可以指定命名关键字的默认值
注意:
参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数
返回值:
return var,在函数的内部把某个结果进行返回,return之后直接跳出函数。
返回值数量=0,返回None。
返回值数量=1,返回object。
返回值数量>1,返回tuple。
例子:
def test(arg,*argv,**kargv): print arg print argv print kargv test('1','2','3',a='4',b='5')
结果:
1 ('2', '3') {'a': '4', 'b': '5'}
直接传递字典进去是不行的,也是需要在字典变量前加**,列表相同
局部变量:
在函数内定义的变量,只在函数里生效,那么该函数就是该变量的作用域
全局变量:
在程序中定义的变量,在程序内全局生效。
函数内是无法修改全局变量的值的,如果非要修改,那么就需要在函数内声明变量为全局变量的值
global varname --->一般是不用的
注意:
函数内是无法修改字符串、数值类型的变量的。但是可以修改字典,列表,集合,类的变量的值!
三元运算符和lambda表达式
正常情况下:
if 1 > 3: print 'lt' else: print 'gt'
运用三元运算符:(三目运算符)
print 'lt' if 1>3 else 'gt'
lambda表达式:
又叫匿名函数
tem = lambda x,y:x+y print tem(2,3) 等于: def tem(x,y): return x+y print tem(2,3)
一般用在函数逻辑比较简单,在程序内基本不会重复调用的函数,节省代码量
递归:
在函数内部,可以调用其他函数.如果一个桉树在内部调用自己本身,那么这个函数就是递归函数.
递推特性:
1、递归必须要有一个明确的条件
2、每次进入更深一层的调用时,问题规模相比上一次递归应该有所减少
比如:数字是依次递减,列表的元素依次减少等等。
3、递归效率不高,递归曾测多会导致栈溢出(在计算机中,函数调用是通过栈这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限大的,所以递归调用次数过多,会导致栈溢出)
例子:
def calc_division(n): 'this func user for n devision 2' print(n) if int(n/2) > 0: return calc_division(int(n/2)) print('-->',n) calc_division(20)
Python中的排序分为原地排序和复制排序。
- 原地排序(in place sort) 指按照指定的方式排列数据,然后用排序后的数据替换原有数据
- 复制排序(copied sort)指按你指定的方式排列数据,然后返回一个源数据的有序副本,源数据的顺序依然保留
- 原地排序使用对象的sort()方法
- 复制排序使用内置BIF sorted()
- 默认都是正序,倒序的话可以添加reverse=True
原地排序:
>>> a =[2,3,6,9,43,6,98,4,8] >>> a.sort() >>> a [2, 3, 4, 6, 6, 8, 9, 43, 98] >>> a.sort(reverse=True) >>> a [98, 43, 9, 8, 6, 6, 4, 3, 2] >>> sorted(a,reverse=True) [98, 43, 9, 8, 6, 6, 4, 3, 2]
复制排序:
>>> b = [7,45,8,3,5,7,9,0,5,7] >>> sorted(b) [0, 3, 5, 5, 7, 7, 7, 8, 9, 45] >>> b [7, 45, 8, 3, 5, 7, 9, 0, 5, 7]
去重:
对一个列表进行去重其实有很多方法: >>> d = ['a','b','a','c'] >>> e=[] >>> for i in d: if i not in e: e.append(i) >>> e ['a', 'b', 'c'] 这里可以利用一种特殊的数据类型集合。集合是无序的并且元素是唯一的 >>> d ['a', 'b', 'a', 'c'] >>> set(d) {'b', 'a', 'c'}
字符编码
计算机里面,编码方法有很多种,英文的一般用ascii,而中文有unicode,utf-8,gbk等等。unicode是 utf-8,gbk等这些的父编码,这些子编码都能转换成unicode编码,然后转化成子编码,例如utf8可以转成unicode,再转gbk,但不能直接从utf8转gbk,需要有一个中间过程
所以,python中就有两个方法用来解码(decode)与编码(encode),解码是子编码转unicode,编码就是unicode转子编码
1.编码
a = '你好'
print(a.encode('gbk'))
print(a.encode('utf-8'))
这里使用Python 3, 所以a的默认编码类型为unicode
输出的结果为:
b'\xc4\xe3\xba\xc3'
b'\xe4\xbd\xa0\xe5\xa5\xbd'
2.解码
a = '你好'
print(a.encode('gbk').decode('gbk'))
print(a.encode('utf-8'))
这里a为unicode编码,decode方法将gbk的bytes格式的数据转换为unicode编码
输出结果:
你好
b'\xe4\xbd\xa0\xe5\xa5\xbd'
因为a是unicode编码的,如果对a进行解码,那就会报错,没有decode方法
AttributeError: 'str' object has no attribute 'decode'
3、文件加载过程
1、程序向系统发送调用命令
2、系统切换到内核态从磁盘(bytes格式)加载到内存中(unicode格式),这里就有一个编码(decode)的过程,既 bytes(utf-8) -> unicode
3、python解释器读取内存中的unicode编码的文件,如果python解释器指定了编码集为UTF-8,那么就会产生一个解码(encode)的过程,既unicode -> utf-8
4、python 3中的字符串存储格式是unicode,python 2 中的 bytes格式
5、python3 默认支持中文,python不支持
所有巧合的是要么是上天注定要么是一个人偷偷的在努力。