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不支持

posted @ 2017-05-19 21:55  SpeicalLife  阅读(253)  评论(0编辑  收藏  举报