9.8. functools-可调用对象的高阶函数和操作

2.5 版的新Function。

源代码: Lib/functools.py


functools模块用于高阶函数:作用于或返回其他函数的函数。通常,就此模块而言,任何可调用对象都可以视为函数。

functools模块定义以下Function:

比较函数是可以接受两个参数,对其进行比较并返回小于(小于)的负数,等于(等于)的零或大于(大于)的正数的任何可调用函数。键函数是一个可调用函数,它接受一个参数并返回另一个值用作排序键。

Example:

sorted(iterable, key=cmp_to_key(locale.strcoll))  # locale-aware sort order

有关排序示例和简短的排序教程,请参见排序方式

2.7 版的新Function。

  • functools. total_ordering(* cls *)
    • 给定一个类定义一个或多个丰富的比较排序方法,该类装饰器提供其余的内容。这简化了指定所有可能的丰富比较操作的工作:

该类必须定义lt()le()gt()ge()之一。另外,该类应提供eq()方法。

For example:

@total_ordering
class Student:
    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()))

2.7 版的新Function。

  • functools. reduce(* function iterable * [,* initializer *])
    • 该Function与reduce()相同。它在此模块中可用,以允许编写与 Python 3 更向前兼容的代码。

2.6 版的新Function。

  • functools. partial(* func [,* args] [,**关键词] *)
    • 返回一个新的partial object,该partial object在被调用时的行为类似于* func ,并带有位置参数 args 和关键字参数 keywords 。如果有更多参数提供给调用,则将它们附加到 args 。如果提供了其他关键字参数,它们将扩展并覆盖 keywords *。大致相当于:
def partial(func, *args, **keywords):
    def newfunc(*fargs, **fkeywords):
        newkeywords = keywords.copy()
        newkeywords.update(fkeywords)
        return func(*(args + fargs), **newkeywords)
    newfunc.func = func
    newfunc.args = args
    newfunc.keywords = keywords
    return newfunc

partial()用于部分函数应用程序,该应用程序“冻结”函数的参数和/或关键字的某些部分,从而生成具有简化签名的新对象。例如,partial()可用于创建行为类似于int()函数的可调用对象,其中* base *参数默认为两个:

>>> from functools import partial
>>> basetwo = partial(int, base=2)
>>> basetwo.__doc__ = 'Convert base 2 string to an int.'
>>> basetwo('10010')
18
  • functools. update_wrapper(*包装器,已包装[,已分配] [,已更新] *)
    • 更新* wrapper 函数,使其看起来像 wrapped 函数。可选参数是 Tuples,用于指定将原始函数的哪些属性直接分配给包装函数上的匹配属性,以及使用原始函数中的相应属性更新包装函数的哪些属性。这些参数的默认值是模块级常量 WRAPPER_ASSIGNMENTS (分配给包装函数的 __ name __ __ module __ __ doc __ ,文档字符串)和 WRAPPER_UPDATES (更新包装函数的 __ dict __ * ,即实例字典)。

此函数的主要用途是在decorator函数中,该函数包装装饰后的函数并返回包装器。如果包装器函数未更新,则返回的函数的元数据将反映包装器定义,而不是原始函数定义,这通常会有所帮助。

  • functools. wraps(*包裹[,分配] [,更新] *)
    • 这是一个便捷函数,用于在定义包装函数时调用update_wrapper()作为函数装饰器。它等效于partial(update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated)。例如:
>>> from functools import wraps
>>> 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()
Calling decorated function
Called example function
>>> example.__name__
'example'
>>> example.__doc__
'Docstring'

如果不使用此装饰器工厂,则示例函数的名称将为'wrapper',而原始example()的文档字符串将丢失。

9.8.1. 部分对象

partial对象是partial()创建的可调用对象。它们具有三个只读属性:

  • partial. func

    • 可调用的对象或函数。带有新参数和关键字的对partial对象的调用将被转发到func
  • partial. args

    • 最左侧的位置参数将放在提供给partial对象调用的位置参数之前。
  • partial. keywords

    • 调用partial对象时将提供的关键字参数。

partial对象类似于function对象,因为它们是可调用的,弱引用的,并且可以具有属性。有一些重要的区别。例如,不会自动创建name__doc__属性。同样,在类中定义的partial对象的行为类似于静态方法,并且在实例属性查找期间不会转换为绑定方法。