函数,闭包,装饰器详解

再讲装饰器之前先说一下函数,首先看下面的例子(只适合初学者阅读):

def func():
    pass
    print('in func')

#可以把函数内存地址赋值给另一个对象,导致另一个对象也指向了函数代码
f=func
f()

输出的结果为:in func
结果说明可以把内存地址传给别的对象

def func():
    print('in func')
    def func_in():
        print('in func_in')

func()

结果为 in func
此时内函数的in func_in并没有输出说明内函数并没有执行,此时可以得要只有函数名+()才能调用函数 所以 func_in 并没有被调用的结论

那么什么是闭包呢?

闭包就是函数的返回值是另一个函数的名称。
举例:

def func():
    print('in func')
    def func_in():
        print('in func_in')
    return func_in

f = func()

结果为:in func
此时函数func_in也并没有调用所以不输出结果in func_in,那如果想要in func_in该如何做,看下面的例子:

def func():
    print('in func')
    def func_in():
        print('in func_in')
    return func_in

f = func()
print(f)
f()

结果为:

in func
<function func.<locals>.func_in at 0x00000216C65AAA60>
in func_in

在上面例子的基础上输出f函数即可,咱们打印了一下f,此时可以看到在未调用的时候打印的结果是f函数的内存地址。只有真正调用了函数名+()才能执行, 只有函数名的话只有地址

在看函数的最后一个案例:

def func(number1):   #外部函数
    print('in func')
    def func_in(number2):   #内部函数
        print('in func_in %d'%(number1 + number2))
    return func_in

f = func(99)
f(1001)

输出结果为:

in func
in func_in 1100

此结果可以说明内部函数可以直接调用外部函数的变量

接下来说一下装饰器是如何实现的,实现装饰器的方法有闭包、类。接下来咱们主要讲闭包是如何实现装饰器的

#闭包小案例
def ToSomeBody(name):
    #外部函数作用:创建内部函数,并未内部函数提供相应的运行环境
    pass
    def say(data):
        #内部函数
        print("对%s 说%s"%(name,data))
    return say


zhangsan = ToSomeBody('张三')
zhangsan('今晚吃鸡')

此时会得到结果:

对张三 说今晚吃鸡

正如上面的结论:内部函数可以调用外部函数的变量,而ToSomeBody(‘张三’)返回的结果是say函数,所以函数名+()就会执行函数返回结果。

def ToSomeBody(name):
    def say(data):
        print("对%s 说%s"%(name,data))
    return say


# zhangsan = ToSomeBody('张三')
# zhangsan('今晚吃鸡')
print(ToSomeBody('234'))
print(ToSomeBody('234')('56789'))

结果为:

<function ToSomeBody.<locals>.say at 0x0000029FF4DFAA60>
对234 说56789
None
此时可以得到什么结论呢?

正如上面的结论直接打印ToSomeBody(‘234’)返回的是say函数,直接打印一个函数会返回这个函数的内存地址,而ToSomeBody(‘234’)(‘56789’)在这个函数的基础上+()就会调用,那最后的None是为什么呢,因为say函数没有返回值,不像ToSomeBody函数有返回值say函数, say函数没有返回值只能返回一个None。

什么是装饰器

就是给已有函数增加额外功能的函数,它本质上就是一个闭包函数。

装饰器的功能特点:

  • 不修改已有函数的源代码
  • 不修改已有函数的调用方式
  • 给已有函数增加额外的功能

可以这样说:再不改变源函数的情况下增加新的功能

接下来看一下装饰器是如何编写的

def check(func): #装饰器函数
    def inner():
        print('请及时登录系统,在查询数据')
        func()
    return inner

@check
def select_user_info():  #被装饰的函数
    print('正在查询用户信息')


if __name__ == '__main__':
    select_user_info()

输出结果为

请及时登录系统,在查询数据
正在查询用户信息

此时我们可以看到,装饰器函数是check,被装饰的函数是select_user_info,在被装饰的函数头上加@装饰器函数的名称就可以了,这种写法叫做语法糖,语法糖的书写格式是: @装饰器名字

接下来看一下不用语法糖该如何书写

def check(func):
    def inner():
        print('请及时登录系统,在查询数据')
        func()
    return inner


def select_user_info():
    print('正在查询用户信息')

if __name__ == '__main__':
    select_user_info = check(select_user_info)
    select_user_info()

输出结果为

请及时登录系统,在查询数据
正在查询用户信息

此时可以得出结果:@check == select_user_info = check(select_user_info)

本次装饰器的讲解就到这里,装饰器进阶将放到下次内容

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值