python中的迭代器&&生成器&&装饰器

迭代器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),"\n")
    print("123456 :%s" % type(123456))
    print("is iterable >>",isinstance(123456,Iterable),"\n")
    print("[1,2,4,5,6] :%s" % type([1,2,4,5,6]))
    print("is iterable >>",isinstance([1,2,4,5,6],Iterable),"\n")
    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),"\n")
    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),"\n")
    print("{'a':1,'b':2} :%s" % type({"a":1,"b":2}))
    print("is iterable >>",isinstance({"a":1,"b":2},Iterable),"\n")
    print("Obj() :%s" % type(Obj()))
    print("is iterable >>",isinstance(Obj(),Iterable),"\n")
    print("Fab(2) :%s" % type(Fab(2)))
    print("is iterable >>",isinstance(Fab(2),Iterable),"\n")
    
    
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')
Result

 

可迭代类的使用

'''
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
Result

 

生成器generator

定义:一个函数调用时返回一个迭代器,那这个函数就叫做生成器(generator),如果函数中包含yield语法,那这个函数就会变成生成器

'''
Created on 2018年1月5日

@author: cq
'''

import time


# 此函数包含yield语法,是生成器 ,只能等待__next__()方法唤醒返回迭代对象
def salaryMan(name):
    """
        
    """
    print("%s: ~~~~~太早了关闹钟继续睡\n" % name)
    while True:
        plan = yield
        print("%s: 今天的计划是 %s" % (name, plan))
        if plan == "爬山" or plan == "打球":
            print("%s: 睡个X儿,%s去" % (name, plan))
        else:
            print("%s: 不想去太困了,再睡伙\n" % name)


def alarmClock():
    iterable2 = sleeper1.__next__()
    iterable3 = sleeper2.__next__()
    print("刚响就被关掉了,2S后在响吧...\n")
    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响...\n")
    time.sleep(2)
    alarmClock()


if __name__ == '__main__':
    main()
    
# 输出结果
 
闹钟还有1S响...

老王: ~~~~~太早了关闹钟继续睡

老李: ~~~~~太早了关闹钟继续睡

刚响就被关掉了,2S后在响吧...

闹钟又响了~~~
老王: 今天的计划是 逛街
老王: 不想去太困了,再睡伙

老李: 今天的计划是 看电影
老李: 不想去太困了,再睡伙

闹钟又响了~~~
老王: 今天的计划是 爬山
老王: 睡个X儿,爬山去
老李: 今天的计划是 打球
老李: 睡个X儿,打球去
Result

 

扩展:基于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
Result

 

装饰器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
Result

 

参考博客:http://www.cnblogs.com/alex3714/articles/5143440.html

posted @ 2018-01-05 21:29  前路~  阅读(269)  评论(0)    收藏  举报