python(15)列表推导式、生成器、迭代器

一、列表推导式

列表推导式、字典推导式、集合推导式

旧的列表 ——> 新的列表

1、列表推导式

格式:  [表达式 for 变量 in 旧列表]  或者  [表达式 for 变量 in 旧列表 if 条件]

#过滤掉长度小于等于3的姓名
names = ['aaa', 'bbbb', 'jack', 'abc']

result = [name for name in names if len(name) > 3]
print(result)

#将过滤的姓名首字母大写
result = [name.capitalize() for name in names if len(name) > 3]
print(result)
'''
简化了此过程
for name in names:
    newlist = []
    if len(name) > 3:
        name.title()
        newlist.append(name)
    return newlist
'''
#将1~100之间能被3整除,组成一个新的列表
newlist = [i for i in range(1, 101) if i % 3 == 0 and i % 5 == 0]#携带if条件
print(newlist)

#此处,类比三元表达式     条件为真时的结果 if 条件 else 条件为假时的结果
#         列表推导式     [表达式 for i in 列表 if 条件]

#[(偶数, 奇数), (), ()]  0~5的偶数  0~10的奇数
newlist = [(x, y) for x in range(5) if x % 2 == 0 for y in range(10) if y % 2 != 0]
print(newlist)
'''
def func():
    newlist = []
    for i in range(5):#偶数
        if i % 2 == 0:
            for j in range(10):
                if j % 2 != 0:
                    newlist.append((i, j))
    return newlist
result = func()
print(result)
'''
#list1 = [[1, 2, 3], [4, 5, 6], [7 ,8, 9], [1, 3, 5]] --->[3, 6, 9 ,5]
list1 = [[1, 2, 3], [4, 5, 6], [7 ,8, 9], [1, 3, 5]]
newlist = [i[-1] for i in list1]#没有条件    #取每个列表中最后一个元素
print(newlist)

dict1 = {'name' : 'tom', 'salary' : 5000}
dict2 = {'name' : 'lucy', 'salary' : 8000}
dict3 = {'name' : 'jack', 'salary' : 4500}
dict4 = {'name' : 'lily', 'salary' : 3000}
list1 = [dict1, dict2, dict3, dict4]
#if 薪资大于 5000, 加200, 低于5000 加500
#if为true执行语句 if 条件 else 执行语句 for 元素 in 列表
newlist = [person['salary'] + 200 if person['salary'] > 5000 else person['salary'] + 500 for person in list1]
print(newlist)

2、集合推导式  {}

集合去重且无顺序   类似列表推导式,在列表推导式的基础上添加了一个去除重复项

list1 = [1, 5, 35, 3, 5, 1]
set1 = {x - 1 for x in list1 if x > 5}
print(set1)

3、字典推导式

#字典推导式
#key与value进行交换
dict1 = {'a' : 'A', 'b' : 'B', 'c' : 'C', 'd' : 'C'}
newdict = {value : key for key, value in dict1.items()}
print(newdict)

 

二、生成器  generator

通过列表生成式(列表推导式),我们可以直接创建一个列表,但是受到内存限制,列表容量肯定是有限的。

而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间。

如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。

所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?

这样就不必创建完成的list,从而节省大量的空间。

在Python中,这种一边循环一边计算的机制,称为生成器:generator

 

得到生成器的方式:

方式一、通过列表推导式得到生成器

#得到列表[0, 3, 6, 9, 12, ..., 30]
newlist = [x * 3 for x in range(11)]
print(type(newlist))  #list

#得到生成器  将列表推导式外部[]  改为 ()
g = (x * 3 for x in range(11))
print(type(g))  #generator
print(g)    #<generator object <genexpr> at 0x0000000001D6FA20>
#方式1:通过调用 __next__()
print(g.__next__())  #0
print(g.__next__())  #3  只有调用时,才产生

#方式2: next(生成器对象)  built-in系统内置函数
#每调用一次next(),则会产生一个元素
print(next(g))  #6
print(next(g))  #9
# StopIteration  生成器本来可以生成10个,现在得到了10个,如果继续调用next(生成器) 会抛出异常

while True:
    try:
        e = next(g)
        print(e)
    except:
        print("没有更多的元素")
        break

方式二、借助函数完成  yield

函数中出现 yield,说明函数已经不是函数,而是生成器

步骤:

1、定义一个函数,函数中使用yield关键字

2、调用函数,接收调用的结果

3、得到的结果就是生成器

4、借助于next(生成器) 或 __next__() 得到元素

def func1():
    n = 0
    while True:
        n += 1
        yield n  # return n + 暂停

g = func1()
print(g)  #generator
print(next(g))  # 1
print(next(g))  # 2

#裴波那切数列  0、1、1、2、3、5、8、13、21、34、55、89、144...
def fib(length):
    a, b = 0, 1
    n = 0
    while n < length:
        yield b  #return b + 暂停
        a, b = b, a + b  #再次调用,在yield 下方执行代码
        n += 1
    return '没有更多元素!'  #--->就是在得到StopIteration后提示信息

g = fib(8)
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())

 

生成器的方法:

    __next__():  获取下一个元素

    send(value): 向每次生成器调用中传值  注意:第一次需要调用send(None)

 

生成器send(value) 方法:

def gen():
    i = 0
    while i < 5:
        temp = yield i #return i + pause
        print('temp', temp)
        i += 1
    return '没有更多的数据'

g = gen()
n1 = g.send(None)
n1 = g.send("test")
print(n1)
n2 = g.send("aaa")
print(n2)

 

三、进程、线程、协程之间的关系

进程  包含多个  线程  包含多个  协程

例如:迅雷下载,同时10个线程

#一个进程可以开启多个协程
def task1(n):
    for i in range(n):
        print("正在搬第{}块砖".format(i))
        yield None

def task2(n):
    for i in range(n):
        print("正在听第{}首歌".format(i))
        yield None

#未添加生成器,先搬砖,后听歌,无法交替进行    添加生成器可以交替完成
g1 = task1(10)
g2 = task2(6)

while True:
    try:
        g1.__next__()
        g2.__next__()
    except:
        pass

 

四、总结生成器 generator

定义生成器的方式:

1、通过列表推导式构建

g = (x + 1 for x in range(10))

2、函数和yield

def func():

    ...

    yield

g = func()

 

产生元素:

1、next(generator)  --->每次调用都会产生一个新的元素,如果元素产生完毕,再次调用的话就会产生异常

2、生成器内置方法:

g.__next__()

g.send(value)

 

应用:协程

 

五、可迭代的 和 迭代器

可迭代的:

可迭代的对象: 1、生成器  2、元组、列表、集合、字典、字符串

如何判断一个对象是否是可迭代的?

from collections import Iterable

isinstance(list1, Iterable)

迭代器:

迭代是访问集合元素的一种方式,迭代器是一个可以记住遍历的位置的对象。

特点:

1、迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。

2、迭代器只能往前不会后退。

3、可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator

 

可迭代的 是否是 迭代器?

生成器是可迭代的,是迭代器

list是可迭代的,但不是迭代器

list ---> iter(list) ---> 迭代器 next()

from collections import Iterable

list1 = [1, 3, 5]
f = isinstance(list1, Iterable) 
print(f)

f = isinstance('abc', Iterable)
print(f)

f = isinstance(100, Iterable)
print(f)

g = (x for x in range(10))
f = isinstance(g, Iterable)
print(f)

#list  ---> 迭代器  通过iter()  函数可迭代的变成一个迭代器
list1 = [1, 3, 45, 9, 6]
i_list1 = iter(list1)
print(next(i_list1))
print(next(i_list1))

 

六、生成器和迭代器的关系

迭代器:可以调用next(generator)

迭代器:包含生成器

迭代器分为两大类:1、生成器是迭代器的一种

                                 2、借助iter()  函数的转换,转换成迭代器

                                       例如:iter(list)    iter(tuple)

 

七、总结

列表推导式:

[表达式 for 变量 in 列表]

[x+2 for x in list1] ---> 新的列表

 

1、[表达式 for 变量 in 列表 if 条件]

    [x+2 for x in list1 if x % 2 == 0]

 

2、[结果A if 条件 else 结果B for x in list1]

    [x+2 if x % 2 == 0 else x + 1 for x in list1]

 

集合推导式: {表达式 for i in 列表}  --->类似列表推导式,但是没有重复元素

字典推导式: {key, value for k, v in 字典.items()}

 

生成器:generator

1、使用类似的列表推导式 g = (表达式 for 变量 in 列表)

此时的g就是生成器

2、函数+yield

def func():

    ...

    yield

    ...

g = func()

 

得到里面的元素:

系统函数: next(g)

生成器内置函数: __next__(),  [send(None), send(value)]

 

可迭代的与迭代器:

可迭代:1、生成器  2、字符串、列表、集合、元组

Iterable

isinstance(x, Iterable) --->true, false

 

迭代器:调用next(g)

生成器就是一个迭代器 --->next(g) --->下一个元素

next(list) ---> iter(list) ---> next(iter(list)) --->下一个元素

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章