1. 装饰器
介绍:
装饰器(Decorators)是 Python 的一个重要部分。
简单地说:他们是修改其他函数的功能的函数。他们有助于让我们的代码更简短,也更Pythonic(Python范儿)。
装饰器的概念:
- 装饰器实际上就是一个函数
- 有2个特别之处,参数是一个函数。返回值是一个参数
装饰器的简单理解:
实际上就是为了给一个程序添加功能,但是该程序已经上线或者已被使用, 那么就不能大批量的修改源码,这样不现实,因此就产生了装饰器。
注意点:
- 不能修改被装饰的函数的源代码
- 不能修改被装饰的函数的调用方式
装饰器组成方式:
函数+实参高阶函数+返回值高阶函数+嵌套函数+语法糖 = 装饰器
-
有关高阶函数的理解:
- 把一个函数名当作实参传给另外一个函数(”实参高阶函数“)
- 返回值中包含函数名(”返回值高阶函数“)
-
嵌套函数的理解:
嵌套函数指的是在函数内部定义一个函数,而不是调用。 -
语法糖:
写法:@xx ,一般写在函数的上方
装饰器实例
- 使用高阶函数模拟装饰器:
import time
def timer(func):
start_time = time.time()
func()
print '函数执行时间为', time.time() - start_time
def test():
print '开始执行test'
time.sleep(3)
print 'test执行结束'
timer(test)
'''
开始执行test
test执行结束
函数执行时间为 3.00332999229
'''
- 计算运行时间装饰器:
import time
def timer(func): #timer(test1) func=test1
def deco(*args,**kwargs):
start_time = time.time()
func(*args,**kwargs) #run test1
stop_time = time.time()
print("running time is %s"%(stop_time-start_time))
return deco
@timer # test1=timer(test1)
def test1():
time.sleep(3)
print("in the test1")
test1()
- 装饰无参函数,示例代码如下:
#装饰器装饰的函数无参数
def timer(func): #func其实指的就是test
def deco():
start = time.time()
func() #这里其实是对test的调用
stop = time.time()
print (stop-start)
return deco
@timer #test函数使用装饰器
def test():
time.sleep(2)
print ("test is running")
test()
打印结果:
test is running
2.003510952
- 装饰有参函数,示例代码如下:
#装饰器装饰的函数有参数
def timer(func):
def deco(*args,**kwargs): #添加可变参数*args和**kwargs
start = time.time()
func(*args,**kwargs) #这里也是一样,添加可变参数*args和**kwargs
stop = time.time()
print (stop-start)
return deco
@timer
def test(value): #test函数有个参数value,正因为装饰器timer装饰的函数test有参数value,因此在timer中的有了可变参数
time.sleep(2)
print ("test is running %s" %value)
test("22")
打印结果:
test is running 22
2.00424408913
- 带参数的装饰器,示例代码如下:
#装饰器带参数
def timer(parameter):
def out_wapper(func):
def wapper(*wargs,**kwargs):
if parameter == "task1":
start = time.time()
func(*wargs,**kwargs)
stop = time.time()
print ("the task1 is run:",stop-start)
elif parameter == "task2":
func(*wargs, **kwargs)
print ("the task2 is run:")
return wapper
return out_wapper
@timer(parameter = "task1")
def task1():
time.sleep(2)
print "in the task1"
@timer(parameter = "task2")
def task2():
time.sleep(2)
print "in the task2"
task1()
task2()
打印结果:
in the task1
('the task1 is run:', 2.002906084060669)
in the task2
the task2 is run:
装饰器使用场景
授权:装饰器能有助于检查某个人是否被授权去使用一个web应用的端点(endpoint)。它们被大量使用于Flask和Django web框架中
日志:在记录日志的地方添加装饰器
缓存:通过装饰器获取缓存中的值
闭包
- 定义:
如果在一个函数的内部定义了另一个函数,外部的我们叫他外函数,内部的我们叫他内函数。那闭包就是,在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包
2.迭代器
定义:
- 迭代是Python最强大的功能之一,是访问集合元素的一种方式。
- 迭代器是一个可以记住遍历的位置的对象。
- 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
- 迭代器有两个基本的方法:iter() 和 next()。
- 字符串,列表或元组对象都可用于创建迭代器:
可迭代对象:
在Python世界里,一切皆对象。对象根据定义的维度,又可以分为各种不同的类型,比如:文件对象,字符串对象,列表对象。。。等等。
一句话:“实现了__inter__方法的对象就叫做可迭代对象”,__inter__方法的作用就是返回一个迭代器对象。
直观理解就是能用for循环进行迭代的对象就是可迭代对象。比如:字符串,列表,元祖,字典,集合等等,都是可迭代对象。
next()与iter():
next()返回迭代器的下一个项目
next语法:
next(iterator[,dafault])
iterator – 可迭代对象 default – 可选,用于设置在没有下一个元素时返回该默认值,如果不设置,又没有下一个元素则会触发
StopIteration 异常。
iter():
iter()函数用来生成迭代器
iter语法:
迭代器实现斐波那契
class Fib():
def __init__(self, n):
self.a = 0
self.b = 1
self.n = n
self.count = 0
def __iter__(self):
return self
def next(self):
res = self.a
self.a, self.b = self.b, self.a + self.b
if self.count > self.n:
raise StopIteration
self.count += 1
return res
print(list(Fib(5)))
print(list(Fib(10)))
-
生成器和迭代器之间的区别
在使用生成器时,我们创建一个函数;在使用迭代器时,我们使用内置函数iter()和next()。 在生成器中,我们使用关键字‘yield’来每次生成/返回一个对象。 生成器中有多少‘yield’语句,你可以自定义。 每次‘yield’暂停循环时,生成器会保存本地变量的状态。而迭代器并不会使用局部变量,它只需要一个可迭代对象进行迭代。 使用类可以实现你自己的迭代器,但无法实现生成器。 生成器运行速度快,语法简洁,更简单。 迭代器更能节约内存。
3.生成器
-
生成器定义、简介
在python中,生成器是根据某种算法边循环边计算的一种机制。主要就是用于操作大量数据的时候,
一般我们会将操作的数据读入内存中处理,可以计算机的内存是比较宝贵的资源,我认为的当要处理的数据超过内存四分之一的大小时就应该使用生成器。 -
生成器的作用
- 通过列表生成式,我们可以直接创建一个列表,但是,受到内存限制,列表容量肯定是有限的。
- 而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
- 所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?
-4. 这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
- 特点
- 和传统的容器相比,生成器更节省内存。
- 延迟计算,在我们需要结果时就调用一下生成器的next()方法即可。
- 可迭代,你可以像遍历list一样,遍历生成器
-
生成器工作原理
生成式函数和普通函数只有一个区别,普通函数使用return返回结果,而生成器函 数使用yield返回结果。
yield的特点在于,它并不是结束函数,而是在返回结果后将函数处于一种挂起状态,等待再次next函数的调用,然后从上次挂起的地方(yield)继续执行。 -
可迭代的数据类型
列表、元组、字典和集合都是可迭代的对象,可以从其中获得迭代器。
所有这些对象都可用iter()方法获取迭代器: -
yield运行机制:
在Python中,yield就是这样的一个生成器。
- 当你问生成器要一个数时,生成器会执行,直至出现 yield 语句,生成器把yield 的参数给你,之后生成器就不会往下继续运行。
- 当你问他要下一个数时,他会从上次的状态开始运行,直至出现yield语句,把参数给你,之后停下。如此反复
- 在python中,当你定义一个函数,使用了yield关键字时,这个函数就是一个生成器
- 它的执行会和其他普通的函数有很多不同,函数返回的是一个对象,而不是你平常所用return语句那样,能得到结果值。如果想取得值,那得调用next()函数
- 每当调用一次迭代器的next函数,生成器函数运行到yield之处,返回yield后面的值且在这个地方暂停,所有的状态都会被保持住,直到下次next函数被调用,或者碰到异常循环退出。
def fib(max_num):
a,b = 1,1
while a < max_num:
yield b
a,b=b,a+b
g = fib(10) #生成一个生成器:[1,2, 3, 5, 8, 13]
print(g.__next__()) #第一次调用返回:1
print(list(g)) #把剩下元素变成列表:[2, 3, 5, 8, 13]
每次执行send()或next()只是返回了对应yield表达式的参数值,其实对应表达式并未执行,直到下次再执行send()或next()才会执行上次返回参数的yield表达式,所谓的执行yield表达式就是给其赋值,并返回下一个yield表达式的参数值!