• 第七篇:三元表达式、推导式、生成器、迭代器


    三元表达式

    num = float(input('请输入一个数字:'))
    result = '偶数' if num%2 == 0 else '奇数'
    print(result)
    
    '''类似于'''
    if num%2 == 0:
        print('偶数')
    else:
        print('奇数')

    推导式

    推导式是python提供的另一种创建数据类型的方式,有列表推导式、集合推导式、字典推导式,没有元祖推导式。

    列表推导式

    x = [1,2,3,4,5]
    y = [6,7,8,9,10]
    transfrom = [1 if i%2==0 else 0 for i in x if i > 2]
    print(transfrom)
    '''类似于'''
    transfroms = []
    for i in x:
            if i > 2:
                if i%2==0:
                    transfroms.append(1)
                else:
                    transfroms.append(0)
    print(transfroms)
    
    
    result = [i+e for i in x if i%2==0 for e in y if e%2 == 0]
    print(result)
    print(type(result))
    '''类似于'''
    results = []
    for i in x:
        for e in y:
            if i%2==0:
                if e%2==0:
                    results.append(i + e)
    print(results)
    
    
    '''1,2,3,4组成无重复三位数'''
    a = [str(i) for i in range(1,5)]
    f = [b+c+d for b in a for c in a for d in a if b != c != d != b]
    print(f)

    集合推导式

    '''1,2,3,4组成无重复三位数'''
    a = [str(i) for i in range(1,5)]
    f = {b+c+d for b in a for c in a for d in a if b != c != d != b} #把[]改为{}即可。
    print(len(f))

    字典推导式

    x = [1,2,3,4,5]
    y = [6,7,8,9,10]
    result = {i:e for i,e in zip(x,y)} #zip函数返回zip对象,被遍历时返回一个序列下标相同的元素组成的元祖
    res = {i:e for i,e in enumerate(y)} #enumerate()函数返回enumerate对象,被遍历时返回一个元祖(下标,元素)。
    print(result)
    print(type(result))
    '''类似于'''
    results = {}
    for i,e in enumerate(y):
        results[i] = e
    print(results)
    print(zip(x,y).__next__())

    生成器

    在Python中,列表,字典等序列的所有数据都在内存里,如果有海量数据,而我们仅仅需要访问几个元素的时候,那绝大多数元素占用的空间都白白浪费了。那么,有没有既想要得到庞大的数据,又想让它占用空间少的方法呢?,那就用生成器!按照某种算法不断推算出后续的元素,需要访问某个元素的时候,只需推算出,而不是从庞大的数据序列里取出

    。这样一边循环一边计算的机制,称为生成器:generator。若要访问generate对象的元素,需要调用它的__next__()函数,或把generate对象传入next()函数,一个__next__()函数只拿出一个,之后循环停止在当前位置,下一个再取值再从停止位置继续向前取值。若推算完所有元素,还调用__next__(),则会抛出StopIteration异常,next()函数也一样。

    创建生成器

    '''方式一(生成器表达式):只要把一个列表推导式式的[]改成(),就创建了一个generator对象。'''
    generate = (e for e in range(1,100,2))
    print(type(generate))
    
    #访问元素
    print(generate.__next__())
    print(generate.__next__())
    print(next(generate))  #在同一个对象里,无论调用next()或__next__()函数,它们都是接力推算的。
    print(generate.__next__())
    print(next(generate))
    print("*"*10,end='
    '*2)
    
    generate2 = (e for e in range(1,10,2)) #重新创建新对象
    for e in generate2: #for循环会不断调用__next__函数推算出后续元素,并返回它,直到捕获StopIteration异常,然后自动结束for循环。
        print(e)
    
    
    '''方式二:如果一个函数中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator。
    调用函数就是创建了一个生成器(generator)对象。yield相当于 return 返回一个值,并且记住这个返回的位置,
    下次迭代时,代码从yield的下一条语句开始执行。'''
    def test(seq):
        index = 0
        while index < len(seq):
            yield seq[index] #遇到yield时,返回一个值,执行停止,并记住该位置,下次调用__next__()时,代码从yield的下一条语句开始执行。。
            print('*'*10)
            print('上一个元素的下标是{}'.format(index))
            index += 1
    str1 = 'abcdefgh'
    generate3 = test(str1)
    print(type(generate3))
    print(generate3.__next__())
    print(generate3.__next__())
    
    #.send() 和next()一样,都能让生成器继续往下走一步(下次遇到yield停),但send()能传一个值,这个值作为yield表达式整体的结果.
    def test1():
        count = 1
        while count < 9:
            it = yield count
            print('*'*10)
            count += 1
            if it:
                print('你第{}次使用的是:send()函数传值,并赋值给了变量step,step = {}'.format(count,it))
            else:
                print('你第{}次使用的是:__next__()函数,未给变量step传值,默认值为None,step = None'.format(count))
    generate4 = test1()
    print('返回值为:{}'.format(generate4.send(None))) #不能使用send()函数向刚启动的生成器发送非空值,不然使用__next__(),否则报错。
    print('返回值为:{}'.format(generate4.send(6)))
    print('返回值为:{}'.format(generate4.send(8)))
    print('返回值为:{}'.format(generate4.__next__()))
    print('返回值为:{}'.format(generate4.send(9)))
    print('返回值为:{}'.format(generate4.__next__()))
    def permutations(iterable, r=None):
        # permutations('ABCD', 2) --> AB AC AD BA BC BD CA CB CD DA DB DC
        # permutations(range(3)) --> 012 021 102 120 201 210
        pool = tuple(iterable)
        n = len(pool)
        r = n if r is None else r
        if r > n:
            return
        indices = list(range(n))
        cycles = list(range(n, n-r, -1))
        yield tuple(pool[i] for i in indices[:r])
        while n:
            for i in reversed(range(r)):
                cycles[i] -= 1
                if cycles[i] == 0:
                    indices[i:] = indices[i+1:] + indices[i:i+1]
                    cycles[i] = n - i
                else:
                    j = cycles[i]
                    indices[i], indices[-j] = indices[-j], indices[i]
                    yield tuple(pool[i] for i in indices[:r])
                    break
            else:
                return
    View Code

    迭代器

    Iterable(可迭代对象): 有迭代能力的对象,一个类,实现了__iter__(),那么就认为它有迭代能力,通常此函数返回一个实现了__next__()的对象(虽然这个要求不强制),如果自己实现了,你可以返回self,当然这个返回值不是必须的。

    Iterator(迭代器): 迭代器(当然也是Iterable),同时实现了__iter__()__next__()的对象,缺少任何一个都不算是Iterator,其中__next__()应该在迭代完成后,抛出一个StopIteration异常。

    可以使用  collections.abc 里面的 Iterator 和  Iterable 配合  isinstance 函数来判断一个对象是否是可迭代的,是否是迭代器对象。

    我们在使用for语句的时候,python内部其实是把for后面的对象上使用了内建函数iter(),返回一个迭代器对象(Iterator),它主要映射到了类里面的__iter__()函数,此函数返回的是一个实现了__next__的对象。for语句会自动处理这个StopIteration异常以便结束for循环。

    from collections.abc import *
    list1 = [1,2,3,4,5]
    str1 = 'abcdef'
    list2iterator = iter(list1) #接受可迭代对象,返回迭代器对象。
    str2iterator = iter(str1)
    
    '''isinstance() 函数来判断一个对象是否是一个已知的类型,类似 type()。type() 不会认为子类是一种父类类型,不考虑继承关系。
    isinstance() 会认为子类是一种父类类型,考虑继承关系。'''
    print('list1是可迭代对象吗?:{} | list1是迭代器对象吗?:{}'.format(isinstance(list1,Iterable),isinstance(list1,Iterator)))
    print('str1是可迭代对象吗?:{} | str1是迭代器对象吗?:{}'.format(isinstance(str1,Iterable),isinstance(str1,Iterator)))
    print('list2iterator是可迭代对象吗?:{} | list2iterator是迭代器对象吗?:{}'.format(isinstance(list2iterator,Iterable),isinstance(list2iterator,Iterator)))
    print('str2iterator是可迭代对象吗?:{} | str2iterator是迭代器对象吗?:{}'.format(isinstance(str2iterator,Iterable),isinstance(str2iterator,Iterator)))
    
    
    class B(object):
        def __next__(self):
            raise StopIteration
    
    class A(object):
       def __iter__(self):
           return B()
    
    a = A()
    b = B()
    print(isinstance(a, Iterable))
    print(isinstance(a, Iterator))
    print(isinstance(b, Iterable))
    print(isinstance(b, Iterator))
    
    
    '''制作自己的迭代器'''
    class MyIterator():
        def __init__(self,seq):
            self.index = 0
            self.seq = seq
        def __iter__(self):
            return self
        def __next__(self):
            if isinstance(self.seq,dict):
                self.seq = list(self.seq.values())
                res = self.seq[self.index]
                self.index += 1
                return res
            else:
                if self.index < len(self.seq):
                    element = self.seq[self.index]
                    self.index += 1
                    return element
                else:
                    raise StopIteration()  #在不想继续有迭代的情况下抛出一个StopIteration的异常,由for语句会捕获这个异常,并且自动结束for。
    
    test = 'abcdef'
    testIter = MyIterator(test)
    print(isinstance(testIter,Iterable))
    print(isinstance(MyIterator,Iterable)) #__iter__()和__next__()是类的普通方法,不是类方法或静态方法,只能被实例化对象调用,所以不能通过类名判断它是否是迭代器。
    print(isinstance(MyIterator(test),Iterator))

     

  • 相关阅读:
    什么时候用resultMap,什么时候用resultType?
    Cannot create PoolableConnectionFactory解决思路
    去除list集合中重复项的几种方法-转载
    ORA-02298 定位问题
    命令行退出MySQL和登录MySQL
    CX4-480服务器数据恢复过程(服务器数据恢复通用方法)
    也谈腾讯云的静默损坏
    raid5阵列两块硬盘离线怎么解决
    服务器卷删除初检报告/数据恢复成功率分析
    服务器两块硬盘离线如何恢复数据
  • 原文地址:https://www.cnblogs.com/us-wjz/p/10909392.html
Copyright © 2020-2023  润新知