闭包装饰器与递归
闭包
定义
1. 闭包是嵌套在函数中的函数。
2. 闭包必须是内层函数对外层函数的变量(非全局变量)的引用。
3.默认参数就是闭包原理
4.函数拥有自由变量
如何判断判断闭包
如果此函数拥有自由变量,那么就可以侧面证明其是否是闭包函数了
利用 函数名.__code__.co_freevars 查看函数的自由变量
闭包的作用
保存局部信息不被销毁,保证数据的安全性。
装饰器
1.遵循开放封闭原则:
开放:对代码的拓展开放的, 更新地图,加新枪,等等。
封闭:对源码的修改是封闭的。
2.在不改变原函数的代码以及调用方式的前提下,为其增加新的功能。
装饰器就是一个函数。
标准版的装饰器
def wrapper(f):
f = zz # 第2步
def inner(*args, **kwargs): # 第5步
ret = f(*args,**kwargs)#第7步
return ret
return inner # 第3步
@wrapper #语法糖做了这件事 zz=weapper(zz) 第一步
def zz(): # 第4步 此时zz 为 inner
pass
带参数的装饰器
def wrapper_out(n,*args,sex="男")
def wrapper(f):
def inner(*args,**kwargs):
ret = f(*args,**kwargs) # 这边执行的是func1()
return ret
return inner
return wrapper
def func1():
print("in func1")
func = wrapper_out(1) # wrapper函数名
ly = fun(func1) # inner = wrapper(func1)
ly() # inner()
def wrapper_out(n):
def wrapper(f):
def inner(*args,**kwargs):
if n == "qq":
username = input("请输入用户名:").strip()
password = input("请输入密码:").strip()
with open("qq",encoding="tuf-8") as f1:
for line in f1:
user,pwd = line.strip().split("|")
if username == user and password == pwd:
print("登陆成功")
ret = f(*args,**kwargs)
return ret
return False
elif n == "yiktok":
username = input("请输入用户名:").strip()
password = input("请输入密码:").strip()
with open("qq",encoding="tuf-8") as f1:
for line in f1:
user,pwd = line.strip().split("|")
if username == user and password == pwd:
print("登陆成功")
ret = f(*args,**kwargs)
return ret
return False
def wrapper_out(n):
def wrapper(f):
def inner(*args,**kwargs):
username = input("请输入用户名:").strip()
password = input("请输入密码:").strip()
with open(n,encoding="tuf-8") as f1:
for line in f1:
user,pwd = line.strip().split("|")
if username == user and password == pwd:
print("登陆成功")
ret = f(*args,**kwargs)
return ret
return False
return inner
return wrapper
@ wrapper_out("qq")
def qq():
print("成功访问qq")
qq()
# 看到带参数的装饰器分两步执行:
@ wrapper_out("腾讯")
# 1.执行wrapper_out("腾讯"),把相应的参数传给n,并且得到返回值wrapper函数名
# 2.将@与wrapper结合,得到我们之前熟悉的标准版装饰器,按照装饰器的执行流程执行
@ wrapper_out("qq")
def qq():
print("成功访问qq")
@ wrapper_out("tiktok")
def tiktok():
print("成功访问抖音")
qq()
tiktok()
# 开发思路:增强耦合性
多个装饰器装饰一个函数
def wrapper1(func1): # func1 = f原函数
def inner1():
print('wrapper1 ,before func') # 2
func1()
print('wrapper1 ,after func') # 4
return inner1
def wrapper2(func2): # func2 == inner1
def inner2():
print('wrapper2 ,before func') # 1
func2() # inner1
print('wrapper2 ,after func') # 5
return inner2
@wrapper2 # f = wrapper2(f) 里面的f == inner1 外面的f == inner2
@wrapper1 # f = wrapper1(f) 里面的f == func1 外面的f == inner1 先看下面
def f():
print('in f') # 3
f() # inner2() 看外层f
递归
1.官网规定:默认递归的最大深度1000次。
2.递归效率很低 总是要开辟空间, 递归比起循环来说更占用内存
3.递归就是自己调自己
4.修改递归的最大深度
# import sys
# sys.setrecursionlimit(1000000000)
递归的剖析
# 递归函数是怎么停下来的?递归3次结束整个函数
# 一个递归函数要想结束,必须在函数内写一个return,并且return的条件必须是一个可达到的条件
# --注意---并不是函数中有return,return的结果就一定能够在调用函数的外层接收到 谁调用最后一个函数返回给谁
# 加上return tet
# def func(count):
# count += 1
# print(count)
# if count == 5 : return 5#这个5其实是返回给下面的func()
# ret = func(count)#要想把这个5返回给最外层 所以逐层returt
# return ret
# 精简版
def func(count):
count += 1#这里是代码思路
if count == 5 :
return 5#这个5其实是返回给下面的func()
return func(count)#精简了上面的过程
递归的列子
1.计算阶乘 100! = 100*99*98*97*96....*1
def fin(n):
if n ==1 :
return n
else:
return n*fin(n-1)
ret = fin(7)
print(ret)
l2 = [1, 3, 5, ['太白','元宝', 34, [33, 55, [11,33]]], [77, 88],66]
# 递归
# def func(alist):
# for i in alist:
# if type(i) == list:
# func(i) # func(['太白','元宝',34])
# else:
# print(i)
# func(l2)
2.三级菜单 可能是n级
3.os模块:查看一个文件夹下的所有文件,这个文件夹下面还有文件夹,不能用walk
4.os模块:计算一个文件夹下所有文件的大小.这个文件夹下面还有文件夹,不能用 walk
5.计算斐波那契数列找第100个数
6.计算阶乘 100! = 100*99*98*97*96....*1
非学,无以致疑;非问,无以广识