你若不想做, 总能找到借口; 你若想做, 总会找到方@阿拉伯谚语

再探黑魔法-Python 生成器

Python 2017-02-26 浏览量: 1210 字数统计: 796 最后更新: 2017-04-24 18:52

首先提一下lambda

lambda

相当于很小的函数,不需要return

适当使用可以写出更简洁代码结构
和函数的区别:lambda可以写在 列表解析里面,不支持语句的代码块,只允许单个返回值的表达式

lambda 参数1, 参数2......参数n:表达式 (只能一句)

map

对一个可迭代对象中的项,应用一个函数操作

def inc(x): return x + 10


def my_map(func, seq):
    res = []
    for x in seq:
        res.append(func(x))
    return res

    
print list(map(inc, [1, 2, 3]))
print my_map(inc, [1, 2, 3])
print my_map(lambda x: x + 10, [1, 2, 3])

map 和 lambda

# python3 
>>> a = lambda x:x*x 
>>> a
<function <lambda> at 0x7f7a1dd1cae8>

>>> b = map(a, [1,2,3] )
>>> b
<map object at 0x7f7a1bf8fc18>
>>> for i in b :
...     print(i)
... 
1
4
9

reduce


def my_reduce(func, seq):
    current = seq[0]
    for next in seq[1:]:
        current = func(current, next) # 回调函数
    return current


print my_reduce(lambda x, y: x + y, (1, 2, 3, 4))

迭代器

迭代器协议:对象提供 next 方法,返回迭代中的下一项,直到 迭代完成 引发一个 StopIteration 异常终止迭代, 类似于 游标指针 , 可以记住上次操作结束的位置,下次调用的时候会接着进行操作下一个元素

协议是一种约定,“可迭代对象” (实现了迭代器协议的对象 比如说文件对象 )实现迭代器协议,Python的内置工具(for循环,sum,min,max等)使用迭代器协议访问对象

生成器

生成器是支持迭代协议的对象,该对象提供 next 方法,返回迭代中的下一项,直到 迭代完成 引发一个 StopIteration 异常终止迭代。

在 Python 中,有两种方法可以产生生成器

  1. def+yield 产生一个生成器函数
  2. 用 圆括号 的列表解析”产生一个生成器

生成器比列表更加节省内存 因为:列表会一次性把全部元素加载到内存中 生成器无需一次性加载所有元素到内存

遍历

  • 生成器函数:和普通的函数相似,但是, 普通def 函数 返回结果是 return 语句 , 而 生成器函数是 用 yield 语句 一次返回一个结果 在每个结果之间,保存 当前 状态, 便于下次从此处继续
  • 创建生成器的时候会自动实现迭代器协议, 也就是说 生成器实现了迭代器协议
In [7]: def test_yield(a):
   ...:     for b in range(a):
   ...:         yield b
   ...:

In [8]: a = test_yield(5)

In [9]: a        # 生成器对象
Out[9]: <generator object test_yield at 0x0000000003C0F3F0>

In [12]: a.next()
Out[12]: 0

In [13]: a.next()
Out[13]: 1

# 生成器方法
# a.close      a.gi_running a.throw
# a.gi_code    a.next
# a.gi_frame   a.send


# 使用 for 循环返回生成器里面的结果
In [8]: for c in test_yield(5):
   ...:     print c
   ...:
0
1
2
3
4
    • 生成器表达式:和 列表解析 相似 ,列表解析是 一次返回一个结果的列表 , 但是,生成器按照操作 需要一次返回一个结果,而不是一个结果列表

如果值很大的情况下适合使用生成器

生成器表达式的写法:


# 生成器表达式
In [14]: ( a*a for a in range(5) )
Out[14]: <generator object <genexpr> at 0x0000000003D2E900>
# In [15]: list( a*a for a in range(5) )
# Out[15]: [0, 1, 4, 9, 16]


# 列表解析:
In [17]: [ a*a for a in range(5) ]
Out[17]: [0, 1, 4, 9, 16]

生成器的优点

可以用于处理 数据量大的列表

  • 当输入的数据量较大时,列表推导可能会因为占用太多内存而出现问题
  • 由生成器表达式所返回的迭代器,可以逐次产生输出值,从而避免了内存用量问题

生成器缺点

  • 生成器只能迭代一次

def percent_total(line_length):
    total_length = sum(line_length)      # 遍历一遍 获取一个总数
    result = []
    for i in line_length:
        line_percent = 100 * i / total_length      # 每一行长度占总长度的百分数 
        result.append(line_percent)      # 添加到 line_percent 列表里面
    return result

# 生成器
def file_line_length(file_name):
    with open(file_name) as f:       # 打开一个文件
        for line in f:
            yield len(line)       # 返回每一行的长度

a = file_line_length('data.txt')
b= percent_total(a)
print(b)



# 演示
In [8]:
   ...: def percent_total(line_length):
   ...:     total_length = sum(line_length) 
   ...:     result = []
   ...:     for i in line_length:
   ...:         line_percent = 100 * i / total_length 
   ...:         result.append(line_percent)    
   ...:     return result
   ...:

In [9]: def file_line_length(file_name):
   ...:     with open(file_name) as f:  
   ...:         for line in f:
   ...:             yield len(line)  
   ...:
   ...:

In [10]: a = file_line_length('data.txt')
    ...: b= percent_total(a)
    ...: print(b)
    ...:
[]

改正

def percent_total(line_length):
    total_length = sum(line_length)      # 遍历一遍 获取一个总数
    result = []
    for i in line_length:
        line_percent = "{0}%".format(100 * i / total_length)      # 每一行长度占总长度的百分数 
        result.append(line_percent)      # 添加到 line_percent 列表里面
    return result

# 生成器
def file_line_length(file_name):
    with open(file_name) as f:       # 打开一个文件
        for line in f:
            yield len(line)       # 返回每一行的长度

a = list(file_line_length('data.txt'))            # 放到 list 里
b= percent_total(a)
print(b)


# 演示
In [54]: def percent_total(line_length):
    ...:     total_length = sum(line_length)
    ...:     result = []
    ...:     for i in line_length:
    ...:         line_percent = "{0}%".format(100 * i / total_length)      
    ...:         result.append(line_percent)     
    ...:     return result
    ...:

In [55]:
    ...: # 生成器
    ...: def file_line_length(file_name):
    ...:     with open(file_name) as f:  
    ...:         for line in f:
    ...:             yield len(line)  
    ...:

In [56]: a = list(file_line_length('data.txt'))

In [57]: a
Out[57]: [6, 11, 1, 3, 1, 3]

In [58]: b= percent_total(a)

In [59]: print b
['24%', '44%', '4%', '12%', '4%', '12%']
小蜗牛 说:
Freedom is the source from which all meaning and all values spring .


文章版权归 原文作者所有丨本站默认采用CC-BY-NC-SA 4.0协议进行授权| 转载必须包含本声明,并以超链接形式注明原文作者和本文原始地址: https://www.tougetu.com/2017/02/python-generator-1.html

还不快抢沙发

添加新评论

代码 Pastebin Gist 加粗 删除线 斜体 链接 签到