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

三元表达式

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='\n'*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__()))

迭代器

  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))

 

猜你喜欢

转载自www.cnblogs.com/us-wjz/p/10909392.html