装饰器
什么是装饰器
让其他函数在不需要做任何代码变动的前提下,增加额外的功能。装饰器的返回值也是一个函数对象。装饰器的应用场景:比如插入日志,性能测试,事务处理,缓存等等场景。
案例切入
def func1():
print("in func1")
# 要求调用func1()输出如下内容,并且前提是不动原本的两行代码
# hello world
# in func1
# hello python
def func2(func):
def inner():
print("hello world")
func()
print("hello python")
return inner
func1 = func2(func1)
func1()
迭代器
什么是迭代器
迭代是访问集合元素的一种方式。迭代器是一个可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
可迭代对象
我们已经知道可以对list、tuple、str等类型的数据使用for…in…的循环语法从其中依次拿到数据进行使用,我们把这样的过程称为遍历,也叫迭代。
但是,并不是所有的数据类型都可以放到for…in…的语句中,然后每次从中取出一条数据供我们使用,供我们迭代,比如整型数据。
如何判断一个对象是否可以迭代
可以使用 isinstance() 判断一个对象是否是 Iterable 对象:(可迭代的:内部必须含有一个 __iter__ 方法。)
# 字符串、列表、元组、字典、集合都可以被for循环,说明他们都是可迭代的
from collections.abc import Iterable
l = [1, 2, 3, 4]
t = (1, 2, 3, 4)
d = {1: 2, 3: 4}
s = {1, 2, 3, 4}
print(isinstance(l, Iterable))
print(isinstance(t, Iterable))
print(isinstance(d, Iterable))
print(isinstance(s, Iterable))
__iter__函数与__next__函数
迭代器遵循迭代器协议:必须拥有__iter__方法和__next__方法。
list、tuple等都是可迭代对象,我们可以通过iter()函数获取这些可迭代对象的迭代器。然后我们可以对获取到的迭代器不断使用next()函数来获取下一条数据。iter()函数实际上就是调用了可迭代对象的__iter__方法。
l = [1, 2, 3, 4]
l_iter = l.__iter__()
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
如何判断一个对象是否是迭代器
可以使用 isinstance() 判断一个对象是否是 Iterator 对象:
from collections import Iterator
isinstance([], Iterator)
False
isinstance(iter([]), Iterator)
True
isinstance(iter("abc"), Iterator)
True
生成器
初识生成器
Python中提供的生成器
- 生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次从它离开的地方继续执行。
- 生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表。
生成器Generator
- 本质:迭代器(所以自带了iter方法和next方法,不需要我们去实现)
- 特点:惰性运算,开发者自定义
生成器函数
一个包含yield关键字的函数就是一个生成器函数。
yield可以为我们从函数中返回值,但是yield又不同于return,return的执行意味着程序的结束,调用生成器函数不会得到返回的具体的值,而是得到一个可迭代的对象。每一次获取这个可迭代对象的值,就能推动函数的执行,获取新的返回值,直到函数执行结束。
def genrator_func1():
a = 1
print('将a赋值')
yield a
b = 2
print('将b赋值')
yield b
g1 = genrator_func1()
print(g1)
print(g1.__next__())
print(next(g1))