• Python 的一些高级特性


    好的代码应当是简洁易懂易维护的,所以代码不是越多越好,也不是越复杂越好。
    在工作中,如果刻意得去炫技,故意写一些复杂的、难以看懂的代码,会导致这代码只有你自己能看懂,甚至一段时间之后,你自己也会看不懂。
    等你离职了,下一个接手项目的人在看代码的时候会非常痛苦,心里一定在骂你。
    要达到这样的要求,除了给代码写注释,最好掌握一些 Python 内置的、高效的高级特性。

    切片

    切片的语法是这样:[start:end:d]
    其中:

    • start:起始下标(能取到)
    • end:结束下标(取不到)
    • d:差值(默认为 1)

    截取 str、list 或 tuple 的部分元素是很常见的需求。

    demo_str = "python"
    demo_list = ["p", "y", "t", "h", "o", "n"]
    demo_tuple = ("p", "y", "t", "h", "o", "n")
    

    用切片取前三个元素:

    demo_str[0:3] # 'pyt'
    demo_list[:3] # ['p', 'y', 't']
    

    切片的取值区间是左闭右开[0:3] 是区间 [0, 3)。第一个索引如果是 0,可简写成这样:[:3]

    下标当然也可以是负数,比如:

    demo_str[-1:-3:-1] # 'no'
    

    起始下标为 -1,对应元素 'n';结束下标为 -3,对应元素 'h',取不到,所以取到元素 'n'。差值 -1 的正负号其实可以理解为取值的方向,负号就是按照负方向取值。

    根据这个例子可以写出一个反转字符串的功能:

    demo_str[-1::-1] # 'nohtyp'
    

    迭代

    迭代就是遍历。
    判断一个对象是否可迭代可以这样:

    from collections.abc import Iterable
    
    isinstance("python", Iterable) # True
    isinstance(123, Iterable) # False
    

    遍历的时候想要拿到下标可以这样:

    for index, value in enumerate("python"):
        print(index)
        print(value)
    

    列表推导式

    如果要得到一个这样的列表:[0, 1, 2, 3, 4],常规的方法是这样:

    demo_list = []
    for i in range(5):
        demo_list.append(i)
    print(demo_list) # [0, 1, 2, 3, 4]
    

    列表推导式其实就是把这个代码简写成一行:

    demo_list = [i for i in range(5)]
    print(demo_list) # [0, 1, 2, 3, 4]
    

    可以对每个追加的值做处理:

    demo_list = [i + 1 for i in range(5)]
    print(demo_list) # [1, 2, 3, 4, 5]
    

    如果对于有判断条件的也是可以简写的,比如要得到 [1, 3, 5, 7, 9]

    demo_list = []
    for i in range(11):
        if i % 2 != 0:
            demo_list.append(i)
    print(demo_list) # [1, 3, 5, 7, 9]
    

    列表推导式写法:

    demo_list = [i for i in range(11) if i % 2 != 0]
    print(demo_list) # [1, 3, 5, 7, 9]
    

    不支持 else 条件。

    两层循环也是可以的:

    demo_list = []
    for i in range(2):
        for j in range(2):
            demo_list.append(i + j)
    print(demo_list) # [0, 1, 1, 2]
    

    用列表推导式简写为:

    demo_list = [i + j for i in range(2) for j in range(2)]
    print(demo_list) # [0, 1, 1, 2]
    

    三层及以上的循环虽然也可以,但是写出来太长,不如不用。

    生成器

    当列表元素有几百万时,会很占内存,性能很差。平时练习时基本不会遇到,但实际的项目中这种情况很常见。
    这时最好有一种算法,能够推导出列表的每个值,这样既可以拿到元素又可以节省内存,提高性能,这个算法就是生成器。

    把列表推导式的 [] 改为 () 就创建了一个生成器。

    demo_str = [i for i in range(5)]
    print(demo_str) # [0, 1, 2, 3, 4]
    demo_str = (i for i in range(5))
    print(demo_str) # <generator object <genexpr> at 0x7f2918149f20>
    

    依次访问生成器元素

    next(demo_str) # 0
    next(demo_str) # 1
    next(demo_str) # 2
    next(demo_str) # 3
    next(demo_str) # 4
    next(demo_str) # 报错:StopIteration
    

    遍历生成器

    for i in demo_str:
        print(i)
    # 0
    # 1
    # 2
    # 3
    # 4
    

    生成器只能访问一次,再次访问就没有值了。

    可以将函数改写成生成器,拿生成斐波那契数列实验:

    从第三个数开始,每个数都等于前两个数之和。

    常规函数:

    def fib(first:int, second:int, max_value:int):
        print(first)
        print(second)
        num = second
        while num < max_value:
            first, second = second, num
            num = first + second
            if num >= max_value:
                break
            print(num)
    # fib(1, 1, 10)
    # 1
    # 1
    # 2
    # 3
    # 5
    # 8
    

    改写成生成器:

    def fib(first:int, second:int, max_value:int):
        yield first
        yield second
        num = second
        while num < max_value:
            first, second = second, num
            num = first + second
            if num >= max_value:
                break
            yield num
    
    result = fib(1, 1, 10)
    for i in result:
        print(i)
    # 1
    # 1
    # 2
    # 3
    # 5
    # 8
    

    判断一个对象是否是生成器

    from collections.abc import Generator
    
    demo_list = (i for i in range(5))
    print(isinstance(demo_list, Iterator)) # True
    

    判断是否是迭代器是 isinstance(demo_list, Iterator)

    IteratorIterable 不是一回事:

    list、str、dict、生成器都是 Iterable,但 list、str、dict 不是 Iterator

    (本文完)

  • 相关阅读:
    php 使用正则匹配中文 返回结果
    怎样判断一个jquery对象是否为空jquery对象
    关于tp5.0中对象数组转换普通数组使用助手函数collection而不是toArray
    PHP 面试题三
    PHP 面试题二
    PHP 面试题 一
    laravel 学习笔记 —— 神奇的服务容器
    ubuntu下安装opencv库+Python2.7环境安装及开发摄像头拍照应用
    Linux内核分析(七)----并发与竞态
    Linux内核分析(六)----字符设备控制方法实现|揭秘系统调用本质
  • 原文地址:https://www.cnblogs.com/junsircoding/p/15664973.html
Copyright © 2020-2023  润新知