1 生成器(generator)
我们可以通过列表解析方法来创建列表,但如果列表中的元素很多时,则会占用很大的内存资源。如果程序仅需要访问其中的几个元素,则绝大多数元素所占用的空间都被浪费了。
生成器(generator)是能够按照解析表达式逐次产生出数据集合中数据项元素的函数。在Python中,利用生成器,可不必创建完整的数据集合,从而节省存储空间。
生成器函数与普通函数的差别主要在于:生成器函数中利用yield关键字生成数据项,而不是用return返回数据项。生成器函数用循环遍历时,可以用__next__()方法获取yield生成的数据项。
生成器函数与变通函数的执行流程不同。普通函数是顺序执行的,遇到return语句或最后一行语句就返回。而生成器函数在每次调用__next__()方法的时候才执行,遇到yield语句返回,再次执行时不是从头开始,而是从上次返回的yield语句处继续执行。

生成器是用来创建Python序列的一个对象。使用它可以迭代庞大的序列,且不需要在内存中创建和存储整个序列。通常,生成器是为迭代器产生数据的。如range()函数返回在特定区间的自然数序列,如以下语句可以累加从1到100:
>>> sum(range(1,101))
5050
每次迭代生成器时,它会记录上一次调用的位置,并且返回下一个值。这一点和普通的函数是不一样的,一般函数都不会记录前一次调用,而且都会在函数的第一行开始执行。
如果你想创建一个比较大的序列,使用生成器推导的代*会码**很长,这时可以尝试写一个生成器函数。生成器函数和普通函数类似,但是它的返回值使用yield语句声明而不是return。
下面就是range()函数版本:

如生成一个斐波拉契数列:

2 装饰器(decorator)
装饰器可以在不改变源代码的情况下修改(装饰)已经存在的函数(为已经存在的函数添加功能)。
如果需要添加原始函数的功能,则必须重写return语句,并且会改变返回值的类型。对于已经编写完成的程序,改动一处可能会造成其他相关部分出错。利用装饰器可以在不必改动原有函数的前提下增加功能,经常被用于事务处理、日志记录、验证权限、调试测试等有需求的场景。
装饰器实质上是一个函数(内部函数和闭包)。它把一个函数作为输入并且返回另外一个函数。在装饰器中,通常使用下面这些Python技巧:
*args和**kwargs
闭包
作为参数的函数
由自定义函数document_it()定义了一个装饰器,会实现如下功能:
打印输出函数的名字和参数的值;
执行含有参数的函数;
打印输出结果;
返回修改后的函数;

无论传入document_it()的函数func是什么,装饰器都会返回一个新的函数,其中包含函数document_it()新增加的额外语句。实际上,装饰器并不需要执行函数func中的代码,只是在结束前函数document_it()调用函数func以便得到func的返回结果和附加代码的结果。
其实质就是装饰器函数以另一个需要装饰的函数为参数,再由装饰器返回需要装饰的函数(闭包),而不是调用它。所以,装饰器返回的是一个函数对象。
调用装饰器时,只需在原函数定义前用"@"引导装饰器函数即可。这种对功能没有影响,却能方便程序员使用的语法称为语法糖(syntactic sugar)。使用语法糖能够增加程序的可读性、减少代码出错的概率。

也可以使用多个装饰器:

附代码1:
def generator_even():
for i in range(1,11):
print(’第%d步’ % i)
yield i*2
g = generator_even()
print(g.__next__())
print(g.__next__())
print(g.__next__())
’’’
第1步
2
第2步
4
第3步
6
’’’
附代码2:
def my_range(first = 0, last = 10, step = 1):
number = first
while number <last:
yield number
number += step
ranger = my_range(1,5)
print(my_range)
print(ranger)
for i in ranger:
print(i)
’’’
<function my_range at 0x02285930>
<generator object my_range at 0x02280E10>
1
2
3
4
’’’
附代码3:
def fibgen(limit):
f0,f1 = 1,1
for n in range(limit):
yield f0
f0,f1 = f1, f0 + f1
print(type(fibgen(10)))
for x in fibgen(10):
print(x)
’’’
<class ’generator’>
1
1
2
3
5
8
13
21
34
55
’’’
附代码4:
def decorator(f):
def new_f(x,y):
print(’参数1为%d,参数2为%d’ %(x,y))
return f(x,y)
return new_f
@ decorator
def add(x,y):
return x+y
print(add(5,7))
’’’
参数1为5,参数2为7
12
’’’
附代码5:
# 定义装饰器
def document_it(func):
def new_func(*args, **kwargs):
print(’Running function:’, func.__name__)
print(’Positional arguments:’, args)
print(’Keyword arguments:’, kwargs)
result = func(*args, **kwargs)
print(’result’, result)
return result
return new_func
# 1 人工赋值的方式使用装饰器
#定义需要装饰的函数
def add(a,b):
return a + b
newFunc = document_it(add)
newFunc(3,5)
# 2 直接在要装饰的函数前添加装饰器名字
@document_it
#定义需要装饰的函数
def add2(a,b):
return a + b
add2(3,5)
’’’
上述两种使用装饰器的方式,返回的内容是一样的:
Running function: add
Positional arguments: (3, 5)
Keyword arguments: {}
result 8
’’’
附代码6:
# 使用多个装饰器
def square_it(func):
def new_func(*args, ** kwargs):
result = func(*args, ** kwargs)
return result * result
return new_func
@document_it
@square_it
#定义需要装饰的函数
def add3(a,b):
return a + b
add3(3,5)
’’’
Running function: new_func
Positional arguments: (3, 5)
Keyword arguments: {}
result 64
’’’
-End-