第二模块第17章 生成器

https://zhuanlan.zhihu.com/p/109084444

一 生成器

1. 生成器: 自定义迭代器

如何得到生成器:

  在函数内, 一旦存在yield关键字, 调用函数并不会执行函数体代码, 而是会返回一个生成器对象, 生成器即自定义的迭代器.

def func():
    print('第一次')
    yield 1
    print('第二次')
    yield 2
    print('第三次')
    yield 3
    print('第四次')
    yield 4
g = func()
print(g) # 结果: <generator object func at 0x0000026591539A98>
i = g.__iter__()
print(i) # 结果: <generator object func at 0x0000026591539A98>
print(g.__next__()) # 会触发函数体代码的运行, 然后遇到yield停下来, 将yield后面的值当做本次next调用的结果返回
# 注意: g.__next__()等同于next(g)
# yield可以返回一个值, 也可以返回多个值, 用逗号隔开. yield无值则返回None. 持续next, 如果没有yield, 则会报错.
# 通常, yield与return并不会混用.
# 生成器最大的优点是, 可以将函数挂起, 真正的应用场景在并发编程那里.

# 应用案例:
def my_range(start, end, step=1):
    while start < end:
        yield start
        start += step
g = my_range(1, 10, 2)
while True:
    try:
        print(next(g))
    except StopIteration:
        break

 2. 生成器的表达式形式

def dog(name):
    print('道哥%s准备吃东西啦'%name)
    while True:
        x = yield
        print('道哥%s吃了%s'%(name, x))
g = dog('egon')
g.send(None) # 相当于next(g), 完成初始化
g.send('鸡肉') # 给yield传值, yield将值转交给x
g.send('骨头')
g.close()
# g.send('米饭') # 关闭之后无法传值, 会报错

二 三元表达式

res = 值1 if 条件 else 值2

条件成立返回值1, 条件不成立返回值2.

def func(x, y):
    if x > y:
        return x
    else:
        return y
res = func(1, 2)
print(res)
# 三元表达式
# 语法格式: 条件成立时要返回的值 if 条件 else 条件不成立时要返回的值
# 注意: 三元表达式可以用在函数内部
x = 1
y = 2
res = x if x > y else y
print(res)

res1 = x=1 if 1>2 else 3
print(res1) # 结果:3

三 生成式

l = [表达式 for x in 可迭代对象 if 条件]

dic = {k:v for k,v in 可迭代对象 if 条件}

set = {元素 for x in 可迭代对象 if 条件}

g = (表达式 for x in 可迭代对象 if 条件)

生成器表达式可以与sum, list等联用, 联用时可以去掉一个括号:

sum(表达式 for x in 可迭代对象 if 条件)

list(表达式 for x in 可迭代对象 if 条件)

1. 利用可迭代对象和for循环

2. 可以加if条件判断

1. 列表生成式

列表生成式是python为我们提供的一种简化代码的解决方案,用来快速生成列表,语法如下

[expression for item1 in iterable1 if condition1
for item2 in iterable2 if condition2
...
for itemN in iterableN if conditionN
]

#类似于
res=[]
for item1 in iterable1:
    if condition1:
        for item2 in iterable2:
            if condition2
                ...
                for itemN in iterableN:
                    if conditionN:
                        res.append(expression)
lst = ['alex_dsb', 'lxx_dsb', 'wxx_dsb', 'egon']
new_lst = []
for name in lst:
    if name.endswith('dsb'):
        new_lst.append(name)
print(new_lst)

# 列表生成式
l = [name for name in lst if name.endswith('dsb')]
print(l)
# 结果: ['alex_dsb', 'lxx_dsb', 'wxx_dsb']
# 如果不加if判断, 则默认条件为True.
# 如果条件判断非常复杂, 则没必要使用列表生成式, 因为使用列表生成式的目的是精简代码.

# 示例:
# 1. 将列表元素中所有小写字母变成大写
l1 = [name.upper() for name in lst]
print(l1)
# 结果: ['ALEX_DSB', 'LXX_DSB', 'WXX_DSB', 'EGON']

# 2. 所有名字去掉'_dsb'
l2 = [name.replace('_dsb', '') for name in lst]
print(l2)
# 结果: ['alex', 'lxx', 'wxx', 'egon']

 2. 字典生成式

# 1. 字典生成式
# 示例1:
keys = ['name', 'age', 'gender']
dic = {key:None for key in keys}
print(dic)
# 结果: {'name': None, 'age': None, 'gender': None}

# 示例2:
items = [('name', 'egon'), ('age', 18), ('gender', 'male')]
dic1 = {k:v for k,v in items if k != 'gender'}
print(dic1)
# 结果: {'name': 'egon', 'age': 18}

3. 集合生成式

# 集合生成式
info = ['name', 'age', 'gender']
set1 = {el for el in info}
print(set1)
# 结果: {'name', 'gender', 'age'}

4. 没有元祖生成式

元祖本身是不可变的数据类型, 当然也不可以添加

5. 生成器表达式

# 生成器表达式
g= (i for i in range(10) if i > 3) # 此刻, g内部没有存值
print(g) # 结果: <generator object <genexpr> at 0x000001C486FF9A98>
print(next(g)) # 结果: 4
print(next(g)) # 结果: 5
print(next(g)) # 结果: 6

with open('a', mode='r', encoding='utf-8') as f:
    # 方式一: 节省内存空间
    i = 0
    for line in f:
        res = len(line.strip())
        i += res
    print(i)

    # 方式二: 此方式节省内存空间
    sum = 0
    while True:
        try:
            res = next(f).strip()
            sum += len(res)
        except StopIteration:
            break
    print(sum)
    # 注意: sum中计算的应该是可迭代对象; next(f)取出的是一行的内容, 不是单个字符.

    # 方式三: 利用列表生成式和sum, 但是耗费内存空间
    lst = [len(line.strip()) for line in f]
    res = sum(lst)
    print(res)

    # 方式四: 效率最高, 最节约空间
    res = sum((len(line.strip()) for line in f))
    print(res)
# 以上表达式可以简写为 res = sum(len(line.strip()) for line in f), 即去除生成器外面的括号

猜你喜欢

转载自www.cnblogs.com/libyan/p/13188457.html
今日推荐