python快速入门之迭代器和生成器 (python迭代器生成器视频)

1 生成器(generator)

我们可以通过列表解析方法来创建列表,但如果列表中的元素很多时,则会占用很大的内存资源。如果程序仅需要访问其中的几个元素,则绝大多数元素所占用的空间都被浪费了。

生成器(generator)是能够按照解析表达式逐次产生出数据集合中数据项元素的函数。在Python中,利用生成器,可不必创建完整的数据集合,从而节省存储空间。

生成器函数与普通函数的差别主要在于:生成器函数中利用yield关键字生成数据项,而不是用return返回数据项。生成器函数用循环遍历时,可以用__next__()方法获取yield生成的数据项。

生成器函数与变通函数的执行流程不同。普通函数是顺序执行的,遇到return语句或最后一行语句就返回。而生成器函数在每次调用__next__()方法的时候才执行,遇到yield语句返回,再次执行时不是从头开始,而是从上次返回的yield语句处继续执行。

python生成器和迭代器的使用场景,python生成器和迭代器的区别

生成器是用来创建Python序列的一个对象。使用它可以迭代庞大的序列,且不需要在内存中创建和存储整个序列。通常,生成器是为迭代器产生数据的。如range()函数返回在特定区间的自然数序列,如以下语句可以累加从1到100:

>>> sum(range(1,101))

5050

每次迭代生成器时,它会记录上一次调用的位置,并且返回下一个值。这一点和普通的函数是不一样的,一般函数都不会记录前一次调用,而且都会在函数的第一行开始执行。

如果你想创建一个比较大的序列,使用生成器推导的代*会码**很长,这时可以尝试写一个生成器函数。生成器函数和普通函数类似,但是它的返回值使用yield语句声明而不是return。

下面就是range()函数版本:

python生成器和迭代器的使用场景,python生成器和迭代器的区别

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

python生成器和迭代器的使用场景,python生成器和迭代器的区别

2 装饰器(decorator)

装饰器可以在不改变源代码的情况下修改(装饰)已经存在的函数(为已经存在的函数添加功能)。

如果需要添加原始函数的功能,则必须重写return语句,并且会改变返回值的类型。对于已经编写完成的程序,改动一处可能会造成其他相关部分出错。利用装饰器可以在不必改动原有函数的前提下增加功能,经常被用于事务处理、日志记录、验证权限、调试测试等有需求的场景。

装饰器实质上是一个函数(内部函数和闭包)。它把一个函数作为输入并且返回另外一个函数。在装饰器中,通常使用下面这些Python技巧:

*args和**kwargs

闭包

作为参数的函数

由自定义函数document_it()定义了一个装饰器,会实现如下功能:

打印输出函数的名字和参数的值;

执行含有参数的函数;

打印输出结果;

返回修改后的函数;

python生成器和迭代器的使用场景,python生成器和迭代器的区别

无论传入document_it()的函数func是什么,装饰器都会返回一个新的函数,其中包含函数document_it()新增加的额外语句。实际上,装饰器并不需要执行函数func中的代码,只是在结束前函数document_it()调用函数func以便得到func的返回结果和附加代码的结果。

其实质就是装饰器函数以另一个需要装饰的函数为参数,再由装饰器返回需要装饰的函数(闭包),而不是调用它。所以,装饰器返回的是一个函数对象。

调用装饰器时,只需在原函数定义前用"@"引导装饰器函数即可。这种对功能没有影响,却能方便程序员使用的语法称为语法糖(syntactic sugar)。使用语法糖能够增加程序的可读性、减少代码出错的概率。

python生成器和迭代器的使用场景,python生成器和迭代器的区别

也可以使用多个装饰器:

python生成器和迭代器的使用场景,python生成器和迭代器的区别

附代码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-