一,装饰器
1,概念
装饰器就是给已有的模块添加新的功能,如登录验证功能,运行时间功能等。本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。
强调装饰器的原则:1 不修改被装饰对象的源代码 2 不修改被装饰对象的调用方式
装饰器的目标:在遵循1和2的前提下,为被装饰对象添加上新功能
2,理论基础
要想实现装饰器的功能,我们需要三个理论基础:函数闭包+函数嵌套+高阶函数。我们通过为如下模块加入统计运行时间的装饰器来讲解如何使用
import time def test_func(): for i in range(5): time.sleep(0.5)
3,推导
首先我们知道要知道函数的运行时间,只需要在函数前后加上当前时间,通过差值就能计算出来。因此我们可以定义一个模块,并传入所求的函数的函数地址,即高阶函数。
模块中包含此函数的调用和统计时间的功能
import time def test_func(): for i in range(5): time.sleep(0.5) def decorate(func): start_time = time.time() func() end_time = time.time() print(end_time-start_time) decorate(test_func) #2.5s
这样就实现了统计时间的功能,但是却修改了函数的调用逻辑,因此进一步思考,我们可以在装饰器函数内定义函数,并在此函数内调用被统计函数,即函数嵌套,并返回
代码 如下:
import time def test_func(): for i in range(5): time.sleep(0.5) def decorate(func): def count_time(): start_time = time.time() func() end_time = time.time() print(end_time-start_time) return count_time test_func = decorate(test_func) test_func()
而python给我们提供了装饰器语法:
import time def decorate(func): def count_time(): start_time = time.time() func() end_time=time.time() print(end_time-start_time) return count_time @decorate def test_func(): for i in range(5): time.sleep(0.5) test_func()
上面就实现了一个简单的装饰器,可根据需求来增加它的功能,如传入参数,返回值等。
二,迭代器
1,概念
迭代器(iteretor)是一种遍历容器所有或者部分元素的方法,相当于一个复杂的指针,能够遍历复杂的数据结构,一个容器也应该提供它自己的迭代器。
2,迭代器对象与可迭代对象
迭代器对象:即对象能够提供遍历它的方法,像是迭代器的一种具体表现,在Python中迭代器对象能够提供__iter__和__next__方法来得到容器中下一个元素的值。
可迭代对象:即对象提供__iter__方法,使用该方法后得到迭代器对象,如字符串,列表元组
li=[1,2,3,4,5] li=li.__iter__() # 可迭代对象转化成迭代器对象 print(li.__next__()) # 1
3,使用方法
dic = {"a": 1, "e": 4, "b": 2, "c": 3, "d": 4} iter_dic = dic.__iter__() # while True: try: print(next(iter_dic)) #"a" "e" "b"..... except StopIteration: #需要手动捕捉异常 break
而我们可以借助Python中强大的for循环机制来循环遍历容器
4,for循环
#基于for循环,我们可以完全不再依赖索引去取值了 dic = {‘a‘:1,‘b‘:2,‘c‘:3} for k in dic: print(dic[k]) #for循环的工作原理 #1:执行in后对象的dic.__iter__()方法,迭代器对象.__iter,返回对象本身。得到一个迭代器对象iter_dic #2: 执行next(iter_dic),将得到的值赋值给k,然后执行循环体代码 #3: 重复过程2,直到捕捉到异常StopIteration,结束循环
三,生成器
Python使用生成器能够实现延时操作,何谓延时操作,即需要结果时就产生结果,不需要时就不产生。提供生成器对象有两种方式:
1,生成器函数:和常规的函数定义一样只不过不用return,而是使用yield来返回结果。一次只返回一个结果,在每个结果中间,挂起函数状态,以便下次继续返回。
2,生成器表达式:生成一个生成器对象,按需产生结果,就是迭代的时候产生具体的值。
1,生成器函数
def gensquares(n): for i in range(n): yield i ** 2 obj = gensquares(5) print(obj) # <generator object gensquares at 0x00000000021E55C8> print(next(obj)) # 0 print(next(obj)) # 1 print(next(obj)) # 4
2,生成器表达式
li = [] for i in range(5): name = "name%d" % i li.append(name) print(li) # [‘name0‘, ‘name1‘, ‘name2‘, ‘name3‘, ‘name4‘] # 列表推导 li = ["name%d" % i for i in range(5)] print(li) # [‘name0‘, ‘name1‘, ‘name2‘, ‘name3‘, ‘name4‘] # 简洁了许多 # 生成器表达式 gens = ("name%d" % i for i in range(5)) print(gens) # <generator object <genexpr> at 0x00000000028655C8> print(next(gens)) # name0 print(next(gens)) # name1 print(next(gens)) # name2#生成器对象就是迭代器对象
使用生成器的好处数据不会直接加载到内存,在数据量很大的情况下作用很大。比如使用内置函数如下
#print(sum([i for i in range(100000000)])) #提示计算机内存不足,程序崩溃 print(sum((i for i in range(1000000000)))) #程正常运行
注意事项:生成器对象是一种迭代器对象,它们都只能遍历一次,而可迭代对象可以多次遍历。
原文地址:https://www.cnblogs.com/ifyoushuai/p/8970244.html