zoukankan      html  css  js  c++  java
  • Python学习笔记第三周

    目录

    一、基础概念

      1、集合

        集合方法

        a、设置集合

        b、取交集

        c、取并集

        d、取差集

        e、判断子集

        f、判断父集

        g、对称差集

        基本操作:

        a、添加

        b、删除

        c、discard删除

        d、长度

        e、成员判断

        f、拷贝

      2、文件操作

        1、操作类型方法

          1)读模式

          2)写模式

          3)追加模式

        2、读模式相关操作

          1)read操作

          2)readline操作

          3)readlines操作

          4)close操作

          5)文件编码格式

          6)正确的文件读取方式

          7)tell和seek方法介绍

        3、文件其他操作

          1)encoding

          2)fino()

          3)isatty()

          4)name打印文件名称

          5)seeekable()

          6)flush()

            例子:打印进度条

          7)colsed判断文件是否关闭

          8)truncate()

        4、修改文件

          1、文件全部读到内存中修改

          2、将文件按照行模式读,然后每行操作完毕后放入新文件,节约内存

          更常用文件操作:

          1)r+读写模式

          2)w+写读模式

          3)a+追加读模式

        5、二进制文件

        二进制文件两种方式,rb与wb

          1、网络传输

          2、视频文件打开

        6、with语句

    3、字符编码与转码

    4、函数

      1、编程方式

      2、定义函数

      3、定义过程

      4、调用函数与调用过程,查看返回值

      5、使用函数的好处

      6、函数的返回值

      7、形参与实参

      8、默认参数

      9、参数组

      10、局部变量与全局变量

      11、递归

      12、高阶函数

    二、作业

      1、作业一:实现类似sed的替换操作

      2、对一个haproxy文件查找、删除、添加操作

    内容

    一、基础概念

    1、集合:

    集合是一个无序的、不重复的数据组,它的作用:

    1)、去重复、把一个列表变成集合,就会自动去重

    2)、关系测试,测试两组数据之间的交集、差集、并集等关系

      集合的方法:

        a、设置集合

    >>> list_1 = [1,3,5,6,77,3,12]   #列表1
    >>> list_2 = [1,3,88,4,33,77]  #列表2
    >>> list_1 = set(list_1)  #通过set方法可以将列表变为集合
    >>> list_1
    {1, 3, 5, 6, 12, 77}  #集合list_1现在已经去重
    >>> list_2 = set(list_2)
    >>> list_2
    {1, 33, 3, 4, 77, 88}
    >>>print(list_1,type(list_1)) #打印list_1类型,发现为set类型,证明为集合

    {1, 3, 5, 6, 12, 77} <class 'set'>

        

        b、取交集 intersection(list_1  list_2共有的元素)

    >>> list_1.intersection(list_2)     
    {1, 3, 77}
    >>> print(list_1  & list_2)
    {1, 3, 77}
    #上述两种方法均可以取出list_1与list_2的交集

        c、取并集union(list_1 与list_2中全部去重元素)

    >>> list_1.union(list_2)                  
    {1, 33, 3, 4, 5, 6, 12, 77, 88}
    >>> list_1  | list_2
    {1, 33, 3, 4, 5, 6, 12, 77, 88}
    #上述两种方法取两个集合的全部去重元素

        d、取差集(差集是一个集合有,但是另一个集合没有的元素,所以差集可以得到两种不同的结果)

        

    >>> list_1.difference(list_2) #list_1中存在但是list_2中不存在
    {12, 5, 6}
    >>> list_2.difference(list_1) ##list_2中存在但是list_1中不存在
    {88, 33, 4}

    >>> list_1 - list_2
    {12, 5, 6}
    >>> list_2 - list_1
    {88, 33, 4}

        e、判断子集(判断一个集合是否在另一个集合中)

    >>> list_3 = set([1,3])
    >>> list_3.issubset(list_2)
    True
    >>> list_3.issubset(list_1)
    True

        f、判断父集

    >>> list_1.issuperset(list_3)
    True

        g、对称差集symmetri_difference(去掉list_1与list_2的交集后存入其他剩余元素)

    >>> list_1.symmetric_difference(list_2)
    {33, 4, 5, 6, 88, 12}
    >>> list_1 ^ list_2
    {33, 4, 5, 6, 88, 12}

       

      基本操作:

        a、添加(集合操作没有插入动作,只能添加)

    >>> list_1
    {1, 3, 5, 6, 12, 77}
    >>> list_1.add(999)    #添加单项
    >>> list_1.add('wang')
    >>> list_1
    {1, 3, 5, 6, 999, 12, 77, 'wang'}
    >>> list_1.update(['alex','john','tom'])  #添加多项
    >>> list_1
    {1, 3, 5, 6, 999, 12, 77, 'john', 'tom', 'wang', 'alex'}

        b、删除

    >>> list_1
    {1, 3, 5, 6, 999, 12, 77, 'john', 'tom', 'wang', 'alex'}
    >>> list_1.remove(999)  #通过remove方法删除,删除后不显示删除项,删除需要明确指定删除项的内容,因为集合是无序的,没有索引的概念
    >>> list_1
    {1, 3, 5, 6, 12, 77, 'john', 'tom', 'wang', 'alex'}
    >>> list_1.remove(wang)  #针对字符串需要加引号
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    NameError: name 'wang' is not defined
    >>> list_1.remove('wang')
    >>> list_1
    {1, 3, 5, 6, 12, 77, 'john', 'tom', 'alex'}
    >>> list_1.pop()  #pop方法属于随机删除,删除后显示删除的内容
    1
    >>> list_1.pop()
    3
    >>> list_1.pop()
    5
    >>> list_1.pop()
    6
    >>> list_1.pop()
    12
    >>> list_1.pop()
    77
    >>> list_1.pop()
    'john'
    >>> list_1
    {'tom', 'alex'}

        c、discard删除

    >>> list_1
    {'wang', 1, 3, 5, 6, 999, 12, 77, 'john', 'tom', 'alex'}
    >>> list_1.discard(999)   
    >>> list_1
    {'wang', 1, 3, 5, 6, 12, 77, 'john', 'tom', 'alex'}
    >>> list_1.discard(888)    #discard与remove的不同之处在于,discard如果是删除不存在的内容,不会报错,但是remove会报错
    >>> list_1.remove(999)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    KeyError: 999

        d、长度len

    >>> len(list_1)
    10
    >>> list_1
    {'wang', 1, 3, 5, 6, 12, 77, 'john', 'tom', 'alex'}

        e、成员判断(in 和not in)

    >>> list_1
    {'wang', 1, 3, 5, 6, 12, 77, 'john', 'tom', 'alex'}
    >>> 'wang' in list_1
    True
    >>> 11 in list_1      
    False
    >>> 11 not in list_1
    True

        f、拷贝(和list一样,都属于浅拷贝)

     2、文件操作:

      1、文件操作包括以下几种方式:

        1)读模式

    >>> data = open('yesterday.txt', 'r')   #open函数默认是读默认,所以r可以省略,但是为了规范最好写清楚已哪种方式打开
    >>> print(data)  #当打开这个文件后,print会返回该文件名字,默认与默认编码等文件本身属性
    <_io.TextIOWrapper name='yesterday.txt' mode='r' encoding='UTF-8'>

        2)写模式

    >>> data = open('yesterday1.txt', 'w')   #文件已写模式打开
    >>> data.write('1234
    ')   #当打开后,可以使用wirite方法进行写入操作,如果需要每行结束后换行,需要手动添加“
    ”  这样保证在输入后进行换行操作,当写入后,会自动提示写了多少个字符
    5
    >>> f = data.read()    #由于模式之间不兼容,如果只以写模式打开文件,进行读操作会报错
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    io.UnsupportedOperation: not readable

        3)追加模式

    >>> data = open('yesterday1.txt', 'a')  #和写模式不同,已追加模式打开文件,不会覆盖原文件内容,只会在文件后面进行添加,如果以w模式打开,会将文件原有内容全部清空,重新编写
    >>> 
    >>> 
    >>> data.write('wwwyy
    ')   #对于写与追加模式,都可以进行write操作
    6
    >>> f = data.read()    #追加模式也同样不能进行读操作
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    io.UnsupportedOperation: not readable

      总结:

    文件打开最常用三种模式为读、写、追加。默认为open函数以读模式方式工作,在读模式中可以读取文件内容,写与追加模式均可以对文件进行修改,不同的是,读模式打开文件后,会将原有文件内容清空,添加新内容,而追加模式不会清空原有内容,会在文件最后添加新的需要追加的内容,至于如何在将r、w和a模式进行结合操作,会在修改文件时进行介绍

      2、读模式的相关操作

        1)read操作

    >>> data = open('yesterday.txt', 'r') 
    >>> data.read()    #read操作会一次性将文件全部内容读取到内存中
    '往日重现
    
    当我年轻的时候
    听着收音机
    等待着我最喜爱的歌
    当它播放时我独自跟唱
    让我心情愉快起来
    
    就像那些快乐时光
    惊讶消失的无影无踪
    但当它们回来时
    就像是久没联络的朋友一样
    这都是我喜欢的歌
    
    每个Sha-la-la-la
    每个Wo-o-wo-o
    记忆依鲜明
    每个shing-a-ling-a-ling
    节奏依然美好
    
    当故事到了那个段落
    他伤了她的心
    让我流下泪来
    就像从前
    往日重现'
    >>> data.read()  # 由于文件指针的存在,当一次性读取文件到内存后如果不进行指针回退操作前再次读取,会返回空值,表示该内容上一次已经读取完毕,本次读取没有内容显示
    '' 

        2)readline操作

    >>> data = open('yesterday.txt', 'r')
    >>> data.readline()  #与read操作一次性读取不同,readline操作每次只会读取一行内容存储到内存中,readline方法可以针对每行内容进行操作
    '往日重现
    '
    >>> data.readline()
    '
    '
    >>> data.readline()
    '当我年轻的时候
    '
    >>> data.readline()
    '听着收音机
    '

        3)readlines操作

    >>> data = open('yesterday.txt', 'r')
    >>> data.readlines()#区别于read于readline操作,readlines操作也是一次性读取,不同的是它会将读取的内容放入到一个列表中,这样后续可以操作列表的方式对该文件内容进行需要的操作
    ['往日重现
    ', '
    ', '当我年轻的时候
    ', '听着收音机
    ', '等待着我最喜爱的歌
    ', '当它播放时我独自跟唱
    ', '让我心情愉快起来
    ', '
    ', '就像那些快乐时光
    ', '惊讶消失的无影无踪
    ', '但当它们回来时
    ', '就像是久没联络的朋友一样
    ', '这都是我喜欢的歌
    ', '
    ', '每个Sha-la-la-la
    ', '每个Wo-o-wo-o
    ', '记忆依鲜明
    ', '每个shing-a-ling-a-ling
    ', '节奏依然美好
    ', '
    ', '当故事到了那个段落
    ', '他伤了她的心
    ', '让我流下泪来
    ', '就像从前
    ', '往日重现']

        4)close操作

    >>> data.close()  #在r、w、a操作的最后需要将文件关闭,采用close方法进行关闭,这样才会将文件修改保存到硬盘中,如果没有关闭操作,默认情况下都是在内存中进行操作的

         5)文件的编码格式

    >>> data = open('yesterday.txt', 'r',encoding='utf-8') #在打开文件时需要跟文件的编码格式,python3中默认是采用utf-8格式的编码,所以可以省略
    >>> print(data)
    <_io.TextIOWrapper name='yesterday.txt' mode='r' encoding='utf-8'>

        6)正确的文件读取方式

    data = open('yesterday.txt','r',encoding='utf-8')
    for index,line in enumerate(data.readlines()):  #方式一、将文件一次性通过readlines方法读到内存中,然后对其进行操作,该方法适合小文件,如果大文件会由于空间过大,导致打开文件速度过慢,不推荐该方式
        print(index,line,end='')
    输出:
    0 往日重现
    1 
    2 当我年轻的时候
    3 听着收音机
    4 等待着我最喜爱的歌
    5 当它播放时我独自跟唱
    6 让我心情愉快起来
    7 
    8 就像那些快乐时光
    9 惊讶消失的无影无踪
    10 但当它们回来时
    11 就像是久没联络的朋友一样
    12 这都是我喜欢的歌
    13 
    14 每个Sha-la-la-la
    15 每个Wo-o-wo-o
    16 记忆依鲜明
    17 每个shing-a-ling-a-ling
    18 节奏依然美好
    19 
    20 当故事到了那个段落
    21 他伤了她的心
    22 让我流下泪来
    23 就像从前
    24 往日重现
    ########################################################################
    data = open('yesterday.txt','r',encoding='utf-8')
    for line in data: #第二种方法,data已经变味迭代器而不是列表就没有下标操作,此时会对每行读到内存后进行操作,然后再释放内存,再进行下一行操作,节省内存,推荐该方式操作
        print(line,end='')
    输出:
    往日重现
    
    当我年轻的时候
    听着收音机
    等待着我最喜爱的歌
    当它播放时我独自跟唱
    让我心情愉快起来
    
    就像那些快乐时光
    惊讶消失的无影无踪
    但当它们回来时
    就像是久没联络的朋友一样
    这都是我喜欢的歌
    
    每个Sha-la-la-la
    每个Wo-o-wo-o
    记忆依鲜明
    每个shing-a-ling-a-ling
    节奏依然美好
    
    当故事到了那个段落
    他伤了她的心
    让我流下泪来
    就像从前
    往日重现
    ########################################################################
    data = open('yesterday.txt','r',encoding='utf-8')
    count = 0
    for line in data:
       if count == 9:
           print('------------')
           count +=1
           continue
       print(line,end='')
       count +=1
    print('
    ')
    print(type(data))
    输出:
    往日重现
    
    当我年轻的时候
    听着收音机
    等待着我最喜爱的歌
    当它播放时我独自跟唱
    让我心情愉快起来
    
    就像那些快乐时光
    ------------     #第九行进行替换操作
    但当它们回来时
    就像是久没联络的朋友一样
    这都是我喜欢的歌
    
    每个Sha-la-la-la
    每个Wo-o-wo-o
    记忆依鲜明
    每个shing-a-ling-a-ling
    节奏依然美好
    
    当故事到了那个段落
    他伤了她的心
    让我流下泪来
    就像从前
    往日重现
    
    <class '_io.TextIOWrapper'>   #验证data此时属于何种类型

         7)tell方法与seek方法介绍

    >>> data = open('yesterday.txt','r',encoding='utf-8')
    >>> print(data.tell())  #tell方法可以只是当前文件指针所在位置,初始为0
    0
    >>> print(data.read(100))  #通过read方法读取文件
    往日重现
    
    当我年轻的时候
    听着收音机
    等待着我最喜爱的歌
    当它播放时我独自跟唱
    让我心情愉快起来
    
    就像那些快乐时光
    惊讶消失的无影无踪
    但当它们回来时
    就像是久没联络的朋友一样
    这都是我喜欢的歌
    
    >>> print(data.tell())  #当读取完毕后再次查看文件指针位置
    274
    >>> print(data.read())#读取剩余的全部文件
    
    每个Sha-la-la-la
    每个Wo-o-wo-o
    记忆依鲜明
    每个shing-a-ling-a-ling
    节奏依然美好
    
    当故事到了那个段落
    他伤了她的心
    让我流下泪来
    就像从前
    往日重现
    >>> print(data.tell())   #读取此时文件指针位置
    463
    >>> print(data.read())#由于文件全部读取完毕,再次读取只能返回空值
    
    >>> data.seek(0)  #将文件指针置为初始位置
    print(data.tell())  #验证此时文件指针是否处于初始位置
    0
    >>> print(data.tell())
    print(data.read(50))
    0
    >>> print(data.read(50))
    往日重现
    
    当我年轻的时候
    听着收音机
    等待着我最喜爱的歌
    当它播放时我独自跟唱
    让我心情愉快起来
    
    >>> print(data.tell())  #当读取文件后再次通过tell方法获取文件指针所在位置
    136

      3、文件的其他操作

        1)encoding:打印文件编码

    >>> data.encoding
    'utf-8'

        2)  fino()返回文件句柄所在操作系统的编码  基本不使用操作

        3)isatty()该文件是否是一个终端设备,linux系统中可以用来判断是否是一个tty文件

        4)name打印文件名称

    >>> data.name
    'yesterday.txt'

        5)  seekable() 是否可以移动指针

    >>> data.seekable()
    True

        6)  flush()刷新操作:

    如果以写模式打开文件,写完后不一定立即写入磁盘,如果此时突然断电可能没有及时写入进文件,所以可以通过flush方法刷新进磁盘

    例子:可以在安装程序时,打印进度条

    import time,sys
    for i in range(50):
        sys.stdout.write('#')
        sys.stdout.flush()  #将#号实时刷新到屏幕上来
        time.sleep(0.1)

        7)closed 判断文件是否关闭

    >>> data.closed
    False
    >>> data.close()
    >>> data.closed
    True

        8)  truncate()如果不写入任何东西就是清空文件

        data.truncate(10)会只保留10个字节,其余的会删除,同时truncate自带文件指针,无论通过seek移到任何位置,truncate都会按照初始位置来删除与保留

      4、修改文件:

      修改文件分为两种模式:

        1、将文件全部读入内存中,然后修改,该方式典型代表就是vim程序

        2、将文件按照行模式读,然后每行操作完毕后再放入新文件,这种方式节约内存占用,类似与sed与awk操作

      对于文件操作,除了典型r/w/a方式外还有其他操作,下面来简要介绍这几种更常用操作:

        1)r+  读写操作,表示又能读又能写,这个表示以读与追加模式开始,如果写,会将写的内容放入最后

    >>> data = open('test1.txt','r+',encoding='utf-8')  #以读写模式打开文件
    >>> data.readline() #对文件进行读操作
    '往日重现
    '
    >>> data.readline()
    '当我年轻的时候
    '
    >>> data.readline()
    '听着收音机
    '
    >>> data.readline()
    '等待着我最喜爱的歌
    '
    >>> data.write('-------aaaaaaaaaa---------') #对该文件进行写操作
    26
    >>> data.readline()
    '当它播放时我独自跟唱
    '
    >>> data.readline()
    ''
    >>> data.seek(0)
    0
    >>> data.read()  #在重新载入文件进行读写会发现,追加的内容会放在最后
    '往日重现
    当我年轻的时候
    听着收音机
    等待着我最喜爱的歌
    当它播放时我独自跟唱
    -------aaaaaaaaaa---------'

         2)w+写读模式,创建新文件,输入内容,然后读取文件指针所在位置,在回退,再输入,会发现插入的内容,仍然在最后而不是通过seek调转

    >>> data = open('test1.txt','w+',encoding='utf-8')#以w+模式打开
    >>> data.write('a-------1
    ')
    10
    >>> data.write('a-------2
    ')
    10
    >>> data.write('a-------3
    ')
    10
    >>> data.write('a-------4
    ') #输入内容
    10
    >>> data.seek(10) #跳转到第一行
    10
    >>> data.readline()  #读取第二行
    'a-------2
    '
    >>> data.tell() 
    20
    >>> data.write('a-------5
    ')  #插入新语句,理论上应该插入到第三行
    10
    >>> data.seek(0)
    0
    >>> data.read()
    'a-------1
    a-------2
    a-------3
    a-------4
    a-------5
    '  #通过读取发现仍然是插入到最后一行,证明通过seek移动文件指针也没法改变w+的文件输入顺序

        3)a+追加读模式,在追加的过程中可以进行读

    >>> data = open('test1.txt','a+',encoding='utf-8') 
    >>> data.read()
    ''
    >>> data.tell()
    50
    >>> data.seek(0)
    0
    >>> 
    >>> 
    >>> data.write('a----------6
    ')#将指针挪到开头后进行追加写操作
    13
    >>> data.seek(0)
    0
    >>> data.read()  #重新读取文件发现,追加写仍然按照原有顺序进行添加
    'a-------1
    a-------2
    a-------3
    a-------4
    a-------5
    a----------6
    '

      5、二进制文件

    针对二进制文件有两种方式,rb与wb,其中两种情况下使用rb:

    1、网络传输,socket传输时只能使用二进制格式编码

    2、视频文件打开,也必须使用二进制格式打开

      6、with语句

    为了避免打开文件后忘记关闭,可以通过with来管理上下文,即:

    >>> with open('tes2.txt','w') as f:f.write('nnnnn
    ')
    ... 
    6

    如此方式,当with代码执行完毕后,内部会自动关闭并释放文件所在内存,同时也可以同时打开多个文件

    with open('tes2.txt','w') as f, open('test3.txt','w') as f2:#两个文件之间用‘,’来分割
        f.write('nnn
    ')
        f2.write('mmmm
    ')

      

    3、字符编码与转码

    知识点:

    1.在python2默认编码是ASCII, python3里默认是unicode

    2.unicode 分为 utf-32(占4个字节),utf-16(占两个字节),utf-8(占1-4个字节), so utf-16就是现在最常用的unicode版本, 不过在文件里存的还是utf-8,因为utf8省空间

    3.在py3中encode,在转码的同时还会把string 变成bytes类型,decode在解码的同时还会把bytes变回string

    在介绍编码之前先介绍下计算机语言与人类可识别语言转换:

    计算机只能识别二进制编码,即0和1,在二进制编码中采用bit(位)来表示,但是这种方式对人类来讲是不可读的,所以初始阶段,发明了ASII码,即采用一个byte(8个bits)方式来表示人类可识别字母,2的8次方-1也就是使用255个ASII码来表示A-Za-z0-9这些数字与字母,但是对于非英语国家来说,255个字符表示没法完全表示自己本国语言,对于中国来说,本身采用了gbk  gbk2308 gbk2312等编码方式来进行特定的编码,但是这种方式到了其他国家由于编码格式未统一,所以导致本国的程序到其他国家未必会被采用,基于这种情况,标注化组织开发了unicode即万国码的方式来代替了原有的各自为政的局面,unicode要求:最少已2个资金来表示,这样又引入了新的问题,就是比较浪费资源,所以最后统一使用utf-8编码方式:英语国家采用ASII编码,一个字节,欧洲等国家采用两个字节,而中国这种亚洲国家采用3个字节来表示自己的编码,至此解决了编码方式的问题

    在说的编码与解码,由于类似bgk与utf-8之间没法直接转换,都需要经过unicode作为中转编码,所以需要编码与解码过程

    import sys
    print(sys.getdefaultencoding())   #打印得出默认编码为utf-8
    utf-8
    s = '你好'      #在python3中默认编码为unicode
    s_gbk = s.encode('gbk')  #由于默认编码为unicode,所以这里从unicode到gbk编码采用的是encode模式,因为unicode没有decode过程了,可以直接encode
    print(s_gbk)   #这里输出为gbk编码格式
    b'xc4xe3xbaxc3'
    s_to_utf8 = s.encode('gbk').decode('gbk').encode('utf-8')  '''从bgk变为utf-8:需要先把编码encode为bgk,然后在解码decode,解码是告诉自己为bgk,这时已经转换为unicode了,再从unicode状态encode成utf-8'''
    print(s_to_utf8)
    b'xe4xbdxa0xe5xa5xbd'
    s_to_unicode = s.encode('gbk').decode('gbk').encode('utf-8').decode('utf-8')  #在上面的基础上再使用decode模式解码到unicode
    print(s_to_unicode)
    你好

    4、函数

      1、编程方式

        1)面向对象:类  定义用class

        2)面向过程:过程,定义用def

        3)函数式编程:函数,定义用def

          其中函数式编程,其中没有任何变量,对于某一输入一定存在确定的输出,这种编程语言包括Lisp、relang,这里对函数式编码不做过多讨论

      2、定义函数

      

    def func1():   #通过def方式定义函数
      '''testing'''
      print('func1')
      return 0    #函数可以有返回值
    
    a = func1()   #调用该函数

      3、定义过程

    def func2():  #定义过程与定义函数的区别在于定义过程是没有返回值的
        '''testing'''
        print('in the func2')

      4、调用函数与调用过程,查看返回值

    def func1():   
      '''testing'''
      print('func1')
      return 0
    
    def func2():
        '''testing'''
        print('in the func2')
    
    a = func1()  #调用函数1
    b = func2() #调用过程2
    
    print(a)
    #打印返回值为0
    print(b)
    #打印没有返回值,按照默认来定义:None

      5、使用函数的好处

        1)代码的重复利用

        2)程序容易扩展

        3)保持代码的一致性

      6、函数的返回值

    def func1():
      '''testing1'''
    
    
    
    def func2():
        '''testing2'''
        return 1
    
    def func3():
        '''testing3'''
        return 1,[1,2,3,4,5,6,7],(1,2,4,3,3,'wang'),{'name':'gavin','age':99}
    
    a = func1()
    b = func2()
    c = func3()
    
    print(a)
    None
    print(b)
    1
    print(c)
    (1, [1, 2, 3, 4, 5, 6, 7], (1, 2, 4, 3, 3, 'wang'), {'age': 99, 'name': 'gavin'})

        返回值个数=0,返回None,系统默认返回空

        返回值个数=1,反正object,定义哪个返回值,就返回哪个

        反正值个数>1,返回tuple,当返回值个数大于1时,返回一个元组包含哪些需要返回的数值

       7、形参与实参

    def func1(x,y):   #x与y时函数的形参,在没有调用该函数时,x与y不代表任何变量,不占用内存
      '''testing1'''
      x = x + y
      return x
    
    
    a = func1(10,20)  #10与20是在调用该函数式传递给该函数的实参,目的是代替形参传入函数得到预期的结果
    print(a)   #在没有默认参数的情况下,形参与实参是需要一一对应的,如果调用时不一一对应会导致报错
    30

      8、默认参数

    def func1(x,y=20):#y有默认参数,但是实际调用时没有实参对y赋值,y将采用默认参数,需要注意的是,默认参数要放在最后
      '''testing1'''
      x = x + y
      return x
    a = func1(10)
    print(a)
    30
    b = func1(11,21)
    print(b)
    32

      默认参数特点:

    调用函数时,默认参数可有可无,默认参数的用途是1在默认安装软件时使用,2在连接数据库端口号时使用

      9、参数组

    def func1(fmt,*args):
      '''testing1'''
    
      return fmt%args
    
    a = func1('%d is larger than %d',2,1)
    print(a)
    2 is larger than 1
    
    #函数中*args必须是最后一个参数,*表示任意多个参数,*args会把除了前面以外所有参数放入一个tuple里面传递给函数,可以在函数中通过args来访问
    #args是一个tuple,可以通过访问tuple方法来在函数中访问args
    def func2(format,**keyword):
        for k in keyword.keys():
            print('keyword[%s]  %s %s' %(k,format,keyword[k]))
    
    func2('is',one=1,two=2,three=3)
    keyword[one]  is 1
    keyword[three]  is 3
    keyword[two]  is 2
    #通过dictionary方式传递参数,同样也可以接受多个参数,但是每个参数必须明确指明名称对应关系,比如a=1,b=2,c=3,这些方法可以混混在一起使用,但是要注意顺序,函数会先接受固定参数,然后是可选参数,然后是任意参数(tuple),再然后才是字典参数(dictionary)

      10、局部变量与全局变量

      局部变量只在函数中生效,而全部变量是在整个程序中都生效的变量,代码顶层定义的变量,局部变量变成全局变量需要在函数中global这个局部变量,但是千万不要这么使用,但是需要注意的是,列表、字典、集合、类都是可以在函数中修改内容的,字符串与整数在局部变量中不能修改

    name = 'gavin'
    
    def my(name,age):
        name = 'jack'   #局部变量
        age = 23
        return name,age
    
    
    a = my(name,44)   #name的局部变量在函数中生效变为jack,但是函数结束后仍然为gavin这个全局变量
    print(a)   #传入的44在函数中没有生效
    ('jack', 23)
    
    print(type(a))  #返回值多于一个,反正的是tuple
    <class 'tuple'>
    print(a[0]) #可以按照元组方式调用返回值
    jack
    print(a[1])
    23
    print(name)
    gavin
    a = 'gavin'
    
    def my(name):
        global a    #将a变为全局变量
        name = 'jack'   #局部变量
        a = 'john'
        print(name,a)
    
    my('a')
    jack john
    print(a)
    john
    names = ['alex','gavin','tom']
    
    def my():
        print(names)
        names[1] = 'jack'   #将全局变量中的names[1]修改为jack
        return names
    
    my()
    ['alex', 'gavin', 'tom']
    print(names)   #在打印时发现局部变量中的jack替换了全部变量中的gavin
    ['alex', 'jack', 'tom']

      11、递归

    在函数内部,可以调用其他函数,如果一个函数在内部调用函数本身,这个函数就叫做递归函数

      递归的特点:

        1)必须有一个明确的结束条件

        2)每次进入更深的一层递归时,问题规模相比上一次递归应有所减少

        3)递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈这种数据结构实现的,每当进入一个函数调用,栈会增加一层栈帧,每当函数返回会减少一层栈帧,由于栈的大小不是无限的,所以递归次数过多会导致栈的溢出)

    def calc(n):
        print(n)
        if int(n/2) > 0:
            return calc(int(n/2))
        print('--->', n)
    calc(10)
    10
    5
    2
    1
    ---> 1

      12、高阶函数:没找到应用场景

    变量可以指向函数,函数的参数能接受变量,那么一个函数就能接收另一个函数作为参数,这种函数叫做高阶函数

    def add(a,b,f):
        return f(a) + f(b)
    res = add(3,-10,abs)
    print(res)
    13

       

    二、作业

    1、作业一

    实现类似与sed的替换操作

    import sys,os
    i_flag = sys.argv[1]    #传递替换参数=s
    source_sed = sys.argv[2]  #需要替换的内容
    dest_sed = sys.argv[3]    #替换的内容
    source_file = sys.argv[-1]  #需要替换的文件
    source_file_bak = sys.argv[-1] + '_bak' + '.txt'   #替换后的临时文件
    flag = 0
    print(i_flag,source_sed,dest_sed,source_file,source_file_bak,flag)
    if i_flag != 's':
        print('error input ,please input your command like this "sed_python s source_sed dest_sed source_file" ')
    else:
        pass
    
    try:
        with open(source_file,'r') as file1, open(source_file_bak, 'w') as file2:
            for line in file1:
                if line.strip() == source_sed:  #当核对到需要替换的内容后,进行替换操作
                    line = line.replace(source_sed,dest_sed)
                    flag = 1  #当flag为1时进行回写操作,如果没有发生替换,就不进行回写
                file2.write(line)  #将替换的内容写入新的文件中
    
    except IOError:
        print('the file %s is not exist!' %(source_file))
    
    if flag == 1:   #判断是否发生替换操作,如果发生,进行回写操作
        with open(source_file,'w') as file1, open(source_file_bak, 'r') as file2:
            for line in file2:
                file1.write(line)  #将替换的文件内容回写到原文件中
    os.remove(source_file_bak)  #替换完成后删除临时文件

     作业二

    对一个haproxy文件进行查找、删除、添加操作

    import json,shutil,os
    def logging():
        print('pls input your option'.center(35,'@'))
        print('[1]. print the backend information')
        print('[2]. add the backend information')
        print('[3]. delete the backend information')
        print('  the end  '.center(35,'@'))
    
    
    
    
    def printer(backend):
        backend_list = []
        with open('haproxy.txt','r',encoding="utf-8") as f:
            change_flag = False
            for line in f:
                if line.split(' ')[0].strip() == 'backend' and line.split(' ')[1].strip() == backend:#匹配要查找的参数
                    change_flag = True  #方便记录该backend下面的server数据
                    continue
                elif change_flag != True:
                    continue
                elif change_flag == True :  #根据前面的if操作的赋值,得到backend下面的server配置,写入列表中
                    if line.split(' ')[0].strip() != 'backend':  #该操作为了避免遇到下一个backend,这当做结束操作
                        backend_list.append(line.strip())
                    else:
                        break
        return backend_list
    
    
    def adder(obj):
        backend_obj = obj['backend']
        finder = printer(backend_obj)
        if finder == []:  #当没有该backend时的操作
            with open('haproxy.txt','a') as f:  #执行打开文件执行全新文本操作
                f.write("
    backend " + str(obj['backend'])+'
    ')
                f.write(" " *4 + 'server {server} {server}  weight {weight} maxconn {maxconn}'.format(server=obj['record']['server'],weight=obj['record']['weight'],maxconn=obj['record']['maxconn']) +'
    ')
    
        elif finder != []:#当backend不为新增时,需要判断server是否为新增
            data = 'server {server} {server}  weight {weight} maxconn {maxconn}'.format(server=obj['record']['server'],weight=obj['record']['weight'],maxconn=obj['record']['maxconn'])
            if data not in finder:  #当server为新增时,进行如下操作
                with open('haproxy.txt','r') as f, open('new.txt','w') as f2:
                    flag = False
                    for line in f:
                        if line.strip().startswith('backend') and line.split(' ')[1].strip() == obj['backend']:
                            flag = True  #为了避免该backend后面server重复写入而进行置位
                            f2.write(line)
                            finder.append(data)  #将原有server配置与新增server存入一个list钟
                            for line in finder:  #根据list内容,进行打印操作
                                f2.write(" " * 4 + line + "
    ")
                            continue
                        if flag and line.strip().startswith("backend"):  # 下一个backend
                            flag = False 
                            f2.write(line)
                            continue  # 退出此循环,避免server信息二次写入
                        if line.strip() and not flag:  #普通文本操作
                            f2.write(line)
                shutil.copy('new.txt','haproxy.txt')
                os.remove('new.txt')
            else:
                    print('33[32;1myour input is in configre of haproxy 33[0m')
    
    
    def delete(backend_name):
        finder = printer(backend_name)
        if finder == []:  #当查找函数没有返回值,说明没有找到配置中存在该选项
            print('33[31;1mthe proxy.txt not inclould the backend33[0m')
        elif finder != []:
            with open('haproxy.txt','r') as f, open('del.txt','w') as f2:
                    flag = False
                    for line in f:
                        if line.strip().startswith('backend') and line.split(' ')[1].strip() == backend_name:
                            flag = True  #flag置为True已保证backend下面的server均没法写入配置文件中
                            continue  #直接跳过本次操作,防止和下面if选项符合而导致没有正确删除操作
                        if flag and line.strip().startswith("backend"):  # 下一个backend
                            flag = False
                            f2.write(line)
                            continue  # 退出此循环,避免server信息二次写入
                        if line.strip() and not flag:   #普通文本均通过该选项写入配置文件中
                            f2.write(line)
            shutil.copy('del.txt','haproxy.txt')  #将执行拷贝操作
            os.remove('del.txt')  #删除多余配置文件
    
    
    def output(result):  #当列表不为空,调用该函数打印
        for line in result:
            print(line)
    
    
    
    def dicter():  #增加选项时,根据输入的字符串转换为字典以方便取值
        backend_record_raw = input("Input backend info:").strip()
        backend_record_eval = eval(backend_record_raw)
        return backend_record_eval 
    
    
    
    def operating(action):
        if action == 'printer':  #当action为printer时,进行查找操作
            backend = input('pls input your will find backend: ').strip()
            acter = printer(backend) 
            if acter != []: #当执行printer函数,返回列表不为空,进行打印
                output(acter) 
            else:
                print('33[31;1mthe backend is not exist!33[0m')
    
        elif action is None:
            print("33[31;1mNothing to do!33[0m")
        else:
            if action == 'adder': 
                backend_record = dicter()  #当action为adder时,进行调用赋值函数,从而进入增加操作
                adder(backend_record)
            elif action == 'delete':
                backend_name = input('input your want to delete backend name: ').strip()  #根据输入的数值进行删除操作
                delete(backend_name)
    
    
    
    
    def judging():  #判断环节
        choice = input('action:').strip()  #根据logging函数替换输入选项
        if choice == '1':   #当选择为1时,将action赋值为printer操作
            action = 'printer'
        elif choice == '2':  #当选择为2时,将action赋值为adder操作
            action = 'adder'
        elif choice == '3':  #当选择为3时,将action赋值为delete操作
            action = 'delete'
        elif choice == "q" or choice == "quit":
            exit("Bye,thanks!".center(35, "#"))
        else:
            print("33[31;1mInput error!33[0m")
            action = None
        return action   #函数返回值为action赋值
    
    
    
    def main():  #程序主入口
        while True:
            logging()  #调用log打印信息
            action = judging()    #进入判断环节
            operating(action)     #通过判断环节得到的数据进行操作环节
    
    
    
    
    if __name__ == '__main__':
        main()

    配置文件如下:

    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.163.com
        server 100.1.7.10 100.1.7.10 weight 20 maxconn 3000
        server 10.1.1.11 10.1.1.11  weight 20 maxconn 40

      

  • 相关阅读:
    linux之sed用法
    个人记录-虚拟现实
    对于spark以及hadoop的几个疑问(转)
    关于老师的说的技术问题
    为什么我们总是行动不起来?你失败不是因为能力差? 如何才能实现我们的计划?
    Hibernate中一对多和多对一关系
    C# 将PDF文件转换为word格式
    C# 设置word文档页面大小
    C# 将多个office文件转换及合并为一个PDF文件
    C# 给PDF文件添加水印
  • 原文地址:https://www.cnblogs.com/xiaopi-python/p/6351391.html
Copyright © 2011-2022 走看看