• 迭代器 生成器 推导式


    可迭代对象:
    for循环后面必须添加可迭代对象

    s1 = '123'
    for i in s1:
        print(i)
    
    for i in 123:
        print(i)  #报错,数字是不可迭代对象。'int' object is not iterable
    View Code

    内部含有__iter__方法的就是可迭代对象,遵循可迭代协议。
    dir(判断内部都有什么方法)

    print(dir('123'))       #'__inter__'
    #打印出:'__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', .....'
    View Code

    判断是不是可迭代对象:

    print('__iter__'in dir([1,2,3]))
    print('__iter__'in dir({'name':'alex'}))
    print('__iter__'in dir({'name'}))
    print('__iter__'in dir((1,2,3)))
    print('__iter__'in dir(1))    #Flase
    print('__iter__'in dir(True)) #Flase
    print('__iter__'in dir(range(10)) )
    with open('log1',encoding='utf-8')as f1:
        print('__iter__'in dir(f1))#(文件句柄)
    View Code

    文件句柄是迭代器,其他的是可迭代对象(元组,列表,字典,range)

    迭代器:
    (什么是迭代器?)
    可迭代对象通过.__iter__()可以转换成迭代器,满足迭代器协议。
    内部有__iter__且__next__方法的就是迭代器。
    l = [1,2,3]
    l_obj = l.__iter__()
    print(l_obj)
    迭代器的取值有两种方法:
    第一种:__netx__(一个next打印一个值,不可逆)

    l = [1,2,3]
    l_obj = l.__iter__()
    print(l_obj.__next__()) #1
    print(l_obj.__next__())#2
    View Code

    第二种:for 循环

    for循环怎么回事,要求必须是可迭代对象
    for循环的内部,使用的就是迭代器
    最开始,获取迭代器,然后每次执行的时候,都是__next__()

    l = [1,2,3]
    l_obj = l.__iter__()
    for i in l_obj:
        print(i)
    View Code

    判断迭代器方法:
    方法一:判断__iter__和__next__在不在dir(对象中)(很low)

    l = [1,2,3]
    l_obj = l.__iter__()
    print('__next__'in dir(l_obj))
    View Code

    方法二:(导入模块)

    from collections import Iterable#(迭代对象)
    from collections import Iterator#(迭代器)
    print(isinstance('123',Iterable))
    print(isinstance('123',Iterator))
    View Code

    实际上可迭代对象是不可以一个一个的一次取值的,因为他没有__next__方法。
    for 循环提供一个机制:
    1,将可迭代对象转化成迭代器。
    2,利用__next__进行取值。
    3,用try异常处理方法防止报错。
    面试题:处理异常 例题1

    l = [1,2,3,4,5]
    l_obj = l.__iter__()
    while True:
        print(l_obj.__next__())
    报错StopIteration  打印出1,2,3,4,5
    例题2
    l = [1,2,3,4,5]
    l_obj = l.__iter__()
    while True:
        try:
            print(l_obj.__next__())
        except StopIteration:
            pass
    例题三:
    l = [1,2,3,4,5]
    l_obj = l.__iter__()
    while True:
        try:
            print(l_obj.__next__())
        except StopIteration:
            break
    例题四:
    l = [1,2,3,4,5]
    l_obj = l.__iter__()
    while True:
        try:
            print(l_obj.__next__())
        except Exception:
            break
    try Exception(万能错误):处理万能错误报错
    View Code

    面试题:用while循环实现for循环的功能

    l = [1,2,3,4,5]
    l_obj = l.__iter__()
    while True:
        try:
            print(l_obj.__next__())
        except Exception:
            break
    #######try     Exception(万能错误):处理万能错误报错
    View Code

    为什么要有for循环?

    序列类型字符串,列表,元组都有下标,你用上述的方式访问,perfect!但是你可曾想过非序列类型像字
    典,集合,文件对象的感受,所以嘛,年轻人,for循环就是基于迭代器协议提供了一个统一的可以遍历所有
    对象的方法,即在遍历之前,先调用对象的__iter__方法将其转换成一个迭代器,然后使用迭代器协议去
    实现循环访问,这样所有的对象就都可以通过for循环来遍历了,而且你看到的效果也确实如此,这就是无所
    不能的for循环,最重要的一点,转化成迭代器,在循环时,同一时刻在内存中只出现一条数据,极大限度
    的节省了内存~

    迭代器的作用:
    1,节省内存。
    2,满足惰性机制。
    3,取值过程不可逆(一条路走到黑)。
    生成器:
    生成器本质也是迭代器,生成器是自己用python写的迭代器。
    1,通过生成器函数构建。
    2,通过生成器推导式构建。

    3,通过数据的转换也可以获取到生成器

    例题1,
    def func1():
        print(666)
        return 222
    ret = func1()
    print(ret)   #   666   222
    
    例题2,
    def func1():
        print(666)
        yield  222
    g_obj = func1()  #生成器迭代对象generator object
    print(g_obj)
    例题3
    def func1():
        print(666)
        yield  222
    g_obj = func1()
    print(g_obj.__next__())
    View Code
    有yield就是生成器 ,一个yield对应一个next:
    def func1():
        print(111)
        print(333)
        yield 222
        print(666)
        yield 777
    g_obj = func1()
    print(g_obj.__next__())
    print(g_obj.__next__())
    View Code
    例题1:做衣服10000套
    def cloth1():
        for i in range(1,10001):
            print('衣服%s'%i)
    cloth1()
    
    2,
    def cloth2():
        for i in range(1,10001):
            yield '衣服%s'%i
    g = cloth2()
    print(g.__next__())
    print(g.__next__())
    print(g.__next__())
    
    3.
    def cloth2():
        for i in range(1,10001):
            yield '衣服%s'%i
    g = cloth2()
    for i in range(1,51):
        print(g.__next__())
    View Code

    yield可以一段一段循环打印,for i in range全部循环打印

    def func1():
        print(111)   #111
        print(333)   #333
        yield 222    #222
        print(666)   #666
        yield 777    #777
        yield 888
    g_obj = func1()
    print(g_obj.__next__())
    print(g_obj.send(2))
    View Code

    send:
    1,send 具有next功能(一个send对应一个next)
    2,send可以给上一个yield传值。
    3,第一个取值不能使用send
    4,最后一个yield不会得到send的值。
    传值例子:

    def func1():
        count = yield 222
        print(count)
        yield 777
        yield 888
    g_obj = func1()   #222  2  777
    print(g_obj.__next__())
    print(g_obj.send(2))
    View Code

    send取值不能是第一个例子(会报错)

    def func1():
        count = yield 222
        print(count)
        yield 777
        yield 888
    g_obj = func1()
    print(g_obj.send(555))
    print(g_obj.send('wusir'))
    View Code
    yieldreturn 区别
    1,如果函数中包含了yeild,这个函数是一个生成器函数,执行函数的时候是:生成器
    2,生成器执行__next__(),执行到下一个yield
    3,yeild的作用和return基本相同,但是只负责返回,不会结束函数
    4,return 结束函数

    列表推导式:

    列表推导式:能用列表推到式完成的,用python代码都可以完成。
    用一句话构建一个你想要的列表。
    优点:简单,稍微难理解
    缺点:不能用debug

    创建列表1~11:
    li = []
    for i in range(1,12):
    li.append(i)
    print(i)
    列表推导式方法:
    li = [i for i in range(1,12)]
    #[变量(加工后的变量)for 变量 in 可迭代对象] 遍历模式
    print(li)
    2,
    li = []
    for i in range(1,12):
    li.append('python%s期'%i)
    print(li)

    li = ['python%s期'% i for i in range(1,12)]
    print(li)

    [变量(加工后的变量)for 变量 in 可迭代对象] 筛选模式
    1,筛选,100以内所有的奇数。

    l2 = [i for i in range(1,101) if i % 2 == 1]
    l2 = [i for i in range(1,101,2)]
    print(l2)
    View Code

    2,10以内所有书的平方。

    l2 = [i*i for i in range(1,11)]
    print(l2)
    View Code

    3,将100以内所有能被3整除的数留到列表中。

    l2 = [i for i in range(1,101) if i % 3 == 0]
    print(l2)
    View Code

    生成器表达式:
    g = (i*i for i in range(1,11))
    # print(g.__next__())
    # print(g.__next__())
    # print(g.__next__())
    for i in g:
    print(i)
    列表推导式 简单明了,但是占内存
    生成器表达式 节省内存,不易看出。
    1,把列表解析式的[]换成()得到的就是生成器表达式。
    2,列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存。
    3,python不但使用迭代器协议,让for循环变得更加通用。大部分内置函数,也是使用迭代器协议访
    问对象的。例如,sum函数是python的内置函数,该函数使用迭代器协议访问对象,而生成器实现了
    迭代器协议,所以,我们可以直接这样计算一系列值得和。
    4,30以内所有能被3整除的数的平方。

    li = [i*i for i in range(1,31)if i % 3 == 0]
    print(li)
    View Code

    5,找出名字带有两个e的名字

    names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
    ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
    l3 = [name for i in names for name in i if name.count('e') == 2]
    print(l3)
    View Code

    6,字典键值翻转:

    mcase = {'a':10,'b':34}
    mcase_frequency = {mcase[k]:k for k in mcase}
    print(mcase_frequency)
    View Code
  • 相关阅读:
    Problem 1014 xxx游戏 暴力+拓扑排序
    Codeforces Beta Round #10 D. LCIS
    HDU 1423 Greatest Common Increasing Subsequence LCIS
    Codeforces Round #349 (Div. 1) A. Reberland Linguistics dp
    BZOJ 3875: [Ahoi2014]骑士游戏 dp+spfa
    Codeforces Round #360 (Div. 2) E. The Values You Can Make 01背包
    Codeforces Round #360 (Div. 2) D. Remainders Game 中国剩余定理
    UVALive 4872 Underground Cables 最小生成树
    POJ 1182 食物链 并查集
    山东省第六届ACM省赛
  • 原文地址:https://www.cnblogs.com/ls13691357174/p/9047857.html
Copyright © 2020-2023  润新知