从零学习python - 11推导式 \生成器与迭代器

推导式 

# 列表推导式 [] 可以通过简单的语法

        对列表进行操作后返回符合条件的新列表 new_list = [x for x in list]

# 原列表
dict1 = {'name': 'aoa', 'age': 22, 'sex': 'boy'}
dict2 = {'name': 'bob', 'age': 23, 'sex': 'girl'}
dict3 = {'name': 'coc', 'age': 19, 'sex': 'girl'}
dict4 = {'name': 'dod', 'age': 18, 'sex': 'boy'}
list1 = [dict1, dict2, dict3, dict4]
# 返回list1中性别为boy的人
# 使用if结构跟着遍历后面
new_list = [user for user in list1 if user.get('sex') == 'boy']
print(new_list)  # [{'name': 'aoa', 'age': 22, 'sex': 'boy'}, {'name': 'dod', 'age': 18, 'sex': 'boy'}]
# 如果年纪低于20则加1岁 如果年纪大于20则加两岁
# 使用if... else ... 结构 是要放在for遍历前面 (有点类似于三目运算符)
new_list2 = [user['age'] + 1 if user.get('age') < 20 else user['age'] + 2 for user in list1]
print(new_list2) # [{'name': 'aoa', 'age': 22, 'sex': 'boy'}, {'name': 'dod', 'age': 18, 'sex': 'boy'}]
# 集合推导式 {} 格式用法相同 但集合会去除重复元素
list_num = [1, 1, 2, 2, 3, 3, 4, 4, 5, 5]
set_num = {num+1 for num in list_num if num > 2}
print(set_num)      # {4, 5, 6}
# 字典推导式 将下面字典的key和value值互换位置
# 字典推导式 将下面字典的key和value值互换位置
dict_test = {'a': 'A', 'b': 'B', 'c': 'C', 'd': 'C'}
# dict.items()按元组返回字典内存放数据    常用遍历方法 for k,v in dict.items()
dict_fix = {value: key for key, value in dict_test.items()}
# 如果两个值相同,当k,v互换位置时只会保留最后一个元素的k,v
print(dict_fix)     # {'A': 'a', 'B': 'b', 'C': 'd'}

生成器

# 生成器: 使用列表推导式创建的新列表会受到内存的限制,列表容量有限.如果我们仅仅访问前面几个元素的话,还会浪费后面没有使用到的元素占用的空间.所以,如果列表元素可以按照某种算法推算出来,我们就可以一边循环一边推算出后续的元素来使用.
# 这种方法不用创建完整的list,节省空间.这种方法被成为生成器
# 得到生成器的方式:
# 1-通过列表推导式得到生成器:如果我们想用列表推导式来实现 只需要把[]换成()就可以
#    实现得到[0,3,6,9,...,27]
#    下面首先用列表推导式得到结果 这时这个list1会一直占用内存空间
list1 = [num*3 for num in range(10)]
print(list1)    # [0, 3, 6, 9, 12, 15, 18, 21, 24, 27]
#    如果我们想用列表推导式来实现 只需要把[]换成()就可以
g1 = (num*3 for num in range(10))
print(g1)    #  at 0x00000237C61042E0> 这表示g1是一个生成器对象
print(g1.__next__())     # 0
print(g1.__next__())     # 3
print(g1.__next__())     # 6
print(next(g1))     # 9 有两种方法得到生成器中的元素 一个是g1.__next__() 还有系统自带函数 next(g1) 只有执行才会得到元素数值
# 我们可以使用循环来将g1生成器中的元素全部打印出来 如果前面有方法(__next__或者next(g1))拿走了其中的元素 那么我们后面的循环只会拿到剩余的元素
while True:
    try:
        print(next(g1))
    except:
        print('没有更多元素了!')
        break
# 得到生成器的方法:
# 2-借助函数完成  定义一个函数并使用yield关键字 调用函数并接收调用的结果 得到的结果就是生成器 yield关键字作用相当于 (return 并在这暂停)
#   只要函数中出现yield关键字,就说明这个函数不是函数了,已经变成生成器了   (yield n) 相当于 (return n + 暂停)操作
def get_num():
    n = 0
    while True:
        n += 1
        # print(n)
        #  (yield n) 相当于 (return n + 暂停)操作 当每调用一次next(g2)\g2.__next__()时,就会跳转到这个关键字位置继续往下执行
        yield n


g2 = get_num()  # g2是一个生成器对象
print(g2)   # 
print(next(g2))     # 1
# **练习 斐波那契数列
def fib(length):
    a, b = 0, 1
    n = 0

    while n < length:
        yield b     # 这里相当于return b后暂停住 等下个next(g3)调用时 接着往下执行
        a, b = b, a+b
        n += 1
    # 当生成器没有东西产生后 可以使用return返回一个语句以报错信息的形式提示
    return '没有更多元素了!'


g3 = fib(8)
print(next(g3))     # 1
print(next(g3))     # 1
print(next(g3))     # 2
print(next(g3))     # 3
print(next(g3))     # 5
print(next(g3))     # 8
print(next(g3))     # 13
print(next(g3))     # 21
# print(next(g3))     # StopIteration: 没有更多元素了!
# 生成器方法: 
    __next__(): 获取yield后的元素
    send(value):向每次生成器中传value 第一次调用要传入None 因为第一次会在yield暂停返回 所以不传None的话会报错
    当遇到yield关键字程序(return并暂停)后 send相当于程序在这个位置再次启动 并传进去一个值继续往下执行!就相当于 temp=message_test_01 我们send('参数')传过去的参数在yield关键字这个位置替换后重新启动!
    send()函数会将yield后的n返回 我们可以用参数接一下
def gen_test():
    n = 0
    while n < 5:
        temp = yield n
        print(f'temp={temp}')
        n += 1
    return '没有更多元素了'


g4 = gen_test()
n0 = g4.send(None)
print(f's0 = {n0}')     # n0 = 0

n1 = g4.send('message_test_01')     # temp=message_test_01
print(f's1 = {n1}')     # n1 = 1

n2 = g4.send('message_test_02')     # temp=message_test_02
print(f's2 = {n2}')     # n2 = 2

print(g4.send('test3'))     # 3
# 生成器应用场景
# 进程 > 线程 > 协程 协程就是用生成器完成的
# 生成器的多应用
# 搬一块砖听一首歌曲,如果没有生成器的话程序执行顺序将会是先搬完砖再听歌,
# 如果使用生成器就可以控制程序运行.
# 生成器的多应用
def task1(n):
    for i in range(n):
        print(f'正在搬砖第{i + 1}块')
        yield
    # return '搬完了'


def task2(n):
    for i in range(n):
        print(f'正在听歌第{i + 1}首')
        yield
    # return '听完了'


g1 = task1(5)
g2 = task2(5)
while True:
    try:
        g1.__next__()
        g2.__next__()
    except:
        print('干完活儿了!')
        break

迭代器

# 迭代:访问集合元素的一种方式,迭代器是一个可以记住遍历的位置的对象
#   迭代器对象只能从第一个元素开始访问,直到所有元素被访问完毕后结束
#   迭代器只能往前不能后退
#   可以被 next(对象) 函数调用并且不断返回下一个值的对象被称为迭代器:Iterator
# 可迭代的不一定就是迭代器 -> 生成器是可迭代的对象,是迭代器  字符串-列表-元组-集合-字典也是可迭代的,但不是迭代器
# 上述可迭代对象但不是迭代器的,可以使用方法 iter(字符串\列表\元组\集合\字典)来返回一个迭代器从而进行操作

 


print(isinstance('abcdefg', Iterable))  # True
list1 = [1, 2, 3, 4]
print(isinstance(list1, Iterable))  # True
tuple1 = (1, 2, 3, 4)
print(isinstance(tuple1, Iterable))  # True
set1 = {1, 2, 3, 4}
print(isinstance(set1, Iterable))  # True
dict1 = {'a': 'A', 'b': 'B'}
print(isinstance(dict1, Iterable))  # True
g1 = (x for x in range(5))
print(isinstance(g1, Iterable))  # True

# print(next(list1))  # 'list' object is not an iterator
list_iter = iter(list1)
print(type(list_iter))  #  通过iter()方法 将list变成了迭代器了
print(next(list_iter))  # 1

# 其他\列表\元组\集合\字典同理 可以通过iter()方法变成迭代器使用

The End

你可能感兴趣的:(python学习,学习,python,pycharm,经验分享,开发语言)