python递归、collections系列以及文件操作进阶
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
global log 127.0.0.1 local2 daemon maxconn 256 log 127.0.0.1 local2 info defaults log global mode http timeout connect 5000ms timeout client 50000ms timeout server 50000ms option dontlognull listen stats :8888 stats enable stats uri /admin stats auth admin:1234 frontend oldboy.org bind 0.0.0.0:80 option httplog option httpclose option forwardfor log global acl www hdr_reg(host) -i www.oldboy.org use_backend www.oldboy.org if www backend www.oldboy.org server 100.1.7.9 100.1.7.9 weight 20 maxconn 30 ######################################## 配置文件增删查 1、查 输入:www.oldboy.org 获取当前backend下的所有记录 2、新建 输入: arg = { 'bakend': 'www.oldboy.org', 'record':{ 'server': '100.1.7.9', 'weight': 20, 'maxconn': 30 } } 3、删除 输入: arg = { 'bakend': 'www.oldboy.org', 'record':{ 'server': '100.1.7.9', 'weight': 20, 'maxconn': 30 } } 需求
递归:
(1)递归就是在过程或函数里调用自身;
(2)在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。
在python中如果函数没有return,就会return为None
def func(arg1,arg2): if arg1 == 0: print arg1,arg2 arg3 = arg1 + arg2 if arg3 > 1000: return arg3 else: func(arg2,arg3) result = func(0,1) print result 结果为: 0 1 None
正确地递归函数为:
def func(arg1,arg2): if arg1 == 0: print arg1,arg2 arg3 = arg1 + arg2 if arg3 > 1000: return arg3 return func(arg2,arg3) result = func(0,1) print result
计算器作业思路:
循环:递归
将括号中的内容计算出来之后依次递归
练习题1:将列表[11,22,33,44,55,66,77,88,99]大于66的值放入第一个key中,将小于66的值放入字典第二个key中;
#!/usr/bin/env python # _*_ coding:utf-8 _*_ num_list = [11,22,33,44,55,66,77,88,99] dict_list = {'k1':[], 'k2':[], } for item in num_list: if item <=60: dict_list['k1'].append(item) else: dict_list['k2'].append(item) print dict_list
练习题2:上题中,如果字典中没有key值如何处理(只有空字典)
#!/usr/bin/env python # _*_ coding:utf-8 _*_ num_list = [11,22,33,44,55,66,77,88,99] dict_list ={} for item in num_list: if item <=60: if 'k1' in dict_list.keys(): dict_list['k1'].append(item) else: dict_list['k1'] = [item,] #统一一下规范,都加逗号 else: if 'k2' in dict_list.keys(): dict_list['k2'].append(item) else: dict_list['k2']=[item,] print dict_list
练习题3:将文本内容alex|123|1
eric|123|1
tony|123|1放入字典中,第一个名字为key
#!/usr/bin/env python # _*_ coding:utf-8 _*_ f = file(r'log','r') line_list = f.readlines() f.colse() dic = {} for line in line_list: line = line.strip().split('|') dic[line[0]]=line[1:] print dic
一、Collections系列
1、collections系列之计数器
>>> import collections
>>> c1=collections.Counter('abcd') #计数器,对象为字符串或列表
>>> c1
Counter({'a': 1, 'c': 1, 'b': 1, 'd': 1})
>>> c1=collections.Counter([11,22,33,11])
>>> c1
Counter({11: 2, 33: 1, 22: 1})
>>> c1=collections.Counter('abcd')
>>> c1
Counter({'a': 1, 'c': 1, 'b': 1, 'd': 1})
>>> c2=collections.Counter('abc')
>>> c2
Counter({'a': 1, 'c': 1, 'b': 1})
>>> c1.update(c2) #元素个数叠加
>>> c1
Counter({'a': 2, 'c': 2, 'b': 2, 'd': 1})
>>> c1.clear() #清除内容
>>> c1
Counter()
>>> c1
Counter({'a': 1, 'c': 1, 'b': 1, 'd': 1}) #将前n个k,v值当做元组放入列表中
>>> c1.most_common(2)
[('a', 1), ('c', 1)]
>>> c1.elements() #类似于xreadlines(),是一个迭代器,只有循环时才可以显示出来
<itertools.chain object at 0x92697cc>
2、collections之有序字典(与字典用法相同)
>>> o1=collections.OrderedDict() #创建有序字典,区别是内部维护一个列表,列表是有序的
>>> o1
OrderedDict()
>>> o1['k1']=1
>>> o1
OrderedDict([('k1', 1)])
3、默认字典(defaultdict):为字典里的value设置默认类型
字典value的默认类型为None,即为
>>> dic = {'k1':None} #None没有append方法
>>> dic
{'k1': None}
1 >>> import collections 2 >>> 3 >>> dic = collections.defaultdict(list) #定义字典,并将value值设为list 4 >>> dic['k1'] 5 [] 6 >>> dic['k1'].append(1)
4、collections之命名元组----->创建类
一般是:创建类--->使用类创建对象--->使用对象
对于现有的类:直接使用类创建对象--->使用对象
对于元组而言,访问元组对象中的元素,必须使用下标才行,那么如何才能不需要下标来取值呢?
#创建一个扩展的tuple类 >>> Mytuple = collections.namedtuple('Mytuple',['x','y']) >>> new = Mytuple(1,2) #实例化 >>> new Mytuple(x=1, y=2) >>> new.x #通过该方法访问值 1 >>> new.y 2
5、collections之双向队列(deque)-----线程安全
>>> q = collections.deque() #创建队列 >>> q.append(1) #将1添加到队列中 >>> q.append(2) >>> q.append(4) >>> q deque([1, 2, 4]) >>> q.pop() #删除(从右边开始) 4 >>> q.popleft() #从左边删除 1
除了deque,其他python标准模块也提供队列机制,queue,mutiprocessing,asyncio,heapq;
6、单向队列(Queue)-----线程安全
>>> import Queue >>> q=Queue.Queue(10) #创建队列,放10个元素 >>> >>> q.put(1) #往队列中添加数据 >>> q.put(2) >>> q.put(3) >>> q.put(4) >>> q <Queue.Queue instance at 0xa3cbc8c> >>> q.get() #从队列中往出拿数据,相当于pop 1 队列与与栈如何区别: 队列:FIFO 栈:弹夹
7、迭代器和生成器原理
>>> xrange(10):创建时不会在内存中创建对象,只有在循环时才会创建
在数据库创建连接池时,为节省资源,用生成器创建。
8、下标式循环以及冒泡算法
如何将a、b的值互换:
>>> a = 123 >>> b = 321 >>> >>> temp = a >>> a = b >>> b = temp >>> a 321 >>> b 123
下标式循环:
>>> for m in range(len(li)-1): ... print li[m], ... 22 6 99 11
冒泡算法:
>>> li = [13,22,6,99,11] >>> for m in range(len(li)-1): ... for n in range(m,len(li)-1): ... if li[m] > li[n]: ... temp = li[m] ... li[m] = li[n] ... li[n] =temp ... >>> li [6, 13, 22, 99, 11]
9、内置函数
函数的分类:内置函数、自定义函数、导入函数
>>> print vars() #内置函数,拿到当前模块中的所有变量 {'temp': 22, '__builtins__': <module '__builtin__' (built-in)>, 'm': 3, 'li': [6, 13, 22, 99, 11], 'n': 3, 'tab': <module 'tab' from '/usr/lib/python2.7/dist-packages/tab.pyc'>, '__name__': '__main__', '__package__': None, '__doc__': None}
其中:
__file__:文件路径
__doc__:注释
__name__:被执行的文件被赋值为__main__
内存级别函数:
reload:被reload的模块之前必须被import过,一般在被reload的模块内容改变之后使用;
id
is:内存地址相同
计算级别:
cmp(2,3)
abs()
bool()
divmod(10,3)分页
max()
min()
sum()
pow(2,11):2的11次方
all和any:all()接受一个序列,判断所有值为真,返回真,在输入用户名和密码的时候,一次性输入,可以判断输入的是否有空值;
enumerate
>>> for k,v in enumerate([11,22,33,44,55],1): #遍历下标和列表,序号从1开始 ... print k,v ... 1 11 2 22 3 33 4 44 5 55
10、函数式编程和面向对象编程
11、函数式编程之发邮件
#!/usr/bin/env python # _*_ coding:utf-8 _*_ import smtplib from email.mime.text import MIMEText from email.utils import formataddr def email(message): msg = MIMEText(message,'plain','utf-8') msg['From'] = formataddr(["Charles",'qq_c123@163.com']) #源 msg['To'] = formataddr(["走人",'1812352106@qq.com']) #目标 msg['Subject'] = "主题" server = smtplib.SMTP("smtp.163.com",25) server.login("qq_c123@163.com","sXXXXXX") server.sendmail("qq_c123@163.com",['1812352106@qq.com',],msg.as_string()) server.quit() if __name__ == '__main__': cpu = 100 disk = 500 raw = 50 for i in range(1): if cpu > 90: alert='CPU有告警' email(alert) if disk > 90: alert = '磁盘有告警' email(alert) if raw > 90: alert = 'raw有告警' email(alert)
#!/usr/bin/env python # _*_ coding:utf-8 _*_ import smtplib from email.mime.text import MIMEText from email.utils import formataddr def email(message,receiver): msg = MIMEText(message,'plain','utf-8') msg['From'] = formataddr(["常强强",'qq_c123@163.com']) msg['To'] = formataddr(["走人",'1812352106@qq.com']) msg['Subject'] = "主题" server = smtplib.SMTP("smtp.163.com",25) server.login("qq_c123@163.com","start33333") server.sendmail("qq_c123@163.com",[receiver,],msg.as_string()) #发送邮件到多个 server.quit() li = ["qq_c123@163.com","alex111@126.com"] for item in li: emali("cpu报警",item) if __name__ == '__main__': cpu = 100 disk = 500 raw = 50 for i in range(1): if cpu > 90: alert='CPU有告警' email(alert) if disk > 90: alert = '磁盘有告警' email(alert) if raw > 90: alert = 'raw有告警' email(alert)
函数的返回值:
a、如果函数没有返回值,那么返回值就为None;
b、函数返回值可以复制给某个变量
12、函数的参数
a、普通参数:定义了几个形参,就要传几个实参;
b、默认参数:默认参数放在形参的最后;
c、动态参数:def func(*args):接受多个参数
def func(**kwargs):有两种传值方式
第一种:
>>> func(k1=123) {'k1': 123}
第二种:
>>> dic = {'k1':123}
>>> func(**dic) {'k1': 123}
函数 def func(*args,**kwargs):可以接受实参为列表和字典
13、文件操作
打开操作:
r:打开文件,指针在最前面
w:将原来的内容清空掉,然后重写,指针在最前面
a:可读、可写(以追加的方式写),指针在最后
+:只有r+(读写)有意义,指针放在开头,新写入的数据会依次替代原来的数据,没有替代的继续保留;
r+U:在读的时候,将"\r\n"转为"\n",U只能和r一起使用;
>>> obj = open('log','r') >>> obj.read() 'test123\r\n' >>> obj.close() >>> obj = open('log','r+U') >>> obj.read() 'test123\n'
obj.tell():返回文件读写位置的指针;
obj.read():将文件内容读到一个字符串当中;
obj.truncate():从指针指向的位置开始截断数据,保留前面的,丢弃后面的,在r+(读写)的时候用这种方法丢掉原来的数据;
rb/wb/ab:如果是跨平台的话,使用二进制;
操作文件:
f.next() #一次读一行
>>> seq = ["This is frist line\n","This is second line"] >>> obj.writelines(seq) #写入多行 >>> obj.close()
f.write():一次只写一行
with管理文件操作:
>>> with open('log','r') as f: #打开时候无需关闭 ... f.read() ... 'This is frist line\nThis is second line'
利用上述方法操作配置文件:(只有在2.7以上版本才支持)
>>> with open('log','r') as obj1, open('log1','w') as obj2: ... for line in obj1: ... new_line = line.replace('This is frist line','wahaha') ... obj2.write(new_line)
作业来了。。。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
##############配置文件################ global log 127.0.0.1 local2 daemon maxconn 256 log 127.0.0.1 local2 info defaults log global mode http timeout connect 5000ms timeout client 50000ms timeout server 50000ms option dontlognull listen stats :8888 stats enable stats uri /admin stats auth admin:1234 frontend oldboy.org bind 0.0.0.0:80 option httplog option httpclose option forwardfor log global acl www hdr_reg(host) -i www.oldboy.org use_backend www.oldboy.org if www backend www.oldboy.org server 100.1.7.9 100.1.7.9 weight 20 maxconn 30 ##############需求################ 增删查 1、查 输入:www.oldboy.org 获取当前backend下的所有记录 2、新建 输入: arg = { 'bakend': 'www.oldboy.org', 'record':{ 'server': '100.1.7.9', 'weight': 20, 'maxconn': 30 } } 3、删除 输入: arg = { 'bakend': 'www.oldboy.org', 'record':{ 'server': '100.1.7.9', 'weight': 20, 'maxconn': 30 } } 需求
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!/usr/bin/env python # _*_ coding:utf-8 _*_ import time import os import json OldFile="haproxy" #源文件 Bak_File="haproxy%s"%(time.strftime('%y-%m-%d-%H-%M-%S')) #备份文件 def Check(arg): '''通过设置标签Flag位,将需要检查的内容append到列表中,最后返回''' Backend_List = [] Flag = False with open(OldFile,'rb') as f: for line in f.xreadlines(): if line.strip().startswith('backend') and line.strip().split()[-1] == str(arg): Flag = True continue #检查到包含backend www.oldboy.org行时,直接中断循环,进入下一行 if Flag and line.strip().startswith('backend'): '''server 100.1.7.9 100.1.7.9 weight 20 maxconn 30的一行或者多行结束,设置Flag为False''' Flag = False if Flag and line: '''当Flag为True时,内容添加到列表中''' Backend_List.append(line.strip()) return Backend_List #print Check('www.oldboy.org') def Add(arg): '''分为两种情况:一种是不存在对应的backend,此时只需要将backend和对应的record先写入列表中,然后循环列表,追加到新的文件中 另一种情况是存在对应的backend,此时需要将原有的backend和record和新需要增加的record全部先写入列表中,然后通过循环列表写入到新的文件中''' Add_dict = json.loads(arg) BackTitle = "backend %s" %(str(Add_dict['backend'])) BackBody = 'server %s %s weight %d maxconn %d' %(Add_dict['record']['server'],Add_dict['record']['server'], Add_dict['record']['weight'],Add_dict['record']['maxconn'],) Backend_List = Check(Add_dict["backend"]) if not Backend_List: print "不存在对应的backend" Backend_List.append('%s%s'%(BackTitle,'\n')) Backend_List.append(BackBody) with open(OldFile,'rb') as f_old,open('ha_new','ab') as f_new: for line in f_old.readlines(): f_new.write(line) for line in Backend_List: if line.strip().startswith('backend'): f_new.write("%s" %line) else: f_new.write("%s %s\n" %(" "*6,line)) else: print "存在对应的backend" with open(OldFile,'rb') as f_old,open('ha_new','ab') as f_new: Flag = False Has_Write = False Backend_List.insert(0,'%s'%(BackTitle,)) if BackBody not in Backend_List: Backend_List.append(BackBody) print Backend_List for line in f_old.readlines(): if line.strip().startswith('backend') and line.strip().endswith(Add_dict['backend']): Flag = True continue if Flag and line.strip().startswith('backend'): Flag = False if not Flag: f_new.write(line) else: if not Has_Write: print Backend_List for record in Backend_List: if record.strip().startswith('backend'): f_new.write("%s\n" %record) else: f_new.write("%s %s\n" %(" "*6,record)) Has_Write = True #必须设置,否则会重复添加内容 #os.rename(OldFile,Bak_File) #os.rename('ha_new',OldFile) arg = '{"backend": "www.oldboy.org","record":{"server": "100.1.7.9","weight": 20,"maxconn": 30}}' Add(arg) def Delete(arg): '''删除的思路和上面的相同''' '''arg = { 'bakend': 'www.oldboy.org', 'record':{ 'server': '100.1.7.9', 'weight': 20, 'maxconn': 30 } }''' Add_dict = json.loads(arg) BackTitle = "backend %s" %(str(Add_dict['backend'])) BackBody = 'server %s %s weight %d maxconn %d' %(Add_dict['record']['server'],Add_dict['record']['server'], Add_dict['record']['weight'],Add_dict['record']['maxconn'],) Backend_List = Check(Add_dict['backend']) print Backend_List if not Backend_List: print "\033[32m你需要删除的backend记录不存在\033[0m" else: Backend_List.insert(0,BackTitle) print BackBody if BackBody in Backend_List: Backend_List.remove(BackBody) print "删除指定内容" else: print "\033[32m你需要删除的backend记录不存在\033[0m" print Backend_List with open(OldFile,'rb') as f_old,open('ha_new','ab') as f_new: Flag = False Has_Write = False for line in f_old.readlines(): if line.strip().startswith('backend') and line.strip().endswith(Add_dict['backend']): Flag = True continue if Flag and line.strip().startswith('backend'): Flag = False if not Flag: f_new.write(line) else: if not Has_Write: for record in Backend_List: if record.strip().startswith('backend'): f_new.write("%s\n" %record) else: f_new.write("%s %s\n" %(" "*6,record)) Has_Write = True #Delete(arg) if __name__ == '__main__': print """你想要执行如下哪个操作: 1、查看 2、增加 3、删除 """ Chose_Num = int(raw_input("请输入你数字:")) arg = '{"backend": "www.oldboy.org","record":{"server": "100.1.7.9","weight": 20,"maxconn": 30}}' if Chose_Num == 1: print Check('www.oldboy.org') elif Chose_Num == 2: Add(arg) elif Chose_Num ==3: Delete(arg) else: print "\033[31m你输入的数字是无效的\033[0m"