迭代器iterator
迭代器是访问集合元素的一种方式。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。
迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退。另外,迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素。
迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。这个特点使得它特别适合用于遍历一些巨大的或是无限的集合,比如几个G的文件
特点:
访问者不需要关心迭代器内部的结构,仅需通过next()方法不断去取下一个内容
不能随机访问集合中的某个值 ,只能从头到尾依次访问
访问到一半时不能往回退
便于循环比较大的数据集合,节省内存
作用:
这个yield的主要效果呢,就是可以使函数中断,并保存中断状态,中断后,代码可以继续往下执行,过一段时间还可以再重新调用这个函数,从上次yield的下一句开始执行。
另外,还可通过yield实现在单线程的情况下实现并发运算的效果
判断一个对象是否是可迭代对象
''' Created on 2018年1月5日 @author: cq ''' from collections import Iterable class Obj(object): pass class Fab(object): def __init__(self, max): self.max = max self.n, self.a, self.b = 0, 0, 1 def __iter__(self): return self def next(self): if self.n < self.max: r = self.b self.a, self.b = self.b, self.a + self.b self.n = self.n + 1 return r raise StopIteration() def main(): print("Python常见对象的可迭代性") print("abc :%s" % type('abc')) print("is iterable >>",isinstance('abc',Iterable)," ") print("123456 :%s" % type(123456)) print("is iterable >>",isinstance(123456,Iterable)," ") print("[1,2,4,5,6] :%s" % type([1,2,4,5,6])) print("is iterable >>",isinstance([1,2,4,5,6],Iterable)," ") print("{1,2,4,5,8,5,5,5,5} :%s" % type({1,2,4,5,8,5,5,5,5})) print("is iterable >>",isinstance({1,2,4,5,8,5,5,5,5},Iterable)," ") print("(1,2,4,5,6,8) :%s" % type((1,2,4,5,6,8))) print("is iterable >>",isinstance((1,2,4,5,6,8),Iterable)," ") print("{'a':1,'b':2} :%s" % type({"a":1,"b":2})) print("is iterable >>",isinstance({"a":1,"b":2},Iterable)," ") print("Obj() :%s" % type(Obj())) print("is iterable >>",isinstance(Obj(),Iterable)," ") print("Fab(2) :%s" % type(Fab(2))) print("is iterable >>",isinstance(Fab(2),Iterable)," ") if __name__ == '__main__': main()
1 # 输出结果如下 2 3 Python常见对象的可迭代性 4 abc :<class 'str'> 5 is iterable >> True 6 7 123456 :<class 'int'> 8 is iterable >> False 9 10 [1,2,4,5,6] :<class 'list'> 11 is iterable >> True 12 13 {1,2,4,5,8,5,5,5,5} :<class 'set'> 14 is iterable >> True 15 16 (1,2,4,5,6,8) :<class 'tuple'> 17 is iterable >> True 18 19 {'a':1,'b':2} :<class 'dict'> 20 is iterable >> True 21 22 Obj() :<class '__main__.Obj'> 23 is iterable >> False 24 25 Fab(2) :<class '__main__.Fab'> 26 is iterable >> True
迭代对象的next方法
''' Created on 2018年1月5日 @author: cq ''' def main(): str1 = 'hello world!' list1 = [1,2,3,4,5,6] dicts1 = {'name' : "bob", 'age' : "18", 'city' : "Paris", 'gender' : "male" } print("迭代输出可迭代对象'字符串'的元素") list_iter = iter(str1) for i in range(len(str1)): print(list_iter.__next__()) print("----------------------") print("迭代输出可迭代对象[列表]的元素") list_iter = iter(list1) for i in range(len(list1)): print(list_iter.__next__()) print("----------------------") print("迭代输出可迭代对象{字典}的元素") list_iter = iter(dicts1.keys()) for i in range(len(dicts1)): print(list_iter.__next__()) print("----------------------") print("迭代输出可迭代对象{字典}的元素") list_iter = iter(dicts1.values()) for i in range(len(dicts1)): print(list_iter.__next__()) print("----------------------") print("迭代输出可迭代对象{字典}的元素") list_iter = iter(dicts1.items()) try: while True: print(list_iter.__next__()) except StopIteration: pass if __name__ == '__main__': main()
# 输出 迭代输出可迭代对象'字符串'的元素 h e l l o w o r l d ! ---------------------- 迭代输出可迭代对象[列表]的元素 1 2 3 4 5 6 ---------------------- 迭代输出可迭代对象{字典}的元素 name age city gender ---------------------- 迭代输出可迭代对象{字典}的元素 bob 18 Paris male ---------------------- 迭代输出可迭代对象{字典}的元素 ('name', 'bob') ('age', '18') ('city', 'Paris') ('gender', 'male')
可迭代类的使用
''' Created on 2018年1月5日 @author: cq ''' import time class EvenNumber(object): def __init__(self, index=0): self.index = index + 1 # 声明可迭代类,并返回当前对象做为可迭代对象 # 该方法不会在类实例化的时候调用,当该类做为迭代对象使用时,有且在当前类调用一次 def __iter__(self): print("---------",self.index) return self # 与迭代对象一样,调用next方法获取对象 def __next__(self): self.index -= 1 if self.index < 0: raise StopIteration elif divmod(self.index, 2) == (self.index/2,0): return self.index def main(): for i in EvenNumber(12): if i is not None: print(i) if __name__ == '__main__': main()
# 输出结果 # 输出小于该数的偶数 --------- 13 12 10 8 6 4 2 0
生成器generator
定义:一个函数调用时返回一个迭代器,那这个函数就叫做生成器(generator),如果函数中包含yield语法,那这个函数就会变成生成器
''' Created on 2018年1月5日 @author: cq ''' import time # 此函数包含yield语法,是生成器 ,只能等待__next__()方法唤醒返回迭代对象 def salaryMan(name): """ """ print("%s: ~~~~~太早了关闹钟继续睡 " % name) while True: plan = yield print("%s: 今天的计划是 %s" % (name, plan)) if plan == "爬山" or plan == "打球": print("%s: 睡个X儿,%s去" % (name, plan)) else: print("%s: 不想去太困了,再睡伙 " % name) def alarmClock(): iterable2 = sleeper1.__next__() iterable3 = sleeper2.__next__() print("刚响就被关掉了,2S后在响吧... ") time.sleep(2) plan_list = ["打球", "爬山", "看电影", "逛街"] while len(plan_list): print("闹钟又响了~~~") sleeper1.send(plan_list.pop()) sleeper2.send(plan_list.pop()) time.sleep(1) def main(): global sleeper1,sleeper2 sleeper1 = salaryMan("老王") sleeper2 = salaryMan("老李") print("闹钟还有1S响... ") time.sleep(2) alarmClock() if __name__ == '__main__': main()
# 输出结果 闹钟还有1S响... 老王: ~~~~~太早了关闹钟继续睡 老李: ~~~~~太早了关闹钟继续睡 刚响就被关掉了,2S后在响吧... 闹钟又响了~~~ 老王: 今天的计划是 逛街 老王: 不想去太困了,再睡伙 老李: 今天的计划是 看电影 老李: 不想去太困了,再睡伙 闹钟又响了~~~ 老王: 今天的计划是 爬山 老王: 睡个X儿,爬山去 老李: 今天的计划是 打球 老李: 睡个X儿,打球去
扩展:基于yield生成器对象,实现异步回调
from queue import Queue from functools import wraps def apply_async(func, args, *, callback): # Compute the result result = func(*args) # Invoke the callback with the result callback(result) class Async: def __init__(self, func, args): self.func = func self.args = args def inlined_async(func): @wraps(func) def wrapper(*args): f = func(*args) result_queue = Queue() result_queue.put(None) while True: result = result_queue.get() try: ## 注意,这里不仅发送消息给生成器,并且等待生成器返回值 a = f.send(result) apply_async(a.func, a.args, callback=result_queue.put) except StopIteration: break return wrapper def add(x, y): return x + y @inlined_async def test(): for n in [x for x in range(10) if x % 2 == 0]: r = yield Async(add, (n, n)) print(r) if __name__ == '__main__': test()
0
4
8
12
16
装饰器decorator
函数调用+函数嵌套+高阶函数
函数调用:执行其他地方的函数体
函数嵌套:就是指在某些情况下,需要将某函数作为另一函数的参数使用
高阶函数:接受一个或多个函数作为参数,即形式参数中接收函数
装饰器满足开闭原则
对于扩展是开放的,对于修改是关闭的。
功能:
当应用的需求改变时,我们可以对模块进行扩展,使其具有满足那些改变的新行为而不用修改源代码,避免影响原来应用的运行
''' Created on 2018年1月5日 @author: cq ''' import time def time_cost(func): def wrapper(*args,**kwargs): sTime = time.time() func(*args,**kwargs) print("Time cost:%s"%(time.time()-sTime)) return wrapper # 在不改变算法函数的同,添加计算时间开销的功能 @time_cost def algorithm(): print("算法开始执行...") time.sleep(2) if __name__ == '__main__': algorithm()
# 输出结果 算法开始执行... Time cost:2.0004446506500244
参考博客:http://www.cnblogs.com/alex3714/articles/5143440.html