python3高阶函数库functools

###python2.7中functools库wrapper,reduce,partial,total_ordering,cmp_to_key

  • cmp_to_key见名知意把cmp比较函数转换成key比较函数,python3中不支持cmp;
  • total_ordering 这个装饰器是在python2.7的时候加上的,它是针对某个类如果定义了lt、le、gt、ge这些方法中的至少一个,使用该装饰器,则会自动的把其他几个比较函数也实现在该类中;
  • reduce 和之前的reduce函数意义相同;
  • partial局部部分的意思,可以固定函数的部分参数变成定制的函数,看到有些书上翻译成偏函数感觉非常晦涩;
  • wrapper 装饰器函数,把装饰器函数伪装成被装饰函数,实际调用的是update_wrapper,源码设置了name,doc,module,dict属性给装饰器函数;

python3.6.5中functools库新增了lru_cache和singledispatch

  • lru_cache缓存计算结果
  • singledispatch 有点类似c++中的泛型和多态
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    import time
    from operator import mul
    from functools import cmp_to_key, total_ordering, reduce, partial, wraps, lru_cache, singledispatch

    a = [5, 6, 1, 2, 3, 4]


    def my_cmp(x, y):
    if x < y:
    return -1
    if x > y:
    return 1
    return 0

    print(sorted(a, key=cmp_to_key(my_cmp)))


    @total_ordering #如果去掉 >= 不能使用
    class Student:
    def __init__(self, first, last):
    self.firstname = first
    self.lastname = last

    def __eq__(self, other):
    return ((self.lastname.lower(), self.firstname.lower()) ==
    (other.lastname.lower(), other.firstname.lower()))

    def __lt__(self, other):
    return ((self.lastname.lower(), self.firstname.lower()) <
    (other.lastname.lower(), other.firstname.lower()))

    c = Student('abc', 'kevin')
    b = Student('zuang', 'kevin')
    print(b >= c)


    three_mul = partial(mul, 3)
    print(three_mul(9))
    print(reduce(mul, a))


    def clock(func):
    @wraps(func)
    def clocked(*args, **kwargs):
    t0 = time.perf_counter()
    res = func(*args, **kwargs)
    t1 = time.perf_counter()
    print('func:{} args:{} cost:{}'.format(func, args, t1 - t0))
    return res
    return clocked


    @lru_cache()
    @clock
    def fib(n):
    if n < 3:
    return 1
    return fib(n - 1) + fib(n - 2)


    t0 = time.perf_counter()
    print(fib(30))
    t1 = time.perf_counter()
    print('total:{}'.format(t1 - t0))
    print(fib.__name__)
    print(fib.cache_info())


    Point = namedtuple('Point', ['x', 'y'])
    p = Point(1, 2)
    print(p)


    @singledispatch
    def typecheck():
    pass


    @typecheck.register(int)
    def _(text):
    print(type(text))
    print('---int---')


    @typecheck.register(str)
    def _(text):
    print(type(text))
    print('---str---')


    @typecheck.register(float)
    def _(text):
    print(type(text))
    print('---float---')


    typecheck('ring')