●装饰器
装饰器用来增强 函数 的功能 但是不改变其原有的结构与功能 。 在代码运行期间 动态的添加功能 称为 装饰器。
如何理解装饰器?
1.不改变函数结构,即不对函数本身结构体做任何修改;
2.增强函数功能;比如起跳时能带一道彩虹,那么能构造彩虹功能即可以定义为起跳函数的装饰器,并不影响起跳这个函数;
3.本质上,装饰器就是一个返回函数的高阶函数。
下面我们定义一个起跳函数
def jump():
print('我正在蹦跶')
定义一个装饰器
def rainbow(main):
def make_rainbow(*args,**kwargs):
print('你被挂上了彩虹:%s'%(main.__name__))
return main(*args,**kwargs)
return make_rainbow
看这个装饰器(decorator),因为rainbow是一个装饰器 ,所以他是接受一个函数作为参数(main)的。
借助Python的@语法,把decorator置于函数的定义处:
@rainbow
def jump():
print('我正在蹦跶')
执行jump:
if __name__ == '__main__':
jump()
我们从结果上来看,是先执行 装饰器 然后用才执行主函数 那么具体步骤是怎样的呢?
把@raninbow放到jump()函数的定义处,相当于执行了语句:jump=raninbow(jump);
那么 raninbow 返回的是一个新函数 jump() ,那么现在同名的now变量指向了新的函数 ,在rainbow()函数内,首先打印日志,再紧接着调用原始函数 。
import json
'''
装饰器
'''
def guess_with(func):
def rooftop_status():
result = func()
print("天台见")
return result
return rooftop_status
@guess_with
def german_team():
print("德国必胜")
# german_team()
'''函数名可以赋值给变量'''
def a(name):
print("我是{}!慌得一批!".format(name))
a("梅西")
y = a
y("乐福")
'''高阶函数
高阶函数满足其一即为高阶函数:
a.可以接受函数名作为实参;
b.返回值中可以包含函数名
'''
r = map(lambda x:x*3, [3,3,4,5,6])
for i in r:
print("当前天台人数:", i)
# 定义一个可以返回函数的函数 也就是高阶函数
def f(l):
return map(lambda x: x*10,l)
aaa = f([10,22,333])
for i in aaa:
print("已跳天台人数:", i)
'''有了以上的两个概念 实现一个类似的装饰器'''
def status(func): #接受一个 函数名参数 并返回了该函数名 并不会修改原函数 只是增加了一个本身带有的表动
print('慌得一批!')
return func
def name():
print("我是勒布朗")
'''在调用时 这里有个缺陷 就是函数调用方式改变了;即不是原本的name,而是 t
那么改成 name = status(name) 不就可以了?但是每次使用这样的装饰器 都要写这一句
那么简化一下 python提供了一个语法糖 @ 在每个被装饰的函数上使用这个@即为代替name=status(name)
'''
name = status(name) #
name()
def status(func):
print('慌得一批')
return func
@status
def name():
print('LBJ')
name()
"""
装饰器的工作原理:
①构建一个高阶函数 参数为函数 返回的也是函数
②再利用语法糖@ 简化赋值操作
"""
def guess_win(func):
def rooftop_status():
result = func()
print('天台已满,请排队')
return result
return rooftop_status
@guess_win
def german_team():
print('德国必胜')
return '赢了会所嫩模!输了下海干活!'
x = german_team()
print(x)
"""
装饰器本事就是函数,其参数是另一个函数(被装饰的函数)
装饰器通常会额外处理被装饰的函数,然后把它返回,或者将替换成另外一个函数或可调用对象
"""
●迭代器
迭代器 :可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。实现 迭代迭代器协议的 容器对象
注:
访问者无需关注迭代器内部 仅需要通过 next() 方法 去取下一个内容
不能随机访问 集合中的某个值 只能从头到尾访问
访问到一半时 不能往回退
便于循环较大的数据集合 节省内存
a = iter([1,2,3,4,5,555,666])
>>> a = iter([1,2,3,4,56,77])
>>> a.__next__()
1
>>> a.__next__()
2
>>> a.__next__()
3
>>> a.__next__()
4
>>> a.__next__()
56
>>> a.__next__()
77
●生成器
生成器 :一个函数调用时返回一个迭代器,那这个函数就叫做生成器(generator);
如果函数中包含yield语法,那这个函数就会变成生成器。
>>> def odd():
... print 'step 1'
... yield 1
... print 'step 2'
... yield 3
... print 'step 3'
... yield 5
...
>>> o = odd()
>>> o.next()
step 1
1
>>> o.next()
step 2
3
>>> o.next()
step 3
5
>>> o.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
generator保存的是算法,每次调用next(),就计算出下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。
判断一个函数是否是一个特殊的 generator 函数?可以利用 isgeneratorfunction 判断:
下面使用 yield 书写一个斐波那契 函数:
#1.常规版本
def fab(max):
n,a,b = 0,0,1
while n <max:
print(b)
a,b,=b,a+b
n =n+1
>>> from inspect import isgeneratorfunction
>>> isgeneratorfunction(fab)
False
#2.yield版本
def fab(max):
n,a,b = 0,0,1
while n <max:
yield b
a,b,=b,a+b
n =n+1
>>> isgeneratorfunction(fab)
False
yield 的好处是显而易见的,把一个函数改写为一个 generator 就获得了迭代能力,比起用类的实例保存状态来计算下一个 next() 的值,不仅代码简洁,而且执行流程异常清晰;
如:
参考自:https://www.ibm.com/developerworks/cn/opensource/os-cn-python-yield/
https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000