Python学习-迭代器、生成器

迭代器

一、迭代器协议

  1. 对象必须提供一个next方法,执行该方法要么返回迭代中的下一页,或者抛出一个Stoplteration异常,终止迭代。
  2. 具有可迭代的对象。
  3. 一种实现迭代器的的约定。(如for循环、sum、min、max等)使用迭代器协议访问对象。

二、Python中强大的for循环机制

for循环的本质:循环所有的对象,全部使用迭代器协议。只要能被for循环遍历的都有一个_iter_()方法。

其实,严格意义来说(字符串、列表、字典、集合、文件对象都是不可迭代对象),只不过是使用了for循环。调用了它们内部的_iter_方法,把它们变成可迭代的对象。

 1 l = [1,2,3]
 2 #下标访问
 3 print(l[0])
 4 print(l[1])
 5 print(l[2])
 6 print(l[3]) #超出边界报错,IndexError: list index out of range
 7 #遵循迭代器协议访问方式
 8 iter_test = l.__iter__()
 9 print(iter_test)
10 print(iter_test.__next__())
11 print(iter_test.__next__())
12 print(iter_test.__next__())
13 print(iter_test.__next__()) #超出边界值,抛出异常StopIteration
14 
15 #用while来模拟for循环
16 Test_iter = l.__iter__()
17 while True:
18     try:
19         print(Test_iter.__next__())
20     except StopIteration:
21         print("迭代结束!")
22         break
注:for循环帮助处理异常。

生成器

  一种数据类型,自动实现迭代器协议,就是可迭代协议。

  两种表现方式

  1. 函数
1 #生成器雏形
2 def test():
3     yield 1
4     yield 2
5 g = test()
6 print(g.__next__())
7 print(g.__next__())

运行结果:

1 1
2 2

 

  2.生成器表达式

1 g =("egg %s"%i for i in range(5))
2 print(g)
3 print(g.__next__())
4 print(g.__next__())
5 print(g.__next__())
6 print(g.__next__())
7 print(next(g))
8 print(next(g))
9 print(next(g))

运行结果:

 

1  print(next(g))
2 StopIteration
3 <generator object <genexpr> at 0x0000000001DFEDB0>
4 egg 0
5 egg 1
6 egg 2
7 egg 3
8 egg 4

 总结:

  • 语法与常规函数类似,它们之间不同的是生成器使用yield返回一个值,而函数使用return返回值。
  • 自动实现迭代器协议。
  • 状态挂起,yield语句挂起生成器函数的状态,保留足够的信息,以便于下一次从当前位置执行。
  • 生成器只能遍历一次。

例子:

 1 {'name':'北京','population':30000}
 2 {'name':'上海','population':35000}
 3 {'name':'山东','population':30080}
 4 {'name':'河北','population':30900}
 5 {'name':'台湾','population':35600}
 6 #统计上面文件中各个省所占的总人口的比例
 7 def get_population():
 8     with open('人口普查','r',encoding = 'utf-8') as f:
 9         for i in f:
10             yield  i
11 #以生成器的方式获取文件信息
12 g = get_population()
13 s1 = eval(g.__next__())['population']
14 print(s1)
15 all_pop  = sum(eval(i)['population'] for i in g)
16 print(all_pop)
17 
18 for p in g:
19     print('%s %%'%eval(p)['population']/all_pop)
View Code

 

  3.三元表达式

1 name = "laj"
2 res = "SB" if name == "alex" else "shuaige"
3 print(res)
运行结果:
满足if条件,res为SB,不满足则为shuaige。
shuaige

  4.列表解析

1 egg_list = []
2 for i in range(10):
3     egg_list.append("egg %s"%i)
4 print(egg_list)
5 l1 =["egg %s"%i for i in range(10)]
6 print(l1)
7 l2 =["egg %s"%i for i in range(10) if i > 5]
8 print(l2)
9 l1 =["egg %s"%i for i in range(10) if i > 5 else i] #没有四元表达式,可以有两元 

运行结果:

1 ['egg 0', 'egg 1', 'egg 2', 'egg 3', 'egg 4', 'egg 5', 'egg 6', 'egg 7', 'egg 8', 'egg 9']
2 ['egg 0', 'egg 1', 'egg 2', 'egg 3', 'egg 4', 'egg 5', 'egg 6', 'egg 7', 'egg 8', 'egg 9']
3 ['egg 6', 'egg 7', 'egg 8', 'egg 9']

 装饰器

本质就是函数。

装饰就是修饰,修饰一下其他的函数,添加附加功能。

两个原则:

1、不修改被修饰函数的调用方式。

2、不修改被修饰函数的源代码。

知识储备:

装饰器 = 高阶函数+闭包+函数嵌套

高阶函数

1、函数接受的参数是一个函数名

2、函数的返回值是一个函数名

3、只需满足其中一个条件就可以称为高阶函数。

 1 import time
 2 def foo():
 3     time.sleep(1)
 4     print('hello world')
 5 def test1(func):
 6     print(func)
 7     start_time = time.time()
 8     func()
 9     stop_time = time.time()
10     print("函数运行的时间是%s"%(stop_time-start_time))
11 test1(foo)
View Code

函数的嵌套

在函数内部定义函数

1 def father(name):
2     def son():
3         print("我的爸爸是%s"%name)
4     son() #局部变量只能在局部调用
5 father("lqj")

闭包

函数作用域的一种体现

1 def father(auth_typer):
2     def son():
3         #print("我的爸爸是%s"%name)
4         def grandson():
5             print("我的爷爷是%s"%auth_typer)
6         grandson()
7     son() #局部变量只能在局部调用
8 father('xxoo')

搭建装饰器的框架

 1 import time
 2 def timer(func):
 3     def wrapper():
 4         start_time = time.time()
 5         res = func() #运行test
 6         stop_time = time.time()
 7         print('函数的运行时间为%s'%(stop_time-start_time))
 8         return res
 9     return  wrapper
10 @timer
11 def test():
12     time.sleep(3)
13     print('函数运行完毕')
14     return '这是返回值'
15 #res = timer(test) #返回wraper的地址
16 #res() #执行wrapper
17 #test = timer(test) #返回wraper的地址
18 #test() #执行wrapper
19 #@timer 就相当于test = timer(test)
20 res = test()
21 print(res)

解压

1 a,b,c =  (1,2,3)
2 print(a,b,c)
3 a,*_,c = (1,2,3,4,5,6)
4 print(a,c)

两个值交换

1 f1 = 1
2 f2 = 2
3 f1,f2 = f2,f1
4 print(f1,f2)

 

def father(auth_typer):
def son():
#print("我的爸爸是%s"%name)
def grandson():
print("我的爷爷是%s"%auth_typer)
grandson()
son() #局部变量只能在局部调用
father('xxoo')
posted @ 2018-07-20 00:19  qijunL  阅读(130)  评论(0)    收藏  举报