Python全栈工程师

17.2-无参装饰器

2019-09-18  本文已影响0人  BeautifulSoulpy

我饿了,你分给我一半面包,这是朋友。你只吃了一口,剩下的面包全给了我 ,这是爱情。你一口没吃,直接把面包给了我 ,这是父母。 所以请珍惜友情、爱情、亲情,没有谁对谁是应该的。要学会感恩知足!懂得珍惜,才会拥有!


Python 是一种对新手很友好的语言。但是,它也有很多较难掌握的高级功能,比如装饰器(decorator)
如果前面基础知识掌握比较牢固的话,装饰器迎刃而解,没有什么特别难的地方,只需要几个简单的转化、等价,很容易理解装饰器;

在 Python 中,函数是一种非常灵活的结构,我们可以把它赋值给变量、当作参数传递给另一个函数,或者当成某个函数的输出。装饰器本质上也是一种函数,它可以让其它函数在不经过修改的情况下增加一些功能。

Python之装饰器
本章总结:

  1. 硬编码:死死的写到函数中的,
  2. 函数传的参数是否符合上面函数定义的要求,那是在调用时候后的问题
  3. def logger(fn, *args, *kwargs): # 形参定义 与 ret = fn(args, **kwargs) # 参数解构 区别 ;参数-正不正确由核心代码判断;
  4. add = logger(add) add赋值重新定义,记录的是inner函数对象,inner传4,5;调用fn() 实质是记录原来的add(4,5)函数;fn用到了外部变量fn,相当于闭包的特性(记录add的引用,尽管add被重新定义);

装饰器(decorator)

动态附加功能的解决方案:
示例1:

业务核心的代码功能+\-
def add(x,y): #  z = f(x,y)
    return x+y
def sub(x,y):
    return x-y
def a(x,y,z):
    pass

def b(m,n,*args,x,y,**kwargs):
    pass

只关注 附加功能——print  的函数定义;记录函数参数,并不关注函数是否能运行;
def logger(fn,x,y):   #位置参数和关键字参数分开;
    print("call function {}. x={}, y={}".format(fn.__name__, x, y))
    ret = fn(x,y)
    return ret
def logger(fn, *args, **kwargs):    # 形参定义
    print("call function {}. x={}, y={}".format(fn.__name__, *args, **kwargs))
    ret = fn(*args, **kwargs)    #  参数解构
    return ret

print('result = {}'.format(logger(add,4,5)))  #add(4,5)
print('result = {}'.format(logger(b,4,5,6,7,x=10,y=13))) # b(4,5,6,7,x=10,y=13)

def add(x,y): #  z = f(x,y)
    return x+y

示例2:柯里化之后,变成了2层函数;
# def logger(fn,x,y):   #位置参数和关键字参数分开;
#     print("call function {}. x={}, y={}".format(fn.__name__, x, y))
#     ret = fn(x,y)
#    return ret

def logger(fn):
    def inner(*args,**kwargs):
        print("call function {}. x={}, y={}".format(fn.__name__, *args, **kwargs))
        ret = fn(*args, **kwargs)
        return ret
    return inner

logger(add,4,5)
logger(add)(4,5)
fn = logger(add)
ret = add(4, 5)
print(ret)

# add赋值重新定义,记录的是inner函数对象,inner传4,5;调用fn() 实质是记录原来的add(4,5)函数;fn用到了外部变量fn,相当于闭包的特性;(记录add的引用,尽管add被重新定义);

add = logger(add)   #inner 原来的add消失了吗?
ret = add(4,5)  
----------------------------------------
call function add. x=4, y=5
9


最终形态——装饰器:
def logger(fn):
    def inner(*args,**kwargs):
        print("call function {}. x={}, y={}".format(fn.__name__, *args, **kwargs))
        ret = fn(*args, **kwargs)    # 解构,闭包(内外层函数的变量;)
        return ret
    return inner

@logger    # 等价为  add = logger(add)  =》 add=inner
#@logger    # 注释后相当于一个附加功能消失;
def add(x,y): #  z = f(x,y)
    return x+y

ret = add(4, 5)     #   开始调用;ret=inner(4,5)    
print(ret)
--------------------------------------------------
call function add. x=4, y=5

装饰器总结:
1. @logger 新语法的能力:就是将下面的标识符add作为参数传进来;

logger 包装 add ;
def logger(fn):
    def wrapper(*args,**kwargs):
        print("call function {}. x={}, y={}".format(fn.__name__, *args, **kwargs))
        ret = fn(*args, **kwargs)    # 解构,闭包(内外层函数的变量;)
        return ret
    return wrapper

@logger    # 等价为  add = logger(add)
def add(x,y): #  z = f(x,y)
    return x+y

ret = add(4, 5)     #   inner(4,5)
print(ret)
--------------------------------------------------------------------------------
call function add. x=4, y=5
9

有关装饰器的4个函数核心概念

1. 在Python语言中,函数也是对象,因此可以用一个变量指向函数。示例如下:

def func(param):
    print('param is : {}'.format(param))

variable = func
variable('函数赋予变量')

# console
param is : 函数赋予变量

2. 函数可作为入参传递给另一个函数。示例如下:

def func(param):
    print('param is : {}'.format(param))

def call(function, param):
    function(param)

call(func, '函数作为入参')

#console
param is : 函数作为入参

3. 函数可以嵌套。示例如下:

def func(param):
    def inner_func(param):
        print('param is : {}'.format(param))
    return inner_func(param)

print(func('函数嵌套'))

# console
param is : 函数嵌套
None

当里面的函数没有return时,运行结果为None。代码如下:

def func(param):
    def inner_func(param):
        print('param is : {}'.format(param))

print(func('函数嵌套'))

# console
None

4. 函数的返回值可以是函数对象。不是内层函数对象的最终返回结果;

def func():
    def inner_func(param):
        print('param is : {}'.format(param))
    return inner_func

res = func()
res('返回函数对象')
print(func())

# console
param is : 返回函数对象
<function func.<locals>.inner_func at 0x10404dcb0>
上一篇 下一篇

猜你喜欢

热点阅读