• 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
  • 相关阅读:
    Delphi中DLL初始化和退出处理
    03003_Http响应
    雷林鹏分享:CSS 属性 选择器
    雷林鹏分享:CSS 媒体类型
    雷林鹏分享:CSS 图像拼合技术
    雷林鹏分享:CSS 图像透明/不透明
    雷林鹏分享:CSS 图片廊
    雷林鹏分享:CSS 提示工具(Tooltip)
    雷林鹏分享:CSS 下拉菜单
    雷林鹏分享:CSS 导航栏
  • 原文地址:https://www.cnblogs.com/cqq-20151202/p/5058813.html
Copyright © 2020-2023  润新知