python基础——5.闭包,迭代器,装饰器,生成器
1.闭包:嵌套函数,内部函数调用了外部函数的变量
def outer():
a = 1
def inner():
print(a)
print(inner.closure)
outer()
# 只要打印函数的__closure__方法,有cell就是闭包
全局变量有可能被修改,全局变量是不安全的.用闭包可以保护我们的变量
写法:在外层函数中声明一个变量,在内层函数使用或者返回这个变量
闭包的应用,保护变量,常驻内存(全局变量也可以让变量常驻内存)
2.装饰器:不想修改函数的调用方式,但是还想在原来的函数前后添加功能
开放封闭原则;对扩展是开放的;对修改是封闭的;不让修改称之为封板
def timmer(f):
def inner():
start = time.time()
ret = f()
end = time.time()
print(end-start)
return inner
@timmer # 语法糖
def func():
time.sleep(1)
print("123")
ret = func()
# 原始写法
# func = timmer(func)
# func()
3.带参数的装饰器
flage = true
def timmer_out(flage):
def timmer(func):
def inner(args, **kwargs):
if flag:
start = time.time()
ret = func(args, **kwargs)
end = time.time()
print(end-start)
return ret
else:
ret = func(*args, **kwargs)
return ret
return inner
return timmer
@timmer_out(flage):
def func():
tim.sleep(1)
print("ok")
# 首先调了一个timmer_out(flage)理解成@和timmer_out(flage)分两步走
4.多个装饰器装饰一个函数
def wrapper1(func):
def inner1():
print("wrapper1, before func")
func()
print("wrapper1, after func")
return inner1
def wrapper2(func):
def inner2():
print("wrapper2, before func")
func()
print("wrapper2, after func")
return inner2
@wrapper2
@wrapper1
def f():
print("in f")
f()
5.打散聚合
def outer(args):
print(args)
print(args)
outer(1, 2, 3, 4) # == outer([1, 2, 3, 4]) == outer((1, 2, 3, 4))
# print(*args)返回的不是元组
# 原理是print函数带*arg参数
6.迭代器
只要含有__iter__方法的都是可迭代的--可迭代协议
迭代器协议--内部含有__next__和__iter__方法的都是迭代器
可迭代的.__iter__()方法可以得到一个迭代器
迭代器的.__next__()方法可以一个个的获取值
特征:1.节省内存 2.惰性机制 3.只能向前
7.生成器
生成器的本质就是迭代器,写法和迭代器一样
优点:1.节省内存,几乎不占内存 2.惰性机制 3.只能向前
生成器由生成器函数来创建或者通过生成器表达式来创建
在函数中return换成yield这个函数就是生成器函数
如何从生成器中取值:for next send 数据类型强制转换
def func():
for i in range(100):
yield "蛋%s" % i
func().__next__()
func().__next__()
def func():
print("123")
a = yield "abc"
print("234", a)
b = yield "bcd"
print("345", b)
yield "456"
gen = func()
gen.__next__()
def generator():
print(123)
content = yield 1
print("------", content)
print(456)
content2 = yield 2
print("------", content2)
print(789)
yield 3
g = generator()
ret = g.__next__()
print(ret)
ret = g.send("hello")
print(ret)
ret = g.send("hello2")
print(ret)
## send获取下一个值的效果和next基本一致
## 只是在获取下一个值的时候给上一个yield的位置传递一个参数
## 第一次使用生成器只能用next获取值;最后一个yield不能接收外部的值(所以可以最后加一个yield)
# 计算移动平均值
# 1.count计数 2.sum求和 3.avg平均值
# def init(average):
# def inner(*args, **kwargs):
# g = average(*args, **kwargs)
# g.__next__()
# return g
# return inner
#
# @init
# def average():
# sum = 0
# count = 0
# avg = 0
# while 1:
# num = yield avg
# sum += num
# count += 1
# avg = sum/count
#
# g = average()
# print(g.send(10))
# print(g.send(20))
#
# for i in [4, 5, 88, 9, 98, 66]:
# print(g.send(i))
## 生成器表达式
(条件成立想放在生成器中的值) for i in 可迭代的 if 条件
g = (i for i in range(10))
# 与列表推导式的区别 括号不一样 返回的值不一样