python开发基础——day12 闭包与装饰器

一、上节回顾

函数对象-->把函数当成一个普通数据来使用,该干嘛就干嘛
    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()

四、初识装饰器(wrapper)

装饰器:本质就是一个函数,是一个特殊的闭包

添加装饰器的前提:

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()

4.1带参装饰器

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没有给你的参数准备位置

4.2装饰器总结

什么情况下会用到装饰器:
    一个相同的功能可能会在很多函数都会用上,这种情况就可以把函数写为装饰器
    
特性:在不修改源代码的基础上,给函数间接加功能
    
实现原理:
    1.在一个嵌套函数中,用外层函数接收一个函数作为参数,内层函数就会接收函数的参数
    2.在内层函数中调用函数,并写一个要增加的功能
    3.外层函数,返回内层函数-->返回出去的就是(加好功能的函数)

五、print调试

以后我们一般不用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

你可能感兴趣的:(python学习,python,开发语言)