美文网首页
Day03 - Python基础3

Day03 - Python基础3

作者: 乘风逐月 | 来源:发表于2016-12-06 23:18 被阅读0次

    Day03的课程要点记录
    详细教程地址:金角大王 - Day3 Python基础3 | 金角大王 - Day2 Python基础2 | 银角大王 - Python基础(二)

    一、集合的使用

    集合是一个无序的,不重复的数据组合,它的主要作用如下:

    • 去重,把一个列表变成集合,自动去重
    • 关系测试,测试两组数据之前的交集、差集、并集等关系

    1.1 常用操作

    a = {11, 22, 33, 44}
    s = set([3, 5, 9, 10]) #创建一个数值集合
    t = set('Hello') #创建一个唯一字符的集合

    a = t | s # t 和 s 的并集
    b = t & s # t 和 s 的交集
    c = t - s # 求差集(项在t中,但不在s中)
    d = t ^ s # 对称差集(项在t或s中,但不会同时出现在二者中)

    1.2 基本操作

    • s.intersection(t),s & t,交集,返回一个新的 set 包含 s 和 t 中的公共元素
    >>> s.intersection(t)
    set()
    
    • s.union(t),s | t,并集,放回一个新的 set 包含 s 和 t 中的每一个元素
    >>> s.union(t)
    {'e', 3, 'l', 5, 'H', 9, 10, 'o'}
    
    • s.difference(t),s - t,差集,返回一个新的 set 包含 s 中有但是 t 中没有的元素
    >>> s.difference(t)
    {9, 10, 3, 5}
    
    • s.issubset(t),s <= t,子集,测试 s 中的每一个元素是否都在 t 中
    >>> s.issubset(t)
    False
    
    • s.issuperset(t),s >= t,父集,测试 t 中的每一个元素是否都在 s 中
    >>> s.issuperset(t)
    False
    
    • s.symmetric_difference(),s ^ t,对称差集,返回一个新的 set 包含 s 和 t 中不重复的元素
    >>> s.symmetric_difference(t)
    {'e', 'l', 'H', 3, 5, 9, 10, 'o'}
    
    • s.copy(),返回 set “s”的一个浅复制

    • s.isdisjoint(t),零交叉测试,如果两个集合中零交叉,则返回True

    >>> s.isdisjoint(t)
    True
    

    1.3 增删改查

    1.3.1 增加元素
    • t.add('a') 向集合内添加一项元素
    >>> t.add('a')
    >>> t
    {'o', 'e', 'l', 'H', 'a'}
    
    • s.update([111, 222, 333]) 向集合内添加多项元素
    >>> s.update([111, 222, 333])
    >>> s
    {3, 5, 9, 10, 333, 111, 222}
    
    1.3.2 删除元素
    • s.pop() 随机删除 s 中的一个元素,并返回
    >>> s.pop()
    3
    
    • t.remove('a') 删除 t 中的元素 a
    >>> t.remove('a')
    >>> t
    {'o', 'e', 'l', 'H'}
    
    • s.discard() 删除 s 中的一个指定元素,如果没有此元素,不报错
    >>> s.discard(333)
    >>> s
    {5, 9, 10, 111, 222}
    >>> s.discard(999)
    >>> s
    {5, 9, 10, 111, 222}
    
    1.3.4 其他
    • len(s) set 的长度

    • x in s 测试 x 是否是 s 的成员

    • x not in s 测试 x 是否不是 s 的成员


    set集合练习题

    old_dict = {
       '#1': 8,
       '#2': 4,
       '#4': 2
    }
    
    new_dict ={
       '#1': 4,
       '#2': 4,
       '#3': 2
    }
    

    需求

    1. 应该删除哪几个槽位?
    2. 应该更新哪几个槽位?
    3. 应该增加哪几个槽位?

    实现代码:

    old_set = set(old_dict.keys())
    new_set = set(new_dict.keys())
    
    del_set = old_set.difference(new_set)   # 应该删除old中有new中无的差集
    update_set = old_set.intersection(new_set)  # 应该更新old和new的交集
    add_set = new_set.difference(old_set)   # 应该增加new中有old中无的差集
    
    print(del_set)
    print(update_set)
    print(add_set)
    

    二、文件操作

    对文件操作流程:

    1. 打开文件,得到文件句柄并赋值给一个变量
    2. 通过句柄对文件进行操作
    3. 关闭文件

    2.1 基本操作 - 读、写、追加

    f = open('lyrics')     # 打开文件
    first_line = f.readline()
    print('first line:',first_line)     # 读一行
    print('我是分隔线'.center(50,'-'))
    data = f.read()        # 读取剩下的所有内容,文件大时不要用
    print(data)     # 打印文件
     
    f.close()     # 关闭文件
    

    打开文件的模式有:

    • r,只读模式(默认)。
    • w,只写模式。【不可读;不存在则创建;存在则删除内容;】
    • a,追加模式。【可读; 不存在则创建;存在则只追加内容;】

    "+" 表示可以同时读写某个文件

    • r+,可读写文件。【可读;可追加写】
    • w+,写读
    • a+,同a 【追加读】

    "U"表示在读取时,可以将 \r \n \r\n自动转换成 \n (与 r 或 r+ 模式同使用)

    • rU
    • r+U

    "b"表示处理二进制文件(如:FTP发送上传ISO镜像文件,linux可忽略,windows处理二进制文件时需标注)

    • rb 网络传输情况下
    • wb
    • ab

    2.2 循环读取文件内容

    • 差方法
    # 读取到第9行时,打印分割线
    for index,line in enumerate(f.readlines())
        if index == 9:
            print("我是分隔线".center(20, '-'))
            continue
        print(line.strip())
    
    • 好方法
    count = 0
    for line in f:
        if count == 9:
            print("我是分隔线".center(20, '-'))
            count += 1
            continue
        print(line.strip())
        count += 1
    

    2.3 其他方法

    f.tell()获取当前光标位置,以及f.seek()移动光标位置

    print(f.tell())         # 获取当前光标位置。 (0)
    print(f.readline())     # 打印第一行
    print(f.readline())     # 打印第二行
    print(f.tell())         # 获取当前光标位置。 (140)
    print(f.seek(0))        # 光标移回至起始处
    print(f.readline())     # 打印第一行
    

    f.enconding() 当前文件的编码
    f.fileno() 返回文件在内存中的编号
    f.name() 当前文件的名字
    f.seekable() 判断文件光标是否可移
    f.readable() 判断文件是否可读
    f.writable() 判断文件是否可写
    f.truncate() 从文件起始截断到指定数(不填则清空)
    f. flush() 将内存中暂存的内容刷新写入硬盘

    命令行进度条实现方式

    import sys, time
    for i in range(100):
        sys.stdout.write('#')
        sys.stdout.flush()
        time.sleep(0.1)    # 每打印一个sleep0.1秒
    

    2.4 文件的修改

    将文件中某一行内的文字进行部分替换

    # 将文本中全部的"我"替换为"你"
    f = open('Yesterday2', 'r', encoding='utf-8')
    f_new = open('Yesterday2.bak', 'w', encoding='utf-8')
    for line in f:
        if '我' in line:
            line = line.replace('我', '你')
        f_new.write(line)
    f.close()
    f_new.close()
    

    2.5 with语句

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

    with open('log','r') as f:
        ...
    

    如此方式,当with代码块执行完毕时,内部会自动关闭并释放文件资源。

    在Python 2.7 后,with又支持同时对多个文件的上下文进行管理,即:

    with open('log1') as obj1, open('log2') as obj2:
        pass
    

    课堂练习

    程序1:实现简单的shell sed替换功能

    import sys
    find_str = sys.argv[1]
    replace_str = sys.argv[1]
     
    with open('Yesterday2', 'r', encoding='utf-8')as f,\
            open('Yesterday3', 'w', encoding='utf-8') as f_new:
        for line in f:
            if find_str in line:
                line = line.replace(find_str, replace_str)
            f_new.write(line)
    

    三、字符转编码操作

    详细文章:py编码终极版 | Strings - Dive into Python3

    Ascii码:每个字符存1个字节
    Unicode:每个字符存2个字节
    utf-8:英文用1个,其他用3个字节


    Decode & Encode

    所有转换动作都需要先decode为Unicode,再encode为相应编码
    在字符串之前加u,默认为其是Unicode,可直接encode

    练习:将字符按顺序转换编码,gb2312 -> utf-8 -> gbk。
    Python2

    import sys
    print(sys.getdefaultencoding())     # 获取默认编码格式
    s = '学习学习再学习'
    s_gb = s.decode('uft-8').encode('gb2312')   # utf-8 -> gb2312
    s_gb_utf8 = s_gb.decode('gb2312').encode('utf-8')   # gb2312 -> utf-8
    s_gb_utf8_gbk = s_gb_utf8.decode('utf-8').encode(gbk)   # utf-8 -> gbk 
    print(s_gb.decode('gb2312'))
    print(s_gb_utf8.decode('utf-8'))
    print(s_gb_utf8_gbk.decode('gbk'))
    

    Python3: 3中encode同时会转换为bytes,显示字符串需要decode为unicode

    import sys
    print(sys.getdefaultencoding())     # 获取默认编码格式
    s = '学习学习再学习'       # py3_default = unicode
    s_gb = s.encode('gb2312')   # unicode -> gb2312
    s_gb_utf8 = s_gb.decode('gb2312').encode('utf-8')   # gb2312 -> utf-8
    s_gb_utf8_gbk = s_gb_utf8.decode('utf-8').encode('gbk')     # utf-8 -> gbk 
    print(s_gb.decode('gb2312'))
    print(s_gb_utf8.decode('utf-8'))
    print(s_gb_utf8_gbk.decode('gbk'))
    

    四、函数

    4.1 函数是什么?

    函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名。

    4.2 基本语法及特性

    4.2.1 语法定义
    def sayhi():    #函数名
        print("Hello, I'm nobody!")
    
    sayhi()        #调用函数
    

    带参数

    # 下面这段代码
    a,b = 5,8
    c = a**b
    print(c)
     
    # 改成用函数写
    def calc(x,y):
        res = x**y
        return res    # 返回函数执行结果
     
    c = calc(a,b)    # 结果赋值给c变量
    print(c)
    
    4.2.2 特性:
    1. 减少重复代码
    2. 使程序变得可扩展
    3. 使程序变得易维护

    4.3 返回值

    return语句返回函数的执行结果。
    注意:

    1. 函数在执行过程中只要遇到return语句,就会停止执行并返回结果。所以可以理解为return语句代表着函数的结束。
    2. 如果未在函数中指定return,那这个函数的返回值为None

    4.4 函数参数

    4.4.1 形参与实参

    形参:变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量
    实参:可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值

    # 改成用函数写
    def calc(x,y):
        res = x**y
        return res
    
    c = calc(a,b)
    print(c)
    
    4.4.2 位置参数

    按顺序给函数传参数

    def test(x,y,z):
       print(x)
       print(y)
       print(z)
    
    test(1, 2, 3)
    
    4.4.3 关键参数

    正常情况下,给函数传参数要按顺序,不想按顺序就可以用关键参数,只需指定参数名即可。但记住一个要求就是,关键参数必须放在位置参数之后。

    def test(x,y,z):
       print(x)
       print(y)
       print(z)
    
    test(3, z=6, y=9)
    
    4.4.4 默认参数

    在写形参时直接给形参定义的一个值。
    特点:调用函数的时候,默认函数非必须传递。
    用途:

    1. 默认安装值
    2. 默认端口号
    def test(x,y=2):
       print(x)
       print(y)
    
    test(1)
    test(1,10)
    
    4.4.5 非固定参数

    *args - 把多传入的位置参数变成一个元组形式。

    def stu_register(name,age,*args):    # *args 会把多传入的参数变成一个元组形式
        print(name,age,args)
     
    stu_register("Alex",22)
    #输出
    #Alex 22 ()    # 后面这个()就是args,只是因为没传值,所以为空
     
    stu_register("Jack",32,"CN","Python")
    #输出
    # Jack 32 ('CN', 'Python')    # 多传入的参数为元组形式
    

    **kwargs - 将多个关键字参数写为字典

    def stu_register(name,age,*args,**kwargs): # *kwargs 会把多传入的参数变成一个dict形式
        print(name,age,args,kwargs)
     
    stu_register("Alex",22)
    #输出
    #Alex 22 () {}#后面这个{}就是kwargs,只是因为没传值,所以为空
     
    stu_register("Jack",32,"CN","Python",sex="Male",province="ShanDong")
    #输出
    # Jack 32 ('CN', 'Python') {'province': 'ShanDong', 'sex': 'Male'}
    

    4.5 全局变量与局部变量

    在子程序中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。
    全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序。
    当全局变量与局部变量同名时:
    在定义局部变量的子程序内,局部变量起作用;在其它地方全局变量起作用。

    name = 'Will'
     
    def change_name(name):
        print("before change:", name)
        name = 'William'
        print('after name', name)
     
    change_name(name)
    print(name)
    

    想在函数内改变全局变量要先声明(可实现,但尽量不要用,出错后调试难度几何级提升)

    name = 'Will'
    school = 'Hometown'
     
    def change_name(name):
        global school
        print("before change:", name)
        name = 'William'
        school = 'University'
        print('after name', name)
     
    change_name(name)
    print(name,school)
    

    五、递归

    在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。
    递归的特性:

    1. 递归必须有一个明确的结束条件
    2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
    3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)
    def calc(n):
        print(n)
        if int(n) > 0:
            return calc(int(n/2))
     
    calc(10)
    

    六、函数式编程介绍

    函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计。函数就是面向过程的程序设计的基本单元。
    函数式编程中的函数这个术语不是指计算机中的函数(实际上是Subroutine),而是指数学中的函数,即自变量的映射。也就是说一个函数的值仅决定于函数参数的值,不依赖其他状态。比如sqrt(x)函数计算x的平方根,只要x不变,不论什么时候调用,调用几次,值都是不变的。

    Python对函数式编程提供部分支持。由于Python允许使用变量,因此,Python不是纯函数式编程语言。

    6.1 定义

    简单说,"函数式编程"是一种"编程范式"(programming paradigm),也就是如何编写程序的方法论。主要思想是把运算过程尽量写成一系列嵌套的函数调用。
    一个数学表达式:(1 + 2) * 3 - 4
    传统的过程式编程

    var a = 1 + 2;
    var b = a * 3;
    var c = b - 4;
    

    函数式编程要求使用函数,可以把运算过程定义为不同的函数,写成下面这样:

    var result = subtract(multiply(add(1, 2), 3), 4);
    

    再演进一下,可以变成这样

    add(1,2).multiply(3).subtract(4)
    

    这基本就是自然语言的表达了。再看下面的代码,应该一眼就能明白它的意思:

    merge([1,2],[3,4]).sort().search("2")
    

    因此,函数式编程的代码更容易理解。
    但要想学好函数式编程,不要用Python,用Erlang,Haskell。

    七、高阶函数

    变量可以指向函数,函数的参数能接收变量。
    而一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。

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

    八、作业

    将输入的字符串转为字典的方法:b = eval(b) | json

    第3周作业:day3 作业详细
    HAproxy配置文件操作(配置文件参考):

    1. 根据用户输入输出对应的backend下的server信息
    2. 可添加backend 和sever信息
    3. 可修改backend 和sever信息
    4. 可删除backend 和sever信息
    5. 操作配置文件前进行备份
    6. 添加server信息时,如果ip已经存在则修改;如果backend不存在则创建;若信息与已有信息重复则不操作

    相关文章

      网友评论

          本文标题:Day03 - Python基础3

          本文链接:https://www.haomeiwen.com/subject/qcxdmttx.html