一、直接与间接程序开发潜规则
生活中:
有台电脑,他的硬盘空间不够了,里面的资料我不能动,也不能删,咋办
1.加装硬盘--直接解决--前提是我的电脑能加装
2.插个u盘--间接解决-->没有特别的要求,比较灵活
开发潜规则:
代码拓展-->开放-->可以加功能
源码修改-->封闭-->不能随便改源代码
一个程序做好之后,一般是不会随意删改里面的函数代码的
如果改了源代码,导致程序出bug了,修改起来很麻烦,所以一般不会再改源码
还有就是随便就能修改,那这样的代码安全性很差
所以有一个要求,就是对于写好的一些代码不应该再随便修改它
那如果要给这个函数加功能,那我们的做法就是可以
不修改函数的源代码,通过间接的方式去修改
间接修改--化妆--通过装饰器
直接修改--整容--修改源代码
二、初识闭包函数
闭:封闭,指的就是一个嵌套函数的内层函数
包:用内层函数,来操作外层函数得到的数据
作用:间接修改数据,保护私有数据不被轻易修改
闭包函数必备的条件:
1、必须是一个嵌套函数
2、内层函数必须操作外层函数数据(这个数据可以是一个变量或者是参数)
3、外层函数必须返回内层函数
闭包可以说就是为了装饰器而生的,单独写闭包意义不大,一般都是配合装饰器来使用
闭包格式:
def 外层函数():
def 内层函数():
操作外层函数的数据
return 内函数名 #不需要加括号
#普通函数
#有个打工仔小赵,钱包里刚开始是0元
money=0
def work(): #定义工作的函数
global money
money+=100
work() #工作一天
print(money) #100元
work() #工作二天
print(money) #200元
work() #工作三天
print(money) #300元
money=0 #天有不测风云,钱包被抢了
print(money) #0元
# #重新工作
work()
print(money) #上面的情况 因为没有封闭很容易被修改
#闭包 操作外层函数的变量
def person():
money = 0
def work_1():
nonlocal money
money+=150
print(money)
return work_1 #返回内层函数名 不需要现在调用
res=person() #res 等同于 work_1
res() ##res() 等同于 work_1()
res()
money=0
res() #450 并没有修改 因为我们这里是封闭的,闭包的作用就是保护私有数据不被轻易修改
检测闭包函数的使用:内函数名.__closure__
print(res.__closure__) #如果打印出来cell,则是闭包,如果是None,就不是闭包函数
#闭包 操作外层函数的参数
#process 是一个 可以给<函数>加功能的函数,给需要加功能的函数加一句话
#a只是形参,只是个名字,它是给要加功能的函数占位置,后面会接收一个函数作为实参传入进来
def process(a):
def product():
a() #a本质是一个函数,先调用你传进来的函数,确保原来的函数功能可以使用
print('我加了个鸡爪')
return product
def food():
print('我是螺蛳粉')
def rice():
print('我是一碗大米饭')
food=process(food) #用加了功能的函数,重新赋值给原函数,原函数才做到了加功能
food()
rice=process(rice)
rice()
三、初识装饰器(wrapper)
装饰器:本质就是一个函数,是一个特殊的闭包
添加装饰器的前提:
1.要有闭包函数的存在
2.要有被装饰的函数
装饰器的作用就是不修改函数源代码/参数的前提下,给一个或者多个函数添加功能
优点:
1.通过间接的方式,保护私有数据不被轻易改变,给函数加功能,会更安全
2.可以给一个/多个函数增加功能,更方便
私聊客服/购买/加入购物车 --> 功能函数
都需要先登录,判断是否登录是必须的,如果登录了才可以正常使用,否则转到登录界面
私聊客服:
判断是否登录
.......
购买:
判断是否登录
.......
专门写个工具函数,作用就是给每个函数增加一个登录功能-->判断是否登录装饰器--给一个/多个函数添加功能,反复使用,-->写一个装饰器,功能就是判断是否登录,然后把装饰器加在其他函数里就可以了
上面的加鸡爪的函数,就属于一个装饰器函数
1.process是一个工具函数 ,作用是给一个函数加功能
2.要给函数加功能,就得接收函数,a就是函数的形,给要加功能的函数先占好位置
3.接收好函数之后,先调用传进来的函数,确保它原来的功能可以正常使用,然后给它加功能
4.调用函数后,在内层函数里添加对应的功能
5.返回内层函数(原函数+添加功能)
装饰器的使用方式
1.函数名=装饰器(函数名) #用加了功能的函数重新赋值给原函数
2.语法糖
@装饰器 (外层函数名) #快速给下面的函数添加装饰器的功能
1、food=process(food)
food()
2、@process
def noodle():
print('我是一碗面条')
noodle()
def boy(person):
def sport():
person()
print('锻炼出来8块腹肌')
print('长高18cm')
return sport
@boy
def student():
print('我是蔡徐坤')
student()
@boy
def student2():
print('我是斑斑')
student2()
1、带参装饰器
#错误实例
# def girl(person):
# def make_up():
# person()
# print('给小美女化好美美的妆')
# return make_up
#
# @girl
# def name1(freind):
# print(f'我是小赵,带了一个朋友{freind}')
# name1('欧雅琪') #报错,因为你这要加功能的函数带了参数,而make_up没有给你的参数准备位置
#也就是如果你要加功能的函数 是有参数的话 是不是也要把参数一起接收过来呢?
#否则函数就不完整了,程序不会给你面子,直接报错
#正确做法
def girl(person):
def make_up(*args,**kwargs): #不管你要加功能的函数传什么类型的参数,传多少参数我都能接收
person(*args,**kwargs)
print('给小美女化好美美的妆')
return make_up
@girl
def name():
print('我是小赵')
name()
@girl
def name1(freind):
print(f'我是小赵,带了一个朋友{freind}')
name1('小张')
@girl
def name2(freind1,freind2):
print(f'我是小赵,带了两个朋友{freind1}和{freind2}')
name2('小张','小王')
def people(a):
def thing(*args,**kwargs):
a(*args,**kwargs)
print('准备房间...')
return thing
@people
def fun1():
print('我是单身')
fun1()
@people
def fun2(child1,child2):
print(f'带俩娃,一个是{child1},另一个是{child2}')
fun2('男孩','女孩')
2、装饰器总结
什么情况下会用到装饰器
一个相同功能可能会在很多函数都会用上(登录,收藏,购买),这种情况就可以把函数写为装饰器
特性:在不修改源代码的基础上,给函数加功能
四、print调试
我们一般不用print-->以后做网站后台/小程序后台/爬虫
1.爬虫的东西一般就是发送请求/保存数据
2.写后台都是操作数据-->输出内容都是前端的
有一个项目有几百行的代码,运行没有报错,但是有的功能没有实现
这时候就可以用print调试
比如代码一共500行,现在有功能没有实现
这个时候就可以在100,200,300,400行各写一个print,运行程序,看程序运行到哪个print,哪个print没有输出,就知道是哪一段代码有问题
输出了第200行的print,前200行没问题,后面的代码有
五、分享几个可以用来学习的博客
https://www.cnblogs.com/huxi/archive/2011/03/01/1967600.html
https://www.cnblogs.com/Jerry-Chou/archive/2012/05/23/python-decorator-explain.html
https://www.cnblogs.com/cotyb/p/5243252.html
https://www.cnblogs.com/rhcad/archive/2011/12/21/2295507.html
这篇文章到这就结束了,有什么问题欢迎随时评论或者私信哦~