首页 > 代码库 > 【函数】04、装饰器

【函数】04、装饰器

一、高阶函数

  python中函数是一等对象(first class);函数也是对象,并且它可以像普通对象一样复制、作为参数、作为返回值。

  返回函数或者参数是函数的函数就是高阶函数,也被称为函数式编程

In [23]: def counter(base):
    ...:     def inc(x=1):
    ...:         nonlocal base
    ...:         base += x
    ...:         return base
    ...:     return inc          # 返回一个函数
    ...: 

In [24]: inc = counter(3)

In [25]: inc
Out[25]: <function __main__.counter.<locals>.inc>

In [26]: inc()
Out[26]: 4

In [27]: inc()
Out[27]: 5


内置函数sorted()的实现:

In [48]: def sort(it, cmp=lambda a, b: a<b):
    ...:     ret = []
    ...:     for x in it:
    ...:         for i, e in enumerate(ret):
    ...:             if cmp(x, e):
    ...:                 ret.insert(i, x)
    ...:                 break
    ...:         else:
    ...:             ret.append(x)
    ...:     return ret
    ...: 

In [49]: sort([1, 3, 5, 2, 4, ])
Out[49]: [1, 2, 3, 4, 5]

In [50]: sort([1, 3, 5, 2, 4, ], lambda a, b: a>b)
Out[50]: [5, 4, 3, 2, 1]


总结:

  函数作为返回值常用于闭包的场景:需要封装一些变量

  函数作为参数常用于大多数逻辑固定,少部分逻辑不固定的场景

  函数作为参数,返回值也为是函数:常用于作为参数的函数在执行前后需要一些额外的操作(增加功能)

In [77]: def add(x, y):
    ...:     return x + y
    ...: 

In [78]: add.__name__
Out[78]: ‘add‘


In [80]: def logger(fn):
    ...:     def wrap(*args, **kwargs):
    ...:         print(‘call {}‘.format(fn.__name__))
    ...:         ret = fn(*args, **kwargs)
    ...:         print(‘{} called‘.format(fn.__name__))
    ...:         return ret
    ...:     return wrap
    ...: 

In [81]: loged_add = logger(add)

In [82]: loged_add(3, 5)
call add
add called
Out[82]: 8

简单、优雅一点:

In [90]: def add(x, y):
    ...:     return x + y
    ...: 

In [91]: def logger(fn):
    ...:     def wrap(*args, **kwargs):
    ...:         print(‘call {}‘.format(fn.__name__))
    ...:         ret = fn(*args, **kwargs)
    ...:         print(‘{} called‘.format(fn.__name__))
    ...:         return ret
    ...:     return wrap
    ...: 

In [92]: add = logger(add)    # add变量名被重新赋值定义,赋值是先执行右边的部分

In [93]: add(3, 4)
call add
add called
Out[93]: 7

更简单、优雅:

In [102]: def logger(fn):
     ...:     def wrap(*args, **kwargs):
     ...:         print(‘call {}‘.format(fn.__name__))
     ...:         ret = fn(*args, **kwargs)
     ...:         print(‘{} called‘.format(fn.__name__))
     ...:         return ret
     ...:     return wrap
     ...: 

In [103]: @logger # @这是装饰器的语法糖,相当于 add=logger(add)=wrp
     ...: def add(x, y):
     ...:     return x + y
     ...: 

In [104]: add(1, 2)
call add
add called
Out[104]: 3

这是logger就是装饰器了


二、装饰器

1、装饰器

  函数的参数是一个函数,返回值也是一个函数,就可以作为装饰器




【函数】04、装饰器