第一类对象、闭包(装饰器)、语法糖

函数是第一类对象

所谓第一类对象:可以用标识符给对新命名,并且对象可被当做数据处理,

例如赋值、作为参数传递给函数,或者作为返回值return

因此,可用其他变量名引用这个函数对象

或将函数对象作为参数,传递给另一个函数:传参过程类似于一个赋值操作

def func(a,b):
    return a+b
add = func
print(func(1,2))
print(add(1,2))

def caller__func(f):
    return f(1,2)
if __name__ == '__main__':
    print(caller__func(func))

运行结果:3

         3

         3

说明:局部变量f引用func函数,f实际指向了函数func

执行 return f(1,2)相当于执行return func(1,2)

函数对象vs函数调用

无论是把函数赋值给新的标识符,还是作为参数传递给新的函数,针对的都是函数对象本身,而不是函数的调用

eg

def func():
    return 'hello world'

ref1 = func         #将函数对象赋值给ref1
ref2 = func()       #调用函数,将函数的返回值赋值给ref2

#判断两者类型
print(ref1)
print(ref2)

#可用callable函数验证某一变量或函数是否可调用
print(callable(ref1))
print(callable(ref2))

运行结果:<function func at 0x05535540>

hello world

True

False

闭包&LEGB法则

闭包,将组成函数的语句和对应的执行环境打包在一起得到的对象

闭包最重要的使用价值在于:封存函数执行的上下文环境;
闭包在其捕捉的执行环境(def语句块所在上下文)中,也遵循LEGB规则逐层查找,直至找到符合要求的变量,或者抛出异常。

对于嵌套函数,闭包将会捕捉内层函数执行所需的整个环境

闭包必需的三大条件:函数嵌套、内部函数引用外部变量、外部函数需返回内层函数

'闭包(函数嵌套):调用过程:将内部函数返回给外部函数'
def FunX(x):
    print('-----------开始-----------')
    def FunY(y):
        print(y)
        return x*y
    print('-------------结束--------------')
    def FunZ(z):
        print(z)
        return x*z
    return FunY,FunZ
y,z=FunX(3)
print(y(4))
print(z(5))

其中的FunY和FunZ就是所谓的闭包,而FunY内部所引用过的y(FunZ内部所引用过的z)就是所谓的闭包变量。

内函数里运用了外函数的临时变量x,并且外函数的返回值FunY,FunZ是内函数的引用。这样就构成了一个闭包。

一般情况下,局部变量在函数返回时,就会被垃圾回收器回收,而不能再被使用。但闭包是一种特殊情况,当外函数的的变量在内函数使用时,即绑定给内部函数,延长生命周期

装饰器

封存上下文这一特性可被巧妙的用于现有函数的包装,从而为现有函数增加功能,即装饰器

装饰器就是闭包,但装饰器传入的参数是函数

因为python是一门胶水语言,在python一切皆是对象,python中全部都是引用类型

因此函数可以像变量一样被指向和传递。

原则:
1
、不能修改被装饰函数的源代码。
2、不能修改被装饰函数的调用方式。
3、不能改变被装饰函数的执行结果。
装饰器对被装饰函数是透明的

def add(a,b):
    return a+b
def checkParams(fn):
    def wrapper(a,b):
        if isinstance(a,(int,float)) and isinstance(b,(int,float)):
            return fn(a,b)
        else:
            print('变量ab不能相加')
        return
    return wrapper
if __name__ == '__main__':
    wrapper=checkParams(add)
    result=wrapper(2,3)
    print(result)

语法糖

def doupi(fn):
    def jiadoupi():
        print('麻酱豆皮10')
        return fn()+10
    return jiadoupi
def xiangcai(fnn):
    def jiaxiangcai():
        print('麻酱香菜5')
        return fnn()+5
    return jiaxiangcai

#语法糖
@xiangcai
@doupi
def diguo():
    print('底锅:50')
    return 50

#aa=doupi(diguo)
#aa=doupi(xiangcai(diguo))
#print(aa())

x=diguo()
print(x)

猜你喜欢

转载自blog.csdn.net/Candriy/article/details/80652776