Python基础(8)-装饰器、生成器、迭代器

 

1.装饰器

在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。本质上,decorator就是一个返回函数的高阶函数

1)正常函数

#!/usr/local/bin/python3
import time

def is_Prime(num):
    if num < 2:
        return True
    elif num ==  2:  
        return False
    else:
        for i in (2,num):
            if num % i == 0:
                return False
        return True

def find_Prime():
	t1 = time.time()
    for i in range(2,10000):
        if is_Prime(i):
            print(i)
	t2 = time.time()
	print(t2-t1)
	
find_Prime()

2)装饰器,无参数,无返回值

#!/usr/local/bin/python3
import time
def display_time(func):
    def wrapper():
        t1 = time.time()
        func()
        t2 = time.time()
        print(t2-t1)
    return wrapper
	
def is_Prime(num):
    if num < 2:
        return True
    elif num ==  2:  
        return False
    else:
        for i in (2,num):
            if num % i == 0:
                return False
        return True

@display_time
def find_Prime():
    for i in range(2,10000):
        if is_Prime(i):
            print(i)

find_Prime()

3)装饰器,有返回值

#!/usr/local/bin/python3
import time
def display_time(func):
    def wrapper():
        t1 = time.time()
        result = func()
        t2 = time.time()
        print(t2-t1)
	return result
    return wrapper
	
def is_Prime(num):
    if num < 2:
        return True
    elif num ==  2:  
        return False
    else:
        for i in (2,num):
            if num % i == 0:
                return False
        return True

@display_time
def find_Prime():
  count = 0 for i in range(2,10000): if is_Prime(i): count +=1
  return count

find_Prime()

4)装饰器,有参数

def display_time(func):
    def wrapper(n):
        t1 = time.time()
        result = func(n)
        t2 = time.time()
        print(t2-t1)
        return result
    return wrapper
	
def is_Prime(num):
    if num < 2:
        return True
    elif num ==  2:  
        return False
    else:
        for i in (2,num):
            if num % i == 0:
                return False
        return True
		
@display_time
def find_Prime(n):
    count = 0 
    for i in range(2,n):
        if is_Prime(i):
            count += 1
    return count

find_Prime(10000)

2. 生成器

通过列表生成式,可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。比如我要循环100万次,按py的语法,for i in range(1000000)会先生成100万个值的列表。但是循环到第50次时,我就不想继续了,就退出了。但是90多万的列表元素就白为你提前生成了。

for i in range(1000000):
    if i == 50: 
        break
    print(i)

如上,for i in range(1000000)会先生成100万个值的列表。但是循环到第50次时,程序退出了,但是90多万的列表元素已经提前生成了,上述做法,不仅会占用很大的存储空间,而且绝大数元素占用的空间也浪费了。

在Python中,这种一边循环一边计算后面元素的机制,称为生成器:generator。

# 生成器创建
(x * x for x in range(10))

通过next()函数获得generator的下一个返回值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。通过for循环来迭代它,就不需要关心StopIteration的错误

g = (x * x for x in range(10))
    for n in g:
        print(n)    

3.函数生成器

def fib(max):
    a,b = 0,1
    n = 0  # 斐波那契数
    while n < max:
        n = a + b
        a = b # 把b的旧值给到a
        b = n # 新的b = a + b(旧b的值)
        #print(n)
        yield n # 程序走到这,就会暂停下来,返回n到函数外面,直到被next方法调用时唤醒
f = fib(100) # 注意这句调用时,函数并不会执行,只有下一次调用next时,函数才会真正执行

print(f)
print(f.__next__())
print(f.__next__())
print(f.__next__())
print(f.__next__())

>>>输出结果:
第1个print:
第2个print:1
第3个print:2
第4个print:3
第5个print:5

这就是定义generator的另一种方法。如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator:

generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句暂停并返回数据到函数外,再次被next()调用时

从上次返回的yield语句处继续执行

4.迭代器

可以直接作用于for循环的对象统称为可迭代对象:Iterable,可迭代的意思就是可遍历、可循环

可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。

 

生成器都是Iterator对象,但listdictstr虽然是Iterable,却不是Iterator

listdictstrIterable变成Iterator可以使用iter()函数

 

为什么listdictstr等数据类型不是Iterator

这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()

数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。

Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。

  

posted @ 2019-01-05 20:12  麦小秋  阅读(359)  评论(0编辑  收藏  举报