再探黑魔法-Python 生成器


首先提一下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])

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. 用 圆括号 的列表解析”产生一个生成器

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%']

Hello, I am Mingyue Li. Read my thoughts on IT and Life

Copyright Declaration:

All articles and pictures contained on this web site is copyright protected. If reproduced, must contain this statement, and indicate the original author and the original address of this article