python递归、collections系列以及文件操作进阶

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
            }
        }

需求
上文件操作方式练习作业--结合Flag标志位极好的例子--需求

递归:

(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:在读的时候,将" "转为" ",U只能和r一起使用;

>>> obj = open('log','r')
>>> obj.read()
'test123
'
>>> obj.close()
>>> obj = open('log','r+U')
>>> obj.read()
'test123
'

obj.tell():返回文件读写位置的指针;

obj.read():将文件内容读到一个字符串当中;

obj.truncate():从指针指向的位置开始截断数据,保留前面的,丢弃后面的,在r+(读写)的时候用这种方法丢掉原来的数据;

rb/wb/ab:如果是跨平台的话,使用二进制;

操作文件:

     f.next()    #一次读一行

>>> seq = ["This is frist line
","This is second line"]
>>> obj.writelines(seq)    #写入多行
>>> obj.close()

   f.write():一次只写一行

with管理文件操作:

>>> with open('log','r') as f:    #打开时候无需关闭
...      f.read()
... 
'This is frist line
This 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)

 作业来了。。。

##############配置文件################
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
            }
        }

需求
修改配置文件练习--结合上述操作+Flag实现
#!/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,'
'))
        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
" %(" "*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
" %record)
                            else:
                                f_new.write("%s %s
" %(" "*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 "33[32m你需要删除的backend记录不存在33[0m"
    else:
        Backend_List.insert(0,BackTitle)
        print BackBody
        if BackBody in Backend_List:
            Backend_List.remove(BackBody)
            print "删除指定内容"
        else:
            print "33[32m你需要删除的backend记录不存在33[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
" %record)
                            else:
                                f_new.write("%s %s
" %(" "*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 "33[31m你输入的数字是无效的33[0m"
demo
原文地址:https://www.cnblogs.com/cqq-20151202/p/5058813.html