1.闭包
# 装饰器给已有的函数增加额外的功能,它的本质是一个闭包函数
# 闭包函数
# 函数,函数调用完之后,内部定义的变量直接销毁了,但是有时候我们需要保存函数内的这个变量
# 在这个变量进行一些其他操作,比如求和
# 闭包:
# 形成条件
# 1.实现函数嵌套
# 2.内部函数使用外部函数的变量
# 3.外部函数返回内部函数的名字,不要加括号
# 简单写个闭包
def tes01(a):
b = 1
def tes02():
print(a,b)
return tes02
# a = test02
a = tes01(6)
# test02()
a()
# print里面会返回什么 6,1
# 步骤:是怎么运行的?
# 函数是从上到下执行,只要在函数调用 也就是函数名()才会执行到函数内部
# 不会走到test02 test02()才会执行到test02函数内部
# return 返回test02 test02给谁?
# 定义两个数字相加求和
# result = num1 + num2 num1+=num2 可以吗?1 不可以2
def outer(num1):
print(num1)
def inner(num2):
result = num1 + num2
print(result)
return inner
# inner只是一个名, 没加()
# 不是固定写法 c是变量名随便取 c就是为了取 inner
c = outer(5)
c(9)
# 函数从上到下执行,只有函数名(参数)的时候才会执行
# 打印print(5)
# print之后
# 1.outer(5)先走入到outer(num1)函数内部,num1就是5,打印出来的也是5
# 接下来不会走入到inner(num2)函数内部。返回inner给到outer(5),所以outer(5)就是inner.
# c = inner c(9)就相当于inner(9)触发了函数条件.打印出来的就是14
# def inner(num2):
# result = num1 + num2
# print(result)
# 没有触发条件 inner(num2)
# 返回inner a就是inner c(9) == inner(9)
def outer(num1):
print(num1)
def inner(num2):
nonlocal num1
num1+=num2
print(num1)
return inner
d = outer(5)
d(8)
# 定义一下num1编程global
# 不用global定义修改值用于不同函数 这里用nonlocal:作用对象是外层的变量,就是用在闭包里面
# 普及知识点: 局部变量
# 局部变量: 定义在函数内部
# 全局变量: 定义在函数外部
# num1 = 100
def tes01(num2):
#局部变量
num2 = 3
def tes02(num1):
# 局部里面不能直接修改外部变量
# 在函数内部要修改全局变量的值 用到global
nonlocal num2
num2 += num1
print(num1)
return tes02
e = tes01(5)
e(3)
# 闭包的作用: 变量不会污染全局变量, 不会因为外部函数调用而销毁掉
2.装饰器
# 装饰器:就是给已有的函数增加额外的功能
# 特点:
# 不需要修改原有的代码,就能增加函数额外的功能
# 不用修改调用方式
# 发表评论 检查一下我有没有登录 没有登录 登录一下
# 闭包
# check(comment)
def check(fc):
print('装饰器函数执行')
def inner():
print('请先登录')
fc()
return inner
# check(comment)
@check
def comment():
print('发表评论')
# 调用方式更改了
# f = check(comment)
# f()
# 装饰器的语法糖改一下 @额外函数的功能
comment()
# @check装饰器 怎么去运行的?@check相当于代理
# 现在要运行comment()代理人预约走入到
# 1.先打印 print('装饰器函数执行')
# 不会走入到inner函数内部,没有被调用,返回inner 这个inner返回给谁
# inner返回给秘书inner = comment()
# 2.print('请先登录')
# 3.fc() fc是comment comment()
3.练习题目
# 现在有个函数,想要知道这个函数执行了多长时间
import time
def decorate(fc):
def inner():
# 获得当前的时间
print(time.strftime('%Y-%m-%d %H:%M:%S'))
t_starttime = time.time()
b=fc()
print(b)
# 结束时间的时间戳
t_endtime = time.time()
print(time.strftime('%Y-%m-%d %H:%M:%S'))
# 结束时间 - 开始时间秒数 = 剩余秒数
print('总共花了%.5f'%(t_endtime - t_starttime))
return 1314
return inner
# decorate(tes01)
@decorate
def tes_01():
time.sleep(2)
print('函数在执行中')
return 520
g = tes_01()
print(g)
4.迭代器
# 自定义迭代器里面 iter 还有一个next
# 数据类型:字符串 列表 元组 集合字典 是不是可以用for循环拿到里面的数据类型
# for里面是怎么运行 台前看不到
# 特殊方法__iter__() 返回一个迭代器对象,迭代器对象里面在用__next__()把里面的数据拿出来
# 多拿了一个
a = [1,2,3,4]
b = (1,2,3)
# print(a.__iter__())
# print(b.__iter__())
iterA =a.__iter__()
print(iterA.__next__())
print(iterA.__next__())
print(iterA.__next__())
print(iterA.__next__())
5.生成器
# 也就是一个特殊的迭代器,使用yield的函数就被称为生成器,不是一个普通的函数了
5.1第一种yield
def gen(n):
# 0,1,2,3,4
for i in range(n):
# 每次遇到yield时候函数暂停并报错当前的运行信息
yield i * i
# 不会直接进入gen(5)生成器内部,需要循环或者next才会进入到生成器函数内部
x = gen(5)
for i in x:
print(i)
5.2第二种推导式外层()用也表示生成器
gen = (i * i for i in range(5))
for i in gen:
print(i)
def gen():
yield
print(gen())
# send方法实现生成器内部进行数据交互
# close关闭生成器