• Python基础(十一)


    今日主要内容

    • 补充:三目运算
    • f-strings
    • 迭代器
    • 生成器

    补充:三目运算

    1. 三目运算(三元运算)结构:
    • 表达式1 if 条件表达式 else 表达式2
    • c = a if a > b else b
    1. 执行流程:

      • 判断条件,如果条件正确将a赋值给c
      • 如果条件不正确将b赋值给c
      a = 10
      b = 20
      c = a if a > b else b  # 三目运算
      print(c)
      
      运行结果:
      20
      

    一、f-strings

    • f-strings之前我们已经说过了,python3.6以上的版本可以使用,用来格式化输出,非常的方便,今天来详细说一下
    1. f-strings的格式:

      • f"xxxx{传入的变量}xxxx"(建议使用f
      • F"xxxx{传入的变量}xxxx"(不建议使用F
      name = "zxd"
      age = 23
      print(f"姓名:{name} 年龄:{age}")
      
      运行结果:
      姓名:zxd 年龄:23
      
    2. 引号中如果需要大括号{}时,用两个{{}}代表

      print(f"{{'a'}}")  # 用两个大括号表示
      
      运行结果:
      {'a'}
      
    3. 引号中需要使用引号时,一定用两个单引号''表示

      print(f"{{'a'}}")  # 用单引号表示
      
      运行结果:
      {'a'}
      
    4. 传入的参数可以是三目表达式

      a = 10
      b = 10
      print(f"{a if a > b else b}")
      
      运行结果:
      10
      

    二、迭代器

    (一)可迭代对象

    • 说迭代器之前咱们来看一看可迭代对象,什么是可迭代对象?

      • 可以一个一个取值的对象就是可迭代对象
      s = "12345"
      lst = [1, 2, 3, 4, 5]
      dic = {1: 1, 2: 2, 3: 3}
      .......
      
      # 这些都是可迭代对象
      
      • 他们共有的一个特点就是可以被for循环
      s = "12345"
      lst = [1, 2, 3, 4, 5]
      dic = {1: 1, 2: 2, 3: 3}
      
      for el in s:
      	print(el)
      for el in lst:
      	print(el)
      for el in dic:
      	print(el)	
      
    1. 查看可迭代对象的官方方法:

      • 查看对象是否有__iter__()方法,只要使用有此方法的对象全部都是可迭代对象
      • dir()函数可以查看对象所有的方法
      lst = [1, 2, 3, 4, 5]
      print("__iter__" in dir(lst))
      
      运行结果:
      True
      
    2. 可迭代对象的特点:

      • 空间换时间的理念(用大量的空间节省时间)
      • 优点:
        • 使用灵活,每个可迭代对象都有自己的方法
        • 能够直接查看元素个数
        • 可以重复取值
      • 缺点:
        • 占内存
    3. 应用:内存空间大,当数据量比较少,建议使用可迭代对象

    (二)迭代器

    • 迭代器可以理解成可迭代对象的实体化,它只继承了迭代性(可以一个一个取值),同时节约了内存(唯一的优点)
    • 文件句柄就是一个迭代器
    1. 迭代器的生成方法:

      • 两种生成方法效果相同
      • iter(可迭代对象)
        • 生成可迭代对象的迭代器
        • 打印的是迭代器的地址
      lst = [1, 2, 3, 4, 5]
      l = iter(lst)
      print(l)
      
      运行结果:
      <list_iterator object at 0x0000020BAFCEA940>
      
      
      • 可迭代对象.__iter__()
        • 生成可迭代对象的迭代器
        • 打印的是迭代器的地址
      lst = [1, 2, 3, 4, 5]
      l = lst.__iter__()
      print(l)
      
      运行结果:
      <list_iterator object at 0x000002490EFDA8D0>
      
      
    2. 迭代器的取值

      • 迭代器最大的特点就是惰性机制,如果不主动向迭代器取值,迭代器是不会给你值的,同时也正因为惰性机制节约了内存
      • next(迭代器)
      lst = [1, 2, 3, 4, 5]
      l = iter(lst)
      print(next(l))
      print(next(l))
      print(next(l))
      print(next(l))
      print(next(l))
      
      运行结果:
      1 2 3 4 5
      
      
      • 迭代器.__next__()
      lst = [1, 2, 3, 4, 5]
      l = lst.__iter__()
      print(l.__next__())
      print(l.__next__())
      print(l.__next__())
      print(l.__next__())
      print(l.__next__())
      
      运行结果:
      1 2 3 4 5
      
      
      • 每次执行取值函数只向迭代器取一个值,按顺序向下取值,不能重复取值,迭代器中有多少个元素就只能next多少次,超出最大个数会报错
      lst = [1, 2, 3, 4, 5]
      l = lst.__iter__()
      print(l.__next__())
      print(l.__next__())
      print(l.__next__())
      print(l.__next__())
      print(l.__next__())
      print(l.__next__())
      
      运行结果:
      1 2 3 4 5
      StopIteration
      
      
    3. 迭代器的特点:

      • 时间换空间理念(用大量的时间去节省空间)
      • 节省内存
      • 惰性机制
      • 只能向下取值,不能往复
    4. for循环的本质就是一个迭代器

      • 捕获异常:向迭代器取值超出迭代器元素数量时,会捕获StopIteration异常,从而终止while循环
      lst = [1, 2, 3, 4, 5]
      l = iter(lst)
      while True:
      	try:
      		print(next(l))
      	except StopIteration:  # 捕获异常
      		break
      
      
    5. 向同一个迭代器取值,迭代器内部会记录取值位置,赋值给变量,变量会指向地址和上次取值位置

      lst = [1, 2, 3, 4, 5]
      l_iter = iter(lst)
      print(next(l_iter))
      print(next(l_iter))
      print(next(l_iter))
      print(next(l_iter))
      print(next(l_iter))  # l_iter指向取值记录位置
      
      运行结果:
      1 2 3 4 5
      
      
      • l_iter指向迭代器的地址,每一次取值,l_iter指向上一次取值位置
      • 可以理解成通过熟人买东西,每次买都是上次的优惠价
    6. 向同一个迭代器取值,迭代器内部会记录取值位置,若不赋值,每一次取值都从开头取值,相当于每次寻址后都从头开始

      lst = [1, 2, 3, 4, 5]
      print(next(iter(lst)))
      print(next(iter(lst)))
      print(next(iter(lst)))
      print(next(iter(lst)))
      print(next(iter(lst)))
      print(next(iter(lst)))  # 每次都从头开始取值
      
      运行结果:
      1 1 1 1 1
      
      
      • 没有赋值每次通过func()直接寻址,都从头部开始取值
      • 可以理解成没有熟人了,每次买东西都是原价
    7. 应用:内存小,数据量巨大时,建议使用迭代器

    (三)两者关系

    • 迭代器一定是可迭代对象,可迭代对象不一定是迭代器
    • 迭代器可以通过iter(可迭代对象)可迭代对象.__iter__()得到

    三、生成器

    (一)什么是生成器

    • 生成器的本质就是迭代器

    • 生成器就是一个自己写的迭代器,而迭代器只能通过iter()函数得到

    • 生成器的目的是不通过数据转换实现,通过代码实现

      • 列表转换成了迭代器,但是列表依旧加载到了内存,没有达到省内存的效果
      lst = [1, 2, 3, 4, 5]
      l_iter = iter(lst)
      print(next(l_iter))
      print(next(l_iter))
      print(next(l_iter))
      print(next(l_iter))
      print(next(l_iter))
      
      运行结果:
      1 2 3 4 5
      
      
      • 通过生成器真正达到省内存的效果
      def func():
      	yield 1
      	yield 2
      	yield 3
      	yield 4
      	yield 5
      
      f_gen = func()
      print(next(f_gen))
      print(next(f_gen))
      print(next(f_gen))
      print(next(f_gen))
      print(next(f_gen))
      
      运行结果:
      1 2 3 4 5
      
      

    (二)生成器

    1. 通过函数实现生成器

      • 先来看一个函数
      def func():
      	print(1)
      	return 1
      	
      print(func())
      
      运行结果:
      1 1
      
      
      • 将函数中return替换成yield就变成了一个生成器
      def func():
      	print(1)
      	yield 1
      	
      print(func())
      
      运行结果:
      <generator object func at 0x000001B27042C50>
      
      
      • 如果定义的是函数,函数名加括号是调用函数;而如果定义的是生成器,函数名加括号是得到的是生成器的内存地址
      • yield
        • yield能返回多个值,以元组形式存储
        • yield能返回各种数据类型
        • yield能够写多个并且都能执行
        • yield能够记录执行位置
        • yield后面不写内容,默认返回None
        • yield只能向下进行,不能往复,一次性取值
    2. 生成器的取值

      • next(生成器)
      def func():
      yield 1
      	yield 2
      yield 3
      	yield 4
      yield 5
      
      f_gen = func()
      print(next(f_gen))
      print(next(f_gen))
      print(next(f_gen))
      print(next(f_gen))
      print(next(f_gen))
      
      运行结果:
      1 2 3 4 5
      
      
      • 生成器.__next__()
      def func():
      	yield 1
      yield 2
      	yield 3
      	yield 4
      	yield 5
      	
      print(func().__next__())
      print(func().__next__())
      print(func().__next__())
      print(func().__next__())
      print(func().__next__())
      
      运行结果:
      1 2 3 4 5
      
      
    3. 生成器的本质就是一个迭代器,所以它拥有迭代器的所有特点

      • 时间换空间理念(用大量的时间去节省空间)
      • 节省内存
      • 惰性机制
      • 只能向下取值,不能往复
    4. 向同一个生成器取值,yield会记录取值位置,赋值给变量,变量会指向地址和上次取值位置

      def func():
      	yield 1
      	yield 2
      	yield 3
      	yield 4
      	yield 5
      
      f_gen = func()
      print(next(f_gen))
      print(next(f_gen))
      print(next(f_gen))
      print(next(f_gen))
      print(next(f_gen))  # f_gen指向生成器地址和yiele记录的位置
      
      运行结果:
      1 2 3 4 5
      
      
    5. 向同一个生成器取值,yield会记录取值位置,若不赋值,每一次取值都从开头取值,相当于每次寻址后都从头开始

      def func():
      	yield 1
      	yield 2
      	yield 3
      	yield 4
      	yield 5
      
      print(next(func()))
      print(next(func()))
      print(next(func()))
      print(next(func()))
      print(next(func()))  # 每次都从头开始取值
      
      运行结果:
      1 2 3 4 5
      
      
    6. 若yield的值是个可迭代对象,还可以将其对象逐个返回

      • yield from
      def func():
      	yield from [1, 2, 3]
      	yield from [4, 5, 6]
      	
      print(next(func()))
      print(next(func()))
      print(next(func()))
      print(next(func()))
      print(next(func()))
      print(next(func()))
      
      运行结果:
      1 2 3 4 5 6
      
      

    四、三者区分

    (一)可迭代对象

    • 只要是可以使用__iter__()方法的对象都是可迭代对象
    • 迭代器和生成器都是可迭代对象

    (二)迭代器

    • 查看对象的内存地址,如果有iterator就是一个迭代器
    • 拥有__iter__()__next__()放法的就是一个迭代器

    (三)生成器

    • 查看对象的内存地址,如果有generator就是一个生成器
    • 可以使用send()方法的就是一个生成器
  • 相关阅读:
    命令行打开无线网络设置
    WebView2 的使用记录
    QT-Mac:在Mac下实现QT程序的打包及公证
    QT:CEF实现js函数与C++函数的异步调用
    QT-Mac:QT Creator 中QT Versions显示无效的QT版本的解决办法
    QT-Mac: Undefined symbols for architecture x86_64
    全局键盘钩子失效与WebRTC的关系分析
    第十二届蓝桥杯决赛 大学 B 组 C/C++ 做题记录
    Luogu P2671 求和 | 数学奇偶性&前缀和
    2021铁三决赛 PWN cardstore | 格式化字符串 & ret2libc
  • 原文地址:https://www.cnblogs.com/tianlangdada/p/11567942.html
Copyright © 2020-2023  润新知