美文网首页
Python 解析式、生成器

Python 解析式、生成器

作者: Alexander_Zz | 来源:发表于2021-01-05 10:48 被阅读0次

    一、标准库 datetime

    1.1 datetime 模块
    • 对日期、时间、时间戳的处理
    1.2 datetime
    • 类方法
      a. today() 返回本地时区当前时间的 datetime 对象
      b. now(tz=None) 返回当前时间的 datetime 对象,精确至微秒,若 tzNone,返回同 today()
      c. utcnow() 没有时区的当前时间
      d. fromtimestamp(timestamp, tz=None) 从一个时间戳返回一个 datetime 对象
    1.3 datetime 对象
    • timestamp() 返回一个到微秒的时间戳
      a. 时间戳:格林威治时间 1970 年 1 月 1 日 0 点到现在的秒数

    • 构造方法 datetime.datetime(2020, 12, 6, 16, 29, 43, 79043)

    • yearmonthdayhourminutesecondmicrosecond,取 datetime 对象的年月日时分秒及微秒

    • weekday() 返回周几,周一为 0,周日为 6

    • isoweekday() 返回周几,周一为 1,周日为 7

    • date() 返回日期 date 对象

    • time() 返回时间 time 对象

    • replace() 修改并返回新的时间

    • isocalendar(0 返回一个三元组(年,周数,周几)

    1.4 日期格式化
    • 类方法 strptime(date_string, format),返回 datetime 对象

    • 对象方法 strftime(format),返回字符串

    • 字符串 format 函数格式化

    import datetime
    
    dt = datetime.datetime.strptime("08/12/20 16:30", "%d/%m/%y %H:%M")
    
    print(dt.strftime("%Y-%m-%d %H:%M:%S"))
    print("{0:%Y}/{0:%m}/{0:%d} {0:%H}::{0:%H}::{0:%S}".format(dt))
    print('{:%Y-%m-%d %H:%M:%S}'.format(dt))
    
    示例.png
    1.5 timedelta 对象
    • datetime2 = datetime1 + timedelta
    • datetime2 = datetime1 - timedelta
    • timedelta = datetime1 - datetime2
    • 构造方法
      a. datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)
      b. year = datetime.timedelta(days=365)
    • total_seconds() 返回时间差的总秒数

    二、标准库 time

    2.1 time
    • time.sleep(secs) 将调用线程挂起指定的秒数

    三、列表解析

    3.1 举例
    • 生成一个列表,元素 0 ~ 9,对每一个元素自增 1 后求平方返回新列表
    lst = list(range(10))
    newlst = list()
    
    for i in lst:
        newlst.append((i+1) ** 2)
    print(newlst)
    
    
    lst = list(range(10))
    newlst = [ (i + 1) ** 2 for i in lst]
    print(newlst)
    
    示例.png
    3.2 语法
    • [ 返回值 for 元素 in 可迭代对象 if 条件]
    • 使用中括号 [],内部是 for 循环,if 条件语句可选
    • 返回一个新列表
    3.3 列表解析式是一种语法糖
    • 编译器会优化,不会因为简写而影响效率,反而因优化提高了效率
    • 减少程序员工作量,减少出错
    • 简化了代码,但可读性增强
    3.4 举例
    • 获取 10 以内的偶数,比较执行效率
    even = []
    
    for i in range(10):
        if i % 2 == 0:
            even.append(i)
    
    even = [ i for i in range(10) if i % 2 == 0]
    
    示例.png
    • 思考
      1. 有这样的赋值语句 newlist = [print(i) for i in range(10)],请问打印出什么?newlist 打印出来是什么?

        示例.png
      2. 获取 20 以内的偶数,若同时 3 的倍数也打印 [i for i in range(20) if i % 2 == 0 elif i % 3 ==0] 行么?

        示例.png

    四、列表解析进阶

    4.1 [expr for item in iterable if cond1 if cond2]
    • 等价于
    ret = []
    
    for item in iterable:
        if cond1:
            if cond2:
                ret.appent(expr)
    
    • 举例
      • 20 以内,既能被 2 整除又能被 3 整除的数
      [i for i in range(20) if i %2 == 0 and i % 3 == 0]
      
      [i for i in range(20) if i 5 2 == 0 if i % 3 == 0]
      
    示例.png
    4.2 [expr for i in iteranle1 for j in iterable2]
    • 等价于
    ret = []
    
    for i in iterable1:
        for j in iterable2:
            ret.append(expr)
    
    • 举例
      [(x, y) for x in 'abcde' for y in range(3)]
      [[x, y] for x in 'abcde' for y in range(3)]
      [{x, y} for x in 'abced' for y in range(3)]   # 集合是整个生成列表中的元素,不会去重
      [{x: y} for x in 'abced' for y in range(3)]   # 字典与集合相同,不会去重
      
    示例.png 示例.png 示例.png 示例.png
    4.4 请问下面 3 中输出各是什么?为什么
    [(i,j) for i in range(7) if i>4 for j in range(20,25) if j>23]
    [(i,j) for i in range(7) for j in range(20,25) if i>4 if j>23]
    [(i,j) for i in range(7) for j in range(20,25) if i>4 and j>23]
    
    示例.png

    五、列表解析练习

    5.1 练习(要求使用列表解析式完成)
    • 返回 1 - 10 平方的列表
    [i ** 2 for i in range(11) if i > 0 ]
    
    示例.png
    • 有一个列表 lst = [1, 4, 9, 16, 2, 5, 10, 15],生成一个新列表,要求新列表元素是 lst 相邻 2 项的和
    lst = [1, 4, 9, 16, 2, 5, 10, 15]
    [lst[i] + lst[i+1] for i in range(len(lst)) if i < (len(lst)-1)]
    
    示例.png

    六、生成器表达式 Generator expression

    6.1 语法
    • (返回值 for 元素 in 可迭代对象 if 条件)
    • 列表解析式中的括号换成小括号即可
    • 返回一个生成器
    示例.png
    6.2 和列表解析式的区别
    • 生成器表达式是 按需计算(或称 惰性求值、延迟计算),需要的时候才计算值
    • 列表解析式是立即返回值
    示例.png
    6.3 生成器
    • 可迭代对象
    • 迭代器
    示例.png
    6.4 举例
    g = ("{:04}".format(i) for i in range(1,11))
    next(g)
    for x in g:
        print(x)
    print('~~~~~~~~~~~~')
    for x in g:
        print(x)
    
    • 列表对比
    g = ["{:04}".format(i) for i in range(1,11)]
    for x in g:
        print(x)
    print('~~~~~~~~~~~~')
    for x in g:
        print(x)
    
    6.5 总结
    • 生成器

      1. 延迟计算
      2. 返回迭代器,可迭代
      3. 从前到后走完一遍,不能回头
    • 列表

      1. 立即计算
      2. 返回的不是迭代器,返回可迭代对象列表
      3. 从前导后走完一遍,可重新回头迭代
    6.6 习题
    it = (print("{}".format(i+1)) for i in range(2))
    first = next(it)
    second = next(it)
    val = first + second
    
    • val 的值是什么
    print() 函数是立即返回,所以不论是 first 还是 second 的值都是 None
    所以 val 的运算结果会抛异常
    
    示例
    • val = first + second 语句之后能否再次 next(it)
    不可以 next() 了,因为此前的计数器是 range(2),程序已经迭代两次,所以不可再次 next()
    
    示例.png
    it = (x for x in range(10) if x % 2)
    first = next(it)
    second = next(it)
    val = first + second
    
    • val 的值是什么?
    val 的值为 4
    
    示例.png
    • val = first + second 语句后能否再次 next(it)
    因为此前计数器并未迭代完,所以可以继续 next() 调用
    
    示例.png
    6.7 和列表解析式的对比
    • 计算方式
      1. 生成器表达式延迟计算,列表解析式立即计算
    • 内存占用
      1. 单从返回值本身来说,生成器表达式
      2. 生成器没有数据,内存占用极少,它是使用时一个个返回数据,若将这些返回的数据合起来占用的内存和列表解析式差不多,但是,它不需要立即占用这么多内存
      3. 列表解析式构造新的列表需要立即占用内存,不管你是否立即使用这么多数据
    • 计算速度
      1. 但看计算时间,生成器表达式耗时非常短,列表解析式耗时长
      2. 但生成器本身并没有返回任何值,只返回了一个生成器对象
      3. 列表解析式构造并返回了一个新的列表,所以开起来耗时了

    七、集合解析式

    7.1 语法
    • { 返回值 for 元素 in 可迭代对象 if 条件 }
    • 列表解析式的中括号换成大括号 {} 即可
    • 立即返回一个集合
    7.2 用法
    • {(x, x+1) for x in range(10)}

    • {[x] for x in range(10)}

    八、字典解析式

    8.1 语法
    • { 返回值 for 元素 in 可迭代对象 if 条件 }
    • 列表解析式中的括号换成大括号 {} 即可
    • 使用 key:value 形式
    • 立即返回一个字典
    8.2 用法
    • {x:(x, x+1) for x in range(10)}
    • {x:[x, x+1] for x in range(10)}
    • {(x,):[x, x+1] for x in range(10)}
    • {[x]:[x, x+1] for x in range(10)}
    • {chr(0x41 +x):x**2 for x in range(10)}
    • {str(x):y for x in range(3) for y in range(4)}
    • 等价于
    ret = {}
    for x in range(3):
        for y in range(4):
            ret[str(x)] = y
    

    九、总结

    • Python 2 引入列表解析式
    • Python 2.4 引入生成器表达式
    • Python 3 引入集合、字典解析式,并迁移至 Python 2.7
    • 一般来说,应该多应用解析式,简短、高效
    • 若一个解析式非常复杂,难以读懂,可考虑拆解成 for 循环
    • 生成器和迭代器是不同的对象,但都是可迭代对象
    • 可迭代对象范围更大,都可使用 for 循环遍历

    相关文章

      网友评论

          本文标题:Python 解析式、生成器

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