3.装饰器
3.1 闭包
如果在一个内部函数里,对外层作用域的变量进行引用(不是全局作用域),那么这个内部函数被称为闭包
闭包 = 内部函数+外部环境
作用:使垃圾回收机制不回收外部函数所占用资源,使依赖外部变量的内部函数顺利执行,实现从外部访问函数内部的变量
def outer():
x=100
def inner(): # inner为内部函数
print(x) # 调用了外部变量x
return inner # inner为闭包
outer()() # 100
分析:outer() 返回为inner,在调用inner(),但在此步中**outer函数已经执行完成,**在执行inner中print(x)是找不到x变量的,但能返回100正确值,这种现象为闭包
3.2 装饰器
开放封闭原则:对修改封闭,对扩展开放
def decoration(func):
def inner():
print('Function Starts...')
func()
print('Function Ends...')
return inner
@decoration # foo=decoration(foo)
def foo():
print('foo...')
@decoration # bar=decoration(bar)
def bar():
print('bar...')
foo()
print('='*20)
bar()
decoration是装饰器,foo 和bar 是功能函数,decoration给功能函数扩展功能
装饰器帮我们做的就是将执行代码从下面框框转到上面框框
对于含有参数的装饰器:
(1)功能函数有参数
def decoration(func):
def inner(x,y):
print('Function Starts...')
func(x,y)
print('Function Ends...')
return inner
@decoration
def add(x,y):
print(x+y)
@decoration
def mul(x,y):
print(x*y)
add(2,3)
mul(2,3)
在inner 和 func 中要同步参数
(2)装饰器函数有参数
def logger(flag='Ture'):
def decoration(func):
def inner(x,y):
print('Function Starts...')
func(x,y)
print('Function Ends...')
if flag=='Ture':
print('已记录日志')
return inner
return decoration
@logger() # @logger() -> @decoration,作用为传递了一个参数flag
def add(x,y):
print(x+y)
@logger('a')
def mul(x,y):
print(x*y)
add(2,3)
print('='*20)
mul(2,3)
在原本装饰器函数外在加一个带参数函数,使原来装饰器函数成为闭包。logger()执行返回decoration, @logger() -> @decoration ,区别就是传递了一个flag函数
4.生成器和迭代器
4.1 列表生成器
def f(x):
return x**2
list1=[f(x) for x in range(1,11)]
list2=[x**2 for x in range(1,11)]
# [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
4.2 生成器
优点:节省内存,用的时候拿出
(1) (x*2 for x in range(1,6))生成
a = (x*2 for x in range(1,6))
print(a) #<generator object <genexpr> at 0x000001FA8C17FC10>
# print(a.__next__()) # 在Py2中 a.next()
# print(next(a)) # 2
# print(next(a)) # 4
# print(next(a)) # 6
# print(next(a)) # 8
# print(next(a)) # 10
# 生成器为可迭代对象
for i in a:
print(i)
(2)yield 生成生成器
def foo():
print('First')
yield 1
print('Second')
yield 2
print('Third')
yield 3
print(foo) #<function foo at 0x00000208561BA940>
print(foo()) # <generator object foo at 0x00000208561BFC10>
a = foo()
for i in a:
print(i)
总结yield:只能在函数内使用
1.yield提供了一种自定义迭代器的解决方案
2.yield可以保存函数的暂停的状态
3.yield对比return:相同点,都可以返回值,值得类型与个数没有限制,不同点:yield可以返回多次值,而return只能返回一次值函数就会结束
(3) send() 给函数里传值
def foo():
print('First')
yield 1
print('Second')
count =yield 2
print(count)
print('Third')
yield 3
a = foo()
print(a.send(None)) #First 1
print(a.send(2)) #给yield 1 结果:Second 2
print(a.send(3)) #给yield 2,也就是count 结果:3 Third 3
4.3 迭代器
迭代器:
1既内置有__next__方法的对象,执行该方法可以不依赖索引取值
2.又内置有iter方法的对象,执行迭代器的__iter__方法得到的依然是迭代器本身
生成器都是迭代器,迭代器不一定都是生成器
list1 = [1,2,3]
# print(list1.__iter__())
print(iter(list1)) #<list_iterator object at 0x00000284839B8A60> 用内置方法iter()来替代__iter__()