函数对象-->把函数当成一个普通数据来使用,该干嘛就干嘛
1.函数可以用来赋值
2.函数可以放到容器里(列表,字典,元组)
3.函数可以作为参数
4.函数可以作为返回值
名称空间-->存放python程序里名字的地方
1.内建名称空间--内置函数
2.全局名称空间--定义在程序外部的名字
3.局部名称空间--定义在函数内的名字
作用域:一个数据能够被使用的范围
全局:整个程序里他都可以使用
局部:程序里的部分位置才能使用
global--将一个局部变量升为全局或者修改全局变量的值
nonlocal--在嵌套函数中,内层函数修改外层函数的变量值
匿名函数:
一个函数,可以先把他的功能先写好,需要用的时候,取个名字,再调用
lambda 变量:操作
生活中:
有台电脑,它的硬盘空间不够了,里面的资料既不能删,不能移动,咋办
1.插个u盘--间接解决-->没有特别的条件要求,比较灵活
2.加装硬盘--直接解决-->前提是我的电脑能加装
开发潜规则:
代码拓展-->开放-->可以加功能
源码修改-->封闭-->不能修改源码
一个程序做好之后,一般是不会随意删改里面的函数代码的
如果改了源代码,导致程序出BUG了,修复起来就很麻烦,并且可以随便就能修改,那这样的代码安全性很差,所以一般就不会再改源码
所以有个要求 就是对于一些写好了的代码,不应该在随便改它
那如果要给这个函数加功能,可以通过装饰器间接的给函数加功能
直接修改--整容--修改源代码
间接修改--化妆--通过装饰器
闭:封闭,指的是一个嵌套函数里的内层函数
包:用内层函数,来操作外层函数得到的数据
作用:间接修改数据 保护私有数据不被轻易修改
闭包函数必备的条件
1.必须是一个嵌套函数
2.内层函数必须操作外层函数数据(这个数据可以是一个变量或者是参数)
3.外层函数必须返回内层函数
闭包可以说就是为了装饰器而生的,单独写闭包不大,一般都是配合装饰器来使用
闭包格式:
def 外函数名():
def 内函数名():
操作
return 内函数名
#普通函数 因为没有封闭很容易被修改
#有个打工仔
#钱包
# money=0
#
# #定义工作的函数
# def work():
# global money
# money+=100
#
# work() #工作一天
# print(money)
# work() #工作两天
# print(money)
#
# #天有不测风云 钱被抢了
# money=0
# print(money)
# #重新工作
# work()
# print(money)
#闭包 操作外层函数的变量
def person():
money = 0
def work_1():
nonlocal money
money+=150
print(money)
return work_1 #返回内层函数 不需要加括号调用
res=person() #把person的返回值赋值给res res等同于work_1
res() #res() 等同于work_1()
res()
money=0
res() #450 并没有修改,因为我们这里是封闭的,闭包就是保护私有数据不被轻易修改
# 检测闭包函数的使用:内函数名.__closure__
print(res.__closure__) #cell是闭包
#闭包 操作外层函数的参数
#process只是一个可以给<函数>加功能的工具函数,目的是给函数加一句话(加鸡爪)
#a只是形参,只是个名字,他是给后续要加功能的函数先占个位置.它后面会接收一个函数作为参数传进来
def process(a):
def product():
a() #a本质是一个函数,先调用你传进来的函数 确保原来的函数功能可以使用
print('我加了个鸡爪')
return product
def food():
print('我是螺蛳粉')
def rice():
print('我是一碗白米饭')
food=process(food) #把这个food函数传进去,让工具函数加个功能 最后重新赋值给food food才是加好功能的之后函数
food()
rice=process(rice)
rice()
装饰器:本质就是一个函数,是一个特殊的闭包
添加装饰器的前提:
1.要有闭包函数的存在
2.要有被装饰的函数
装饰器的作用就是在不修改函数源代码/参数的前提下,给函数添加功能,并且可以给多个函数添加功能
优点:
1.通过间接的方式,保护私有数据不被轻易改变,给函数加功能,更安全
2.可以给一个/多个函数增加功能,更方便
购买/加购物车/私聊客服..-->功能函数
我要加一个功能,判断是否登录,如果登录了才可以正常使用,否则跳转到登录界面
私聊客服:
判断是否登录
购买:
判断是否登录
加购物车:
判断是否登录
我专门写个工具函数,作用就是给每个函数增加一个登录功能-->判断是否登录装饰器-->给一个函数添加功能/反复使用-->写一个装饰器,功能就是判断是否登录。然后把装饰器加在其他函数里就可以了
上面的加鸡爪函数,就属于一个装饰器函数
1.process是一个工具函数,作用是给一个函数加功能
2.要给函数加功能,就得接收函数,a就是函数的形参
3.接收好函数之后,先调用传进来的函数,确保原来的功能可以正常使用
4.调用函数后,在内层函数里添加对应的功能
5.返回内层函数(原函数+添加功能)
装饰器的使用方式
1.函数名=装饰器(函数名) #用加了功能的函数重新赋值给原函数
food=process(food)
food()
2.语法糖
@装饰器(外层函数名) #快速给下面的函数添加装饰器的功能
@process
def noodle():
print('我是一碗面条')
noodle()
def study(person):
def study1():
person()
print('好好学习,天天向上')
return study1
@study
def name():
print('我是王五')
name()
@study
def name1():
print('我是张三')
name1()
def make_up(person):
def make_up1(*args,**kwargs):
person(*args,**kwargs)
print('给美女画好美美的妆')
return make_up1
@make_up
def girl():
print('我是美女小美')
girl()
@make_up
def girl1(friend):
print(f'我是美女小美,带个{friend}')
girl1('小美') #报错,因为你这里带了参数,而make_up1没有给你的参数准备位置
@make_up
def girl2(friend1,friend2):
print(f'我是美女小美,带好朋友{friend1}和{friend2}')
girl2('小红','小丽') #报错,因为你这里带了参数,而make_up1没有给你的参数准备位置
什么情况下会用到装饰器:
一个相同的功能可能会在很多函数都会用上,这种情况就可以把函数写为装饰器
特性:在不修改源代码的基础上,给函数间接加功能
实现原理:
1.在一个嵌套函数中,用外层函数接收一个函数作为参数,内层函数就会接收函数的参数
2.在内层函数中调用函数,并写一个要增加的功能
3.外层函数,返回内层函数-->返回出去的就是(加好功能的函数)
以后我们一般不用print-->以后做网站后台/小程序后台/爬虫
1.爬虫的东西一般就是发送请求/保存数据
2.写后台的都是操作数据-->输出内容都是前端干的
有一个项目有几百行的代码,运行没有报错,但是有的功能没有实现,这时候就可以用print来调试
比如代码一共500行。现在有功能没实现
这时候可以在100,200,300,400行各写一个print,运行程序,看看程序运行到哪个print,哪个print没有输出,就知道是哪一段代码有问题
输出了200,前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