一、生产消费模型
场景:一个生产商品,一个消费商品。如果生产商把所有商品生产完毕后,再丢给消费,效率极其低下。
测试代码如下:
import time
def producer(num):
res_l = []
for i in range(1, num + 1):
time.sleep(0.1)
print("产品{}生产完毕".format(i))
pro_s = "产品{}".format(i)
res_l.append(pro_s)
return res_l #全部生产完毕后,交给消费端。如果有亿万级别的数据,内存消耗高
def consumer(product_l):
for i in product_l:
print("消费{}".format(i))
start = time.time()
consumer(producer(50))
end = time.time()
print("花费 %.2f秒" %(end-start))
# 输出 花费 5.15秒
使用生产消费模型改写
import time
def producer(num):
for i in range(1, num + 1):
time.sleep(0.1)
print("产品{}生产完毕".format(i))
pro_s = "产品{}".format(i)
yield pro_s # 通过生成器函数,生产一个返回一个,节约资源
def consumer(product):
while 1:
for i in product: # 消费端死循环,调用生成器next方法进行消费。
print("消费",i)
break
start = time.time()
consumer(producer(50))
end = time.time()
print("花费 %.2f秒" %(end-start))
二、修饰器
修饰器本质就是函数
修饰器的特性:1、不修改原函数调用方式及代码 2、为该函数提供额外的功能
其公式为 修饰器 = 高阶函数 + 函数嵌套 + 闭包(变量作用域)
为了能更好的掌握修饰器,对前面只是进行复习
2.1 高阶函数
高阶函数:可以通过函数作为参数传递 或 返回值是一个函数
# 通过参数来接收一个函数变量,并调用
def high_f1(func):
func()
# 通过返回值来返回一个函数变量
def high_f2():
return foo
# 既通过函数参数传递,还返回一个函数变量
def high_f3(func):
return func
# 普通函数
def foo():
print("hell foo")
high_f1(foo)
high_f2()()
high_f3(foo)()
2.2 函数嵌套
函数嵌套,即函数中再定义了个函数。在python中,函数即变量的原则。所以这种方式是被允许的。
Python 3.7.2 (default, Feb 12 2019, 08:15:36)
[Clang 10.0.0 (clang-1000.11.45.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> def fun1():
... print("from fun1...")
... def fun2():
... print("from fun2..")
... def fun3():
... print("from fun3...")
... fun3()
... fun2()
...
>>> fun1()
from fun1...
from fun2..
from fun3...
2.3 变量的作用域
变量的作用域一般都是寻找自己层级,如果没有再向外一层级寻找。
>>> def fun1(name):
... print("from fun1...",name) # 使用传递的name
... def fun2():
... print("from fun2..",name) # 本层级作用域没有找到name变量,向上一级寻找name
... def fun3():
... name = "bb"
... print("from fun3...",name) # 本层级找到name变量,直接使用
... fun3()
... fun2()
...
>>> fun1("aa")
from fun1... aa
from fun2.. aa
from fun3... bb
2.3.1 global关键字
一般局部作用域中,无法对全局作用域中的变量进行修改。但是使用了global关键,使得这种场景变成可能。
name = "hello"
def fun1(name):
print("from fun1...",name) #使用形参变量
def fun2():
global name
name = "world" #修改全局变量name
print("from fun2..",name) #自己作用域中没有该变量,使用全局作用域变量
def fun3():
print("from fun3...",name)#自己作用域中没有该变量,使用全局作用域变量
fun3()
fun2()
fun1("aa")
# from fun1... aa
# from fun2.. world
# from fun3... world
print(name)
# world
2.3.2 nonlocals关键字
但是有这么一种场景,需要修改上层作用域的变量,不修改全局作用域变量。那么此时需要使用nonlocals来实现
name = "全局作用域"
def fun1():
name = "fun1"
print("from fun1...",name) #使用形参变量
def fun2():
nonlocal name
name = "nonlocal" #修改全局变量name
print("from fun2..",name) #自己作用域中没有该变量,使用全局作用域变量
def fun3():
print("from fun3...",name)#自己作用域中没有该变量,使用全局作用域变量
fun3()
fun2()
fun1()
# 打印如下
# from fun1... fun1
# from fun2.. nonlocal
# from fun3... nonlocal
print(name)
# 全局作用域
2.4 使用修饰器
2.4.1 需求,对A函数增加时间统计功能
在不修改调用方式,不修改函数内部代码的大前提下。A函数如下
def A():
for i in range(5):
print("hi:%s" % i)
# 调用A函数
A()
使用修饰器函数进行增加功能
import time
def timer(func):
def wapper():
start_time = time.time()
func() #寻找上层作用域func并调用
end_time = time.time()
print("执行时间:%s" % (end_time - start_time))
return wapper
@timer #通过timer函数来传递A的函数名作为参数
def A():
for i in range(5):
print("hi:%s" % i)
# 调用A函数
A()
# 输出:
# hi:0
# hi:1
# hi:2
# hi:3
# hi:4
# 执行时间:8.821487426757812e-05