1.生成器
1.什么是生成器
什么是生成器呢.
简单来讲就是在你准备输出内容时又不想将全部内容输出,使用生成器可以将输出的内容储存为一个地址,等到需要的时候可以再对内容接着输出,若输出内容为多个的话则使用一次生成器执行一次内容.
2.创建生成器的方式
它与列表解析式有点相像:
# 列表解析式
list1 = [x for x in range(3)]
print(list1) # [0, 1, 2]
# 一.
# 创建生成器第一种方式
# 此处调用次数为3次,超出则报错
list1 = (x for x in range(3)) # 将列表解析式的[]改成()
# <generator object <genexpr> at 0x00F79568>
print(list1)
print(next(list1)) # 0
print(next(list1)) # 1
print(next(list1)) # 2
list1 = ("hello" for i in range(3))
# <generator object <genexpr> at 0x00F90D10>
print(list1)
print(next(list1)) # hello
print(next(list1)) # hello
print(next(list1)) # hello
# 二.
# 使用yield方法
# 只要函数中含有 yield 这个关键字,这个函数就变成了生成器
# 需求1、1、2、3、5、8、13、21、34、……后一个数为前两个数之和
# 定义一个函数
def createNum():
print("__1__")
a, b = 0, 1
for i in range(3):
print("__2__")
yield b
print("__3__")
a, b = b, a + b
print("__4__")
# 定义一个变量
num = createNum()
# 因为该定义函数又yield方法,所以是一个生成器,生成器将输出数据储存为地址,需要调用才对其进行输出
print(num) # <generator object createNum at 0x01E91D10>
# 使用next()方法或者变量.__next__()方法调用
print(next(num))
"""
__1__
__2__
1 执行到yield b 时停止运行
"""
print(num.__next__()) # 再次调用才往下执行循环到yield b 停止
"""
__3__
__4__
__2__
1
"""
另外可以用send()方法进行传值👇
# 定义一个函数
def createNum():
for i in range(5):
r = yield i
print(r)
a = createNum()
# print(next(a))
# print(next(a))
# print(next(a))
# print(next(a))
# print(next(a))
# 正常调用执行
"""
其中调用函数中yield i没有传值默认为None
0
None
1
None
2
None
3
None
4
"""
# 使用send()给yield i整体传值
# can't send non-None value to a just-started generator 无法将非 None 值发送到刚启动的生成器
a.send(None)
a.send("hello")
a.send("world")
print(next(a))
print(next(a))
"""
第一次传值
hello
第二次传值
world
None
3
None
4
"""
3.多任务处理
def test1():
while True:
print("---1--")
yield None
def test2():
while True:
print("---2--")
yield None
# 只是定义了生成器(存储了数据生成的方式,等待调用) 协处理器
t1 = test1()
t2 = test2()
# 循环执行生成器中内容
while True:
t1.__next__()
t2.__next__()
2.迭代器
可迭代的: 凡是可以通过for循环取值的都是可迭代的 凡是可以被next函数调用取值,并且返回下一个值的对象就是一个迭代器 (生成器一定是一个迭代器,迭代器不一定就是生成器)
# 迭代器
text1 = "hello python"
# 使用iter()方法转换为迭代器
text = iter(text1)
# print(next(text))
# print(next(text))
# print(next(text))
# print(next(text))
# print(next(text))
"""
h
e
l
l
o
"""
# 自动输出
for i in text:
print(i)
# 此外我们可以导入包来进行查看是否符合迭代器规则
from collections import Iterable
print(isinstance("abc",Iterable)) # True
print(isinstance(123,Iterable)) # False
3.闭包
什么是闭包?
在一个函数中,又定义了一个函数,并且里面的函数使用了,外面的函数的参数,这个整体就是一个闭包
什么时候会用到闭包?
外面的函数给定了基础条件,里面的函数基于原来的基础之上进行进一步处理
# 定义一个函数
def text(num):
print("--1--")
def text_in(): # 函数内定义一个函数
print("--2--")
print(num + 50) # 在原先函数的参数上增加
print("--3--")
return text_in
a = text(100)
# 👇 对变量a进行输出,执行到return text_in返回了该函数的内存地址就结束了并没有对该函数执行
print(a)
# 在text(100)赋值给a的基础上调用a方法 即a()执行text_in里的条件
a()
"""
--1--
--3--
<function text.<locals>.text_in at 0x017B2C88>
--2--
150
"""
闭包执行顺序图例:
1.闭包应用
# 闭包的应用
def text(func):
def text_in():
# 假设这里面是一堆你设置的条件
# ……………
print("已完成操作!")
func()
return text_in
def f1():
print("hello")
def f2():
print("python")
# 在定义函数text(参数)传入f1作为参数
print(text(f1)) # <function text.<locals>.text_in at 0x01DA2C88>
# 给定一个变量接收
f1 = text(f1)
f1() # 调用该方法
f2 = text(f2)
f2()
"""
已完成操作!
hello
已完成操作!
python
"""
4.装饰器
# 闭包的应用
def text(func):
def text_in():
# 假设这里面是一堆你设置的条件
# ……………
print("已完成操作!")
func()
return text_in
@text # 在函数上写入@对应的闭包函数就是装饰器
def f1():
print("hello")
@text
def f2():
print("python")
f1()
f2()
"""
已完成操作!
hello
已完成操作!
python
"""
1.多层装饰
#定义函数:完成包裹数据
def makeBold(fn):
print("--makeBold--")
def wrapped():
print("----markBlod11111--")
return "<b>" + fn() + "</b>"
return wrapped
#定义函数:完成包裹数据
def makeItalic(fn):
print("--makeItalic---")
def wrapped():
print("----makeItalic11111--")
return "<i>" + fn() + "</i>"
return wrapped
@makeItalic
@makeBold
def test1():
return "初次见面!"
a = test1()
# 输出结果为
"""
--makeBold--
--makeItalic---
👆 因为调用了装饰器所以从上往下执行了闭包外函数的输出
👇 多层装饰器执行顺序为先执行离函数近的装饰器:makeBold,然后上层装饰器在下层执行完之后的结果进行再一次装饰输出
----makeItalic11111--
----markBlod11111--
"""