IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    [原]7.2 functools--高阶函数和可调用对象

    caimouse发表于 2016-02-28 08:57:57
    love 0

    本模块主要提供了高阶函数和可调用对象。

    functools.cmp_to_key(func) 

    转换旧类型的比较函数为一个键值函数。主要用来转换Python版本2的函数参数,比如在函数sorted(),miin(),max(),heapq.nlargest()。

    例子:

    #python 3.4

    from functools import *

     

    l = [2, 8, 1, 3]

    def num_cmp(x, y):

        return x - y

    r = sorted(l, key = cmp_to_key(num_cmp))

    print(r)

    结果输出如下:

    [1, 2, 3, 8]

     

    @functools.lru_cache(maxsize=128, typed=False)

    lru_cache函数是一个装饰器函数,它主要用来缓存最近调用的结果,这样提高函数调用效率,不用每次都重新计算。参数maxsize是缓存多少次,设置为None时表示不限制缓存的次数,但会占用比较多内存;参数typed是用来是否分不同类型来保存函数返回值,如果设置为True就进行区分,比如f(3)和f(3.0)就会区分不同地方保存;设置为False就不作这样的区分保存。由于使用一个字典保存缓存结果,所以有的位置参数和关键值参数都需要是可以hash保存的。

    例子:

    #python 3.4

    from functools import *

     

    @lru_cache(maxsize=None)

    def fib(n):

        if n < 2:

            return n

        return fib(n-1) + fib(n-2)

    r = [fib(n) for n in range(16)]

    print(r)

    print(fib.cache_info())

    结果输出如下:

    [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]

    CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)

     

    @functools.total_ordering 

    提供一个类拥有所比较方法的装饰器。比如你想写一个排序类时,需要写大于、等于、小于等等比较实现,如果每个都重载要写比较多的代码,而这个装饰器提供了一个方式,只要实现自己需要的比较函数即可,其它使用装饰里的默认实现。

    例子:

    @total_ordering

    class Student:

        def _is_valid_operand(self, other):

            return (hasattr(other, "lastname") and

                    hasattr(other, "firstname"))

        def __eq__(self, other):

            if not self._is_valid_operand(other):

                return NotImplemented

            return ((self.lastname.lower(), self.firstname.lower()) ==

                    (other.lastname.lower(), other.firstname.lower()))

        def __lt__(self, other):

            if not self._is_valid_operand(other):

                return NotImplemented

            return ((self.lastname.lower(), self.firstname.lower()) <

                    (other.lastname.lower(), other.firstname.lower()))

     

    functools.partial(func, *args, **keywords) 

    返回一个固定部分参数的函数对象。比如想调用一个函数有五个参数,但在使用过程中发现有三个参数是需要固定的,不改变的,就可以采用这个方法来绑定这几个参数,从而达到简化,不让后面的代码进行修改。

    例子:

    #python 3.4

    from functools import *

     

    def add(a, b):

        return a + b

    r = partial(add, 10)

    print(r)

    print(r(1)) #10 + 1

    print(r(2)) #10 + 2

    结果输出如下:

    functools.partial(<function add at 0x02D879C0>, 10)

    11

    12

     

    class functools.partialmethod(func, *args, **keywords)

    本函数与上面的函数的意义是一样的,只不过本函数只是针对类里的方法进行绑定参数。

    例子:

    #python 3.4

    from functools import *

     

    class Cell(object):

         def __init__(self):

             self._alive = False

         @property

         def alive(self):

             return self._alive

         def set_state(self, state):

             self._alive = bool(state)

         set_alive = partialmethod(set_state, True)

         set_dead = partialmethod(set_state, False)

     

    c = Cell()

    print(c.alive)

    c.set_alive()

    print(c.alive)

    结果输出如下:

    False

    True

     

    functools.reduce(function, iterable[, initializer]) 

    把一个两个参数的函数function应用到一个序列上进行迭代操作。比如reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])就会这样计算:((((1+2)+3)+4)+5)。它的实现等同于下面的代码:

    def reduce(function, iterable, initializer=None):

        it = iter(iterable)

        if initializer is None:

            value = next(it)

        else:

            value = initializer

        for element in it:

            value = function(value, element)

        return value

    例子:

    #python 3.4

    from functools import *

     

    def statistics(dic,k): 

      if not k in dic: 

        dic[k] = 1

      else: 

        dic[k] +=1

      return dic

    lst = [1, 2, 3, 4]

    print(reduce(statistics, lst, {}))

    结果输出如下:

    {1: 1, 2: 1, 3: 1, 4: 1}

     

    @functools.singledispatch(default) 

    本装饰器用来实现函数对多个类型进行重载。比如同样的函数名称,对不同类型有不同功能实现。

    例子:

    #python 3.4

    from functools import *

     

    @singledispatch

    def fun(arg, verbose = False):

      if verbose:

        print('singledispatch:', end = ' ')

      print(arg)

    @fun.register(list)

    def _(arg, verbose = False):

      if verbose:

        print('list:')

      for i, elem in enumerate(arg):

        print(i, elem)

     

    fun(100, verbose = True)

    fun([1, 2, 3], verbose = True)

    结果输出如下:

    singledispatch: 100

    list:

    0 1

    1 2

    2 3

     

    functools.update_wrapper(wrapper, wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES) 

    更新函数wapper像wrapped函数一样的,主要共用相同的描述字符串。

    例子:

    #python 3.4

    from functools import *

     

    def updateTest(fun):  

      def living(*args, **kw):  

        return fun(*args, **kw)  + ' best'

      return update_wrapper(living, fun)

    @updateTest  

    def Caimouse():  

      "blog.csdn.net/caimouse"  

      return 'Python'  

    print(Caimouse())

    print(Caimouse.__doc__)

    结果输出如下:

    Python best

    blog.csdn.net/caimouse

     

    @functools.wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES) 

    本函数是把上面的函数进行封装,提供的功能是一样的。

    例子:

    #python 3.4

    from functools import *

     

    def my_decorator(f):

         @wraps(f)

         def wrapper(*args, **kwds):

             print('Calling decorated function')

             return f(*args, **kwds)

         return wrapper

     

    @my_decorator

    def example():

         """Docstring"""

         print('Called example function')

     

    example()

    print(example.__doc__)

    结果输出如下:

    Calling decorated function

    Called example function

    Docstring

     

     蔡军生  QQ:9073204  深圳



沪ICP备19023445号-2号
友情链接