Python基础学习笔记(12)生成器 列表推导式 内置函数Ⅰ

Python基础学习(12)生成器 列表推导式 内置函数Ⅰ

一、今日内容大纲

  • 生成器
  • 列表推导式
  • 内置函数Ⅰ

二、生成器 generator

  1. 生成器的概念

    生成器和迭代器可以看作一种,生成器本质就是迭代器。两者唯一的区别是:生成器是我们自己利用 Python 代码构建的数据结构,而迭代器是 Python 提供的,或者利用 iter() 转化而来的。

  2. 获取生成器的方式

    • 生成器函数
    • 生成器表达式
    • Python 内置函数或者模块提供(其实1,3两种本质上差不多,都是通过函数的形式生成,只不过1是自己写的生成器函数,3是python提供的生成器函数而已)
  3. 生成器函数

    以下是我们平时使用的函数基本形式:

    # 这是我们平时的函数
    def func():
        print(111)
        print(222)
        return 3
    
    print(func())
    

    这是利用 yield 构建的生成器函数:

    # 这是生成器函数
    def func():
        print(111)  # line 26: next(ret)
        print(222)  # line 26: next(ret)
        yield 3  # line 26: next(ret)
        # 只有在下次 next(ret) 执行时才运行上次 yield 下面的代码
        print(333)  # line 27: next(ret)
        yield 4  # line 27: next(ret)
    
    # func()  # 无法运行
    ret = func()
    print(ret)  # <generator object func at 0x000002072E771FC0>
    print(next(ret))  # 3
    print(next(ret))  # 4
    print(next(ret))  # StopIteration
    

    可以看到,yield 和 return 分别构成生成器函数和函数,两者具有以下区别:

    • return:函数只存在一个 return 结束函数,并且给函数的执行者返回值
    • yield :只要函数中有 yield 那么它就是生成器函数而不是函数,生成器函数中可以存在多个 yield,yield 不会结束生成器函数,一个 yield 对应一个 next()。
    # Example 1: (这样使用其实没有意义)
    def func():
        print(111)
        return 111
        yield 222  # 只要有yield就是生成器函数
    
    ret = func()
    print(ret)  # <generator object func at 0x00000229C76E1FC0>
    # print(next(ret))  # StopIteration: 111
    
    # Example 2: 买包子
    # 先做再吃:可迭代对象
    def func():
        l1 = []
        for i in range(1, 5001):
            l1.append(f'{i}号包子')
        return l1
    
    ret = func()
    print(ret)
    # 吃一个做一个:迭代器
    def gen_func():
        for i in range(1, 5001):
            yield f'{i}号包子'
    
    ret = gen_func()
    for i in range(200):
        print(next(ret))
    
  4. yield from

    下面通过代码的形式对比一下 yield 和 yield from 的用法:

    # yield 情况
    def func():
        l1 = [1, 2, 3, 4, 5]
        yield l1
    ret = func()
    print(next(ret))  # [1, 2, 3, 4, 5]
    # yield from 情况:将列表变成迭代器返回
    def func():
        l1 = [1, 2, 3, 4, 5]
        yield from l1
    ret = func()
    print(next(ret))  # 1
    print(next(ret))  # 2
    print(next(ret))  # 3
    print(next(ret))  # 4
    print(next(ret))  # 5
    # print(next(ret))  # StopIteration
    
    # Exercise 3: 两个yield from 是顺序执行的
    def func():
        lis1 = ['weilong', 'laobinggun', 'beibingyang', 'niuyangpei']
        lis2 = ['mantou', 'huajuan', 'doubao', 'dabing']
        yield from lis1
        yield from lis2
    
    g = func()
    for i in range(8):
        print(next(g),end=' ')
    # result: weilong laobinggun beibingyang niuyangpei mantou huajuan doubao dabing
    

三、列表推导式和生成器表达式

  1. 列表推导式的概念

    利用已知的方法构建一个含有元素 1-10 的列表:

    # 构建一个1-10的列表
    list = []
    for i in range(1, 11):
        list.append(i)
    print(list)
    

    而利用列表推导式,可以仅用一行代码完成一个相对复杂且有规律的列表的构建:

    l1 = [i for i in range(1, 11)]
    
  2. 列表推导式种类

    • 循环模式: [variable(after processing) for variable in iterable]
    • 筛选模式:[variable(after processing) for variable in iterable if condition]
    # Example 1: PLS use the cycle mode
    
    # 将10以内所有整数的平方写入列表
    list = [i**2 for i in range(1, 11)]
    
    # 100以内所有的偶数写入列表
    list = [i for i in range(0, 100, 2)]
    
    # 从python1期到python100期写入列表
    list = [f'Python{i}期' for i in range(1, 101)]
    
    
    
    # Example 2: PLS use the filter mode
    
    # 30以内被3整除的数
    list = [i for i in range(1, 31) if i % 3 == 0]
    
    # 过滤掉长度小于3的字符串列表,并将剩下的转换为大写字母
    l1 = ['barry', 'ab', 'alex', 'wusir', 'xo']
    list = [str.upper() for str in l1 if len(str) >= 3]
    print(list)
    
    # 找到嵌套列表中名字含有两个'e'的所有名字
    names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
             ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
    list = [str for l1 in names for str in l1 if str.count('e') >= 2]
    print(list)
    
    
    
    # Example 3:构建一个列表:[2,3,4,5,6,7,8,9,10,'J','Q','K','A']
    l1 = [i for i in range(2, 11)] + list('JQKA')
    print(l1)
    
    
  3. 生成器推导式(生成器表达式)

    将列表推导式最外层的'[]'替换为'()'就是生成器推导式:

    # 与列表推导式的写法几乎一模一样
    list = [i for i in range(1, 11)]  # 列表推导式
    generator = (i for i in range(1, 11))  # 生成器推导式
    print(generator)  # <generator object <genexpr> at 0x00000156A5CCD0F8>
    for i in generator:  # generator 和 iterator 也是可以像可迭代对象一样for循环输出的
        print(i)
    
  4. 列表推导式的特点

    • 只能构建比较复杂且有规律的列表
    • 超过三层循环才能构建成功的,不建议使用列表推导式
    • 无法 debug
  5. 列表推导式和生成器表达式的区别

    写法上,列表推导式为[],生成器表达式为();

    本质上,列表推导式属于iterable,生成器表达式属于iterator

  6. 其他类型推导式(了解)

    • 字典推导式

      lst1 = ['jay', 'jj', 'meet']
      lst2 = ['周杰伦', '林俊杰', '元宝']
      dic = {lst2[i]: lst1[i] for i in range(len(lst1))}
      
    • 集合推导式

      print({i for i in range(1, 11)})
      

四、内置函数Ⅰ

Python 一共提供了68个内置函数,我们今天仅一带而过部分不是特别重要的内置函数:

  1. eval():全称 Evaluate,剥去字符串外衣运算内部的代码,返回去除引号的代码计算结果,尽量不要使用,容易引起病毒。网络传输、input 输入、Sql 注入等等情况绝对不可以使用!

    s1 = '1 + 3'
    print(s1)  # 1 + 3
    print(eval(s1))  # 4
    
  2. exec():全称 Execute,与eval()几乎一样,不同之处在于它用来于代码流。

    msg = """
    for i in range(10):
        print(i)
    """
    exec(msg)
    # print(eval(msg))  # SyntaxError: invalid syntax
    
  3. hash():获取一个对象(可 hash 对象包括int str bool tuple等)的哈希值。

    print(hash('123'))  # 8755506514922830437
    
  4. help():帮助。

    print(help('das'))
    print(help(str))
    print(help(str.upper))
    
  5. callable():检查一个对象是否可以调用,根据情况返回布尔值。

    def func():
        pass
    
    i = 1
    print(callable(i), callable(func))  # False True
    
  6. int() float():将字符串或数字转换为整数或浮点数(直接略去小数点)。

  7. complex(real, imag):创建一个值为real + imag * j的复数,如果输入字符串形式,无需指定第二个元素。

    print(complex(1,2))  # (1+2j)
    print(complex('1-2j'))  # (1-2j)
    
  8. bin() oct() hex():全称 binary octal hexadecimal,将十进制分别转化为二、八、十六进制的字符串并返回。

    print(bin(10), type(bin(10)))  # 0b1010 <class 'str'>
    print(oct(10), type(oct(10)))  # 0o12 <class 'str'>
    print(hex(10), type(hex(10)))  # 0xa <class 'str'>
    
  9. divmod(x, y):全称 division modulo,返回一个包含商和余数的元组(x // y, x % y)

    round():保留浮点数的小数位数,默认保留整数。

    pow():全称 power,返回x ** y,传入三个参数时的返回结果为(x ** y) % z

    print(divmod(7,2))  # (3, 1)
    print(round(7/3,2))  # 2.33
    print(round(7/3))  # 2
    print(round(3.32567,3))  # 3.326
    print(pow(2,3))  # 两个参数为2**3次幂
    print(pow(2,3,3))  # 三个参数为2**3次幂,对3取余。
    
  10. bytes():用于不同编码之间的转化。

    s = '你好'
    bs = s.encode('utf-8')
    print(bs)
    s1 = bs.decode('utf-8')
    print(s1)
    bs = bytes(s,encoding='utf-8')
    print(bs)
    b = '你好'.encode('gbk')
    b1 = b.decode('gbk')
    print(b1.encode('utf-8'))
    
  11. ord():输入字符寻找该字符编码的位置。

    chr():输入位置数字寻找其对应的字符。

    print(ord('a'))  # 97
    print(ord('中'))  # 20013
    print(chr(97))  # a
    print(chr(20013))  # 中
    
  12. repr():全称 representation,返回一个对象的 string 形式(原封不动的返回)。

    # %r 原封不动的写出来
    name = 'taibai'
    print('我叫%r'%name)  # 我叫'taibai'
    print(repr('{"name":"alex"}'))  # '{"name":"alex"}'
    print('{"name":"alex"}')  # {"name":"alex"}
    
  13. all():可迭代对象中,全都是True会返回True

    any():可迭代对象中,只要有一个True就会返回True

    print(all([1,2,True,0]))  # False
    print(any([1,'',0]))  # True
    
posted @ 2020-07-11 11:31  Raigor  阅读(113)  评论(0编辑  收藏  举报