• python高级特性:切片/迭代/列表生成式/生成器


    廖雪峰老师的教程上学来的,地址:python高级特性 

    下面以几个具体示例演示用法:

    一、切片

    1.1 利用切片实现trim

    def trim(s):
        while s[:1] == " " or s[-1:] == " ": # 若第1个元素或最后1个元素为空格
            if s[:1] == " ":
                s = s[1:]
            if s[-1:] == " ":
                s = s[:-1]
        return s
    

    注:字符串可以看做一个list,列表切片的完整写法是 L[start:end],其中end也支持负数,最后一个数用-1表示,第1个数用0表示,如果省略start,表示从0开始,如果省略end,表示到最后1个元素结束。

    测试代码:

    if trim('hello  ') != 'hello':
        print('测试失败1!')
    elif trim('  hello') != 'hello':
        print('测试失败2!')
    elif trim('  hello  ') != 'hello':
        print('测试失败3!')
    elif trim('  hello  world  ') != 'hello  world':
        print('测试失败4!')
    elif trim('') != '':
        print('测试失败5!')
    elif trim('    ') != '':
        print('测试失败6!')
    else:
        print('测试成功!')
    

    1.2 切片还有第3个参数,即:L[start:end:skip],比如在1-10之间,把奇数、偶数选出来

    list_1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    
    odd = list_1[::2]
    even = list_1[1::2]
    
    print(odd)
    print(even)
    

    输出:

    [1, 3, 5, 7, 9]
    [2, 4, 6, 8, 10]

    二、迭代

    list_1 = list(range(1, 11))
    
    print("正向迭代:")
    for x in list_1:
        print(x)
    
    print("
    反向迭代:")
    for x in reversed(list_1):
        print(x)
    
    print('
    带索引的迭代:')
    for m in enumerate(list_1):
        print("list_1[", m[0], "]=", m[1])
    
    dic_1 = {"name": "菩提树下的杨过", "blog": "http://yjmyzz.cnblogs.com/"}
    
    # 字典的迭代
    print("
    dict字典迭代1:")
    for k in dic_1:
        print("key:", k, ",value:", dic_1[k])
    
    print("
    dict字典迭代2:")
    for v in dic_1.values():
        print("value:", v)
    
    print('
    dict字典迭代3:')
    for k, v in dic_1.items():
        print("key:", k, ",value:", v)
    

    输出:

    正向迭代:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    反向迭代:
    10
    9
    8
    7
    6
    5
    4
    3
    2
    1
    
    带索引的迭代:
    list_1[ 0 ]= 1
    list_1[ 1 ]= 2
    list_1[ 2 ]= 3
    list_1[ 3 ]= 4
    list_1[ 4 ]= 5
    list_1[ 5 ]= 6
    list_1[ 6 ]= 7
    list_1[ 7 ]= 8
    list_1[ 8 ]= 9
    list_1[ 9 ]= 10
    
    dict字典迭代1:
    key: name ,value: 菩提树下的杨过
    key: blog ,value: http://yjmyzz.cnblogs.com/
    
    dict字典迭代2:
    value: 菩提树下的杨过
    value: http://yjmyzz.cnblogs.com/
    
    dict字典迭代3:
    key: name ,value: 菩提树下的杨过
    key: blog ,value: http://yjmyzz.cnblogs.com/
    

      

    三、列表生成器

    这个老厉害了!比如:要找出1~100内所有奇数的平方数(即:1,3,5... 这些数的平方数)

    a = [x ** 2 for x in range(1, 101) if x % 2 == 1 and x ** 2 <= 100]
    print(a)
    

    输出:[1, 9, 25, 49, 81]

    再比如,打印出当前目录下的所有文件(不考虑递归子目录) 

    import os
    
    print([f for f in os.listdir(".")])
    

    小结:写法就是 [... for ... in .. if ...] ,要生成的list项写在for前面,如果迭代时需要指定条件,写在最后的if中。

    四、生成器(generator)

    这是python引入的一个新概念,想想刚才学到的列表生成器:

    result1 = [x ** 2 for x in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]
    print(type(result1), result1)
    

    输出:

    <class 'list'> [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

    不知道大家想过没有:如果for前面的运算比较复杂(比如:求平方根),而for迭代的列表又很大(比如:1千万个),最终列表生成器肯定运行很慢,会严重影响性能。能不能做到『延时』计算?等到真正要用的时候,再按需计算。这就是生成器(generator)要解决的问题,它与[列表生成器]的区别在于,它只保存计算逻辑(即: 保存算法),并不马上计算结果,真正要用的时候,调用next(g)取出下一个计算结果即可,当然,它也支持迭代。

    generator1 = (x ** 2 for x in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
    print(type(generator1), generator1)
    
    # 取出第1个值
    print(next(generator1))
    # 取出第2个值
    print(next(generator1))
    
    # 打印剩余的值
    for x in generator1:
        print(x)
    

    输出:

    <class 'generator'> <generator object <genexpr> at 0x1087e7f10>
    1
    4
    9
    16
    25
    36
    49
    64
    81
    100
    

    从输出类型上看,它的类型是generator,而非list。单纯从语法上看,只要把"列表生成器"的[],换成()即可。

    再来一个复杂点的示例,中学我们都学过"杨辉三角",如果用常规思路,打印出杨辉三角,可以参考下面的代码:

    import copy
    
    def triangles(limit):
        first, second = [1], [1, 1]
        print(first)
        if limit > 1:
            print(second)
            if limit == 2:
                return
            x = copy.copy(second)
            while True:
                y = copy.copy(first)
                [y.append(x[i] + x[i + 1]) for i in range(len(x) - 1)]
                y.append(1)
                print(y)
                x = copy.copy(y)
                if len(y) >= limit:
                    return
    
    
    triangles(10)
    

    输出:

    [1]
    [1, 1]
    [1, 2, 1]
    [1, 3, 3, 1]
    [1, 4, 6, 4, 1]
    [1, 5, 10, 10, 5, 1]
    [1, 6, 15, 20, 15, 6, 1]
    [1, 7, 21, 35, 35, 21, 7, 1]
    [1, 8, 28, 56, 70, 56, 28, 8, 1]
    [1, 9, 36, 84, 126, 126, 84, 36, 9, 1]

    如果,要改写成生成器(generator),该怎么做呢?答案:只要把print(...)的地方,改成yield 即可。

    def triangles_generator(limit):
        first, second = [1], [1, 1]
        yield first
        if limit > 1:
            yield second
            if limit == 2:
                return
            x = copy.copy(second)
            while True:
                y = copy.copy(first)
                [y.append(x[i] + x[i + 1]) for i in range(len(x) - 1)]
                y.append(1)
                yield y
                x = copy.copy(y)
                if len(y) >= limit:
                    return
    
    
    g = triangles_generator(10)
    # 取出前2个
    print(next(g))
    print(next(g))
    # 剩下的用迭代写法输出
    for x in g:
        print(x)
    

    输出与刚才相同,就不重复贴了。关于这个yield,如果还没理解的,可以对比看下面的示例:

    def test1():
        return [1, 2, 3]
    
    
    def test2():
        print("test2=>1")
        yield 1
        print("test2=>2")
        yield 2
        print("test2=>3")
        yield 3
    
    
    print(test1())
    g = test2()
    print(next(g))
    print(next(g))
    print(next(g))
    

    输出:

    [1, 2, 3]
    test2=>1
    1
    test2=>2
    2
    test2=>3
    3

    test2()遇到yield后,会停下来,保存现场,等待下一次调用next()时,才会继续执行。

  • 相关阅读:
    软件开的目录规范+sys,os,time模块
    模块与包
    匿名函数+函数递归+二分法+面向过程编程
    快捷键
    补充叠加多个装饰器:加载顺序与执行顺序+迭代器+自定义迭代器的方式:生成器+三元表达式
    闭包函数的应用+内置函数
    函数对象+函数嵌套+名称空间与作用域+闭包函数
    SP15637 Mr Youngs Picture Permutations 高维动态规划
    LG3825/BZOJ4945/LOJ2305 「NOI2017」游戏 dfs+2-SAT
    LG1198/BZOJ1012 「JSOI2008」最大数 线段树+离线
  • 原文地址:https://www.cnblogs.com/yjmyzz/p/8907079.html
Copyright © 2020-2023  润新知