美文网首页
functools-高阶函数和可调用对象上的操作

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

作者: 蝉时雨丶 | 来源:发表于2020-07-04 16:03 被阅读0次

functools 模块应用于高阶函数,即参数或(和)返回值为其他函数的函数。 通常来说,此模块的功能适用于所有可调用对象。

functools 模块定义了以下函数:

@functools.cached_property(func)

将一个类方法转换为特征属性,一次性计算该特征属性的值,然后将其缓存为实例生命周期内的普通属性。 类似于 property() 但增加了缓存功能。 对于在其他情况下实际不可变的高计算资源消耗的实例特征属性来说该函数非常有用。

示例:

class DataSet:
    def __init__(self, sequence_of_numbers):
        self._data = sequence_of_numbers

    @cached_property
    def stdev(self):
        return statistics.stdev(self._data)

    @cached_property
    def variance(self):
        return statistics.variance(self._data)

注解

此装饰器要求每个实例上的 dict 属性是可变的映射。 这意味着它将不适用于某些类型,例如元类(因为类型实例上的 dict 属性是类命名空间的只读代理),以及那些指定了 slots 但未包含 dict 作为所定义的空位之一的类(因为这样的类根本没有提供 dict 属性)。

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

一个为函数提供缓存功能的装饰器,缓存 maxsize 组传入参数,在下次以相同参数调用时直接返回上一次的结果。用以节约高开销或I/O函数的调用时间。

由于使用了字典存储缓存,所以该函数的固定参数和关键字参数必须是可哈希的。

不同模式的参数可能被视为不同从而产生多个缓存项,例如, f(a=1, b=2) 和 f(b=2, a=1) 因其参数顺序不同,可能会被缓存两次。

如果指定了 user_function,它必须是一个可调用对象。 这允许 lru_cache 装饰器被直接应用于一个用户自定义函数,让 maxsize 保持其默认值 128:

@lru_cache
def count_vowels(sentence):
    sentence = sentence.casefold()
    return sum(sentence.count(vowel) for vowel in 'aeiou')

如果 maxsize 设为 None,LRU 特性将被禁用且缓存可无限增长。

如果 typed 设置为true,不同类型的函数参数将被分别缓存。例如, f(3)f(3.0) 将被视为不同而分别缓存。

为了衡量缓存的有效性以便调整 maxsize 形参,被装饰的函数带有一个 cache_info() 函数。当调用 cache_info() 函数时,返回一个具名元组,包含命中次数 hits,未命中次数 misses ,最大缓存数量 maxsize 和 当前缓存大小 currsize。在多线程环境中,命中数与未命中数是不完全准确的。

该装饰器也提供了一个用于清理/使缓存失效的函数 cache_clear()

原始的未经装饰的函数可以通过 __wrapped__ 属性访问。它可以用于检查、绕过缓存,或使用不同的缓存再次装饰原始函数。

“最久未使用算法”(LRU)缓存 在“最近的调用是即将到来的调用的最佳预测因子”时性能最好(比如,新闻服务器上最受欢迎的文章倾向于每天更改)。 “缓存大小限制”参数保证缓存不会在长时间运行的进程比如说网站服务器上无限制的增加自身的大小。

一般来说,LRU缓存只在当你想要重用之前计算的结果时使用。因此,用它缓存具有副作用的函数、需要在每次调用时创建不同、易变的对象的函数或者诸如time()或random()之类的不纯函数是没有意义的。

静态 Web 内容的 LRU 缓存示例:

@lru_cache(maxsize=32)
def get_pep(num):
    'Retrieve text of a Python Enhancement Proposal'
    resource = 'http://www.python.org/dev/peps/pep-%04d/' % num
    try:
        with urllib.request.urlopen(resource) as s:
            return s.read()
    except urllib.error.HTTPError:
        return 'Not Found'

>>> for n in 8, 290, 308, 320, 8, 218, 320, 279, 289, 320, 9991:
...     pep = get_pep(n)
...     print(n, len(pep))

>>> get_pep.cache_info()
CacheInfo(hits=3, misses=8, maxsize=32, currsize=8)

以下是使用缓存通过 动态规划 计算 斐波那契数列 的例子。

@lru_cache(maxsize=None)
def fib(n):
    if n < 2:
        return n
    return fib(n-1) + fib(n-2)

>>> [fib(n) for n in range(16)]
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]

>>> fib.cache_info()
CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)

@functools.total_ordering

给定一个声明一个或多个全比较排序方法的类,这个类装饰器实现剩余的方法。这减轻了指定所有可能的全比较操作的工作。

此类必须包含以下方法之一:__lt__()__le__()__gt__()__ge__()。另外,此类必须支持 __eq__() 方法。

例如

@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-高阶函数和可调用对象上的操作

    functools 模块应用于高阶函数,即参数或(和)返回值为其他函数的函数。 通常来说,此模块的功能适用于所有可...

  • 14.8 调用操作符和函数对象--C++ Primer Rea

    14.8 调用操作符和函数对象 定义了调用操作符(Call Operator)类的对象成为函数对象。 14.8....

  • #3 高阶操作符

    1.高阶操作符 高阶操作符和高阶函数或高阶组件的定义是一样的,高阶操作符表示一个可观察对象返回另一个可观察对象 定...

  • 第五章

    高阶函数 map,filter,reduce匿名函数 lambdaany/all可调用对象,创建call方法内省...

  • 高阶函数

    高阶函数: 变量可以指向函数 abs(-10):这是函数调用 abs这是函数本身,也是对象 >>>abs f这是变...

  • 五,Kotlin标准库里面常用的高阶函数

    标准库里面常用的高阶函数的定义和用法 T.apply()函数 调用某对象的apply函数,在函数范围内,可以通过t...

  • 四、函数进阶

    一. 高阶函数 参数类型包含函数类型或返回值类型为函数类型的函数为高阶函数。 常见的高阶函数 高阶函数的调用 二....

  • Kotlin学习之高阶函数和Lambda表达式的基础用法

    Kotlin学习之高阶函数和Lambda表达式的基础用法 一、定义和调用高阶函数的写法 kotlin.collec...

  • kotlin inline、noline、crossinline

    使用高阶函数时,每个函数都是一个对象,函数调用时还有入栈出栈的开销。 以lock函数为例 调用处 反编译成JAVA...

  • php对象方法链式调用

    对象方法链式操作 魔法函数 __call(args)对象调用不存在的方法的时候,会自动调用 调用函数的方法 cal...

网友评论

      本文标题:functools-高阶函数和可调用对象上的操作

      本文链接:https://www.haomeiwen.com/subject/vomuqktx.html