Issue-16 考虑用生成器来改写直接返回列表的函数

我们先考虑这样一个函数,对于一个字符串,我们想找出每一个单词的首字母在这个字符串中的位置,程序如下:

# -*- coding: utf-8 -*-

address = 'four score and seven years ago'

def index_words(text):
    result = []
    if text:    #判断是否为空,不为空那么第一个元素肯定是0
        result.append(0)
    for index,word in enumerate(text):
        if word == ' ':
            result.append(index+1)
    return result

print(index_words(address))

输出:

[0, 5, 11, 15, 21, 27]

这里我们用到了enumerate,枚举,这样每当找到一个空格,说明就是下一个单词的开始,我们就加+1然后放到result列表中就可以了。


这里我们细想,其实代码有点拥挤,创建了新的列表,并且不断的添加元素到列表,这里我们可以考虑使用生成器(一个函数里如果运用了yield表达式,这个函数就是生成器,每次执行的时候,遇到yield就中断,下一次再执行,就从yield处继续执行,另外一个列表生成式如果外面是括号,那么也是一个生成器),当我们调用生成器时,他不会真的运行,而是会返回一个迭代器(迭代器就是可以被next函数不断调用的对象,也可以用for循环来输出)。然后我们就可以不断的在这个迭代器上调用next函数(我们一般使用for函数,来不断的输出每一个值),迭代器就会把生成器推到下一个yield表达是那里。生成器传给yield的每一个值,都会有迭代器来返回给调用者,这里的调用者就是我们的for循环。


# -*- coding: utf-8 -*-

address = 'four score and seven years ago'

def index_words(text):
    if text:
        yield 0
    for index,word in enumerate(text):
        if word == ' ':
            yield index+1

print(index_words(address))

result = list(index_words(address))  #这里通过list函数将这个生成器转换为列表
print(result)

for i in index_words(address):    # 我们一般不用next函数来输出生成器的每一个元素,一般都用for来输出
    print(i)

输出:

<generator object index_words at 0x00000000007D78E0>
[0, 5, 11, 15, 21, 27]
0
5
11
15
21
27


同样的可以从文件里读取数据来继续做上面的操作,我们新建一个 1.txt文件 ,内容为

four score and seven years ago
asd asdd qqqq asdasd

程序:

# -*- coding: utf-8 -*-

def index_words(handle):
    for line in handle:
        offset = 0
        if line:
            yield 0
        for letter in line:
            offset = offset + 1
            if letter == ' ':
                yield offset


with open('1.txt','r') as f:
    print(list(index_words(f)))   这里会输出一个列表,下面的那个for循环就没有用了,因为这个迭代器已经使用过了。
    for i in index_words(f):   
        print(i)   # 请记住,迭代器是有状态的,不可以重复使用,所以这里就不会输出啥了,同样的,如果这个for循环写在前面,那么这个list列表也是没啥,为空

输出:

[0, 5, 11, 15, 21, 27, 0, 4, 9, 14]



总结:

使用生成器比使用列表把收集到的结果展示出来更清晰,直观。

由生成器函数所返回的那个迭代器,可以把生成器函数体中,传给yield表达式的每一个值,逐次产生出来。

无论输入的量有多大,生成器都能产生一系列的输出,因为这些输入和输出,都不会影响它在执行时所耗的内存。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值