Python库functools示例详解

目录
  • 1. cached_property
  • 2. cmp_to_key
  • 3. lru_cache
  • 4. partial
  • 5. partialmethod
  • 6. reduce
  • 7. singledispatch
  • 8. singledispatchmethod
  • 9. total_ordering
  • 10. update_wrapper
  • 11. wraps
  • 参考文献

functools模块是Python的标准库的一部分,它是为高阶函数而实现的。高阶函数是作用于或返回另一个函数或多个函数的函数。一般来说,对这个模块而言,任何可调用的对象都可以作为一个函数来处理。

functools 提供了 11个函数:

1. cached_property

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

# cached_property 缓存属性
class cached_property(object):
    """
    Decorator that converts a method with a single self argument into a
    property cached on the instance.
    Optional ``name`` argument allows you to make cached properties of other
    methods. (e.g.  url = cached_property(get_absolute_url, name='url') )
    """
    def __init__(self, func, name=None):
        # print(f'f: {id(func)}')
        self.func = func
        self.__doc__ = getattr(func, '__doc__')
        self.name = name or func.__name__

    def __get__(self, instance, type=None):
        # print(f'self func: {id(self.func)}')
        # print(f'instance: {id(instance)}')
        if instance is None:
            return self
        res = instance.__dict__[self.name] = self.func(instance)
        return res
class F00():
    @cached_property
    def test(self):
        # cached_property 将会把每个实例的属性存储到实例的__dict__中, 实例获取属性时, 将会优先从__dict__中获取,则不会再次调用方法内部的过程
        print(f'运行test方法内部过程')
        return 3
    @property
    def t(self):
        print('运行t方法内部过程')
        return 44
f = F00()
print(f.test)  # 第一次将会调用test方法内部过程
print(f.test)  # 再次调用将直接从实例中的__dict__中直接获取,不会再次调用方法内部过程
print(f.t)     # 调用方法内部过程取值
print(f.t)     # 调用方法内部过程取值

# 结果输出
# 运行test方法内部过程
# 3
# 3
# 运行t方法内部过程
# 44
# 运行t方法内部过程
# 44

2. cmp_to_key

在 list.sort 和 内建函数 sorted 中都有一个 key 参数

x = ['hello','worl','ni']
x.sort(key=len)
print(x)
# ['ni', 'worl', 'hello']

3. lru_cache

允许我们将一个函数的返回值快速地缓存或取消缓存。
该装饰器用于缓存函数的调用结果,对于需要多次调用的函数,而且每次调用参数都相同,则可以用该装饰器缓存调用结果,从而加快程序运行。
该装饰器会将不同的调用结果缓存在内存中,因此需要注意内存占用问题。

from functools import lru_cache
@lru_cache(maxsize=30)  # maxsize参数告诉lru_cache缓存最近多少个返回值
def fib(n):
    if n < 2:
        return n
    return fib(n-1) + fib(n-2)
print([fib(n) for n in range(10)])
fib.cache_clear()   # 清空缓存

4. partial

用于创建一个偏函数,将默认参数包装一个可调用对象,返回结果也是可调用对象。
偏函数可以固定住原函数的部分参数,从而在调用时更简单。

from functools import partial

int2 = partial(int, base=8)
print(int2('123'))
# 83

5. partialmethod

对于python 偏函数partial理解运用起来比较简单,就是对原函数某些参数设置默认值,生成一个新函数。而如果对于类方法,因为第一个参数是 self,使用 partial 就会报错了。

class functools.partialmethod(func, /, *args, **keywords) 返回一个新的 partialmethod 描述器,其行为类似 partial 但它被设计用作方法定义而非直接用作可调用对象。

func 必须是一个 descriptor 或可调用对象(同属两者的对象例如普通函数会被当作描述器来处理)。

当 func 是一个描述器(例如普通 Python 函数, classmethod(), staticmethod(), abstractmethod() 或其他 partialmethod 的实例)时, 对 __get__ 的调用会被委托给底层的描述器,并会返回一个适当的 部分对象 作为结果。

当 func 是一个非描述器类可调用对象时,则会动态创建一个适当的绑定方法。 当用作方法时其行为类似普通 Python 函数:将会插入 self 参数作为第一个位置参数,其位置甚至会处于提供给 partialmethod 构造器的 args 和 keywords 之前。

from functools import partialmethod

class Cell:
    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)

    print(type(partialmethod(set_state, False)))
    # <class 'functools.partialmethod'>

c = Cell()
c.alive
# False

c.set_alive()
c.alive
# True

6. reduce

函数的作用是将一个序列归纳为一个输出reduce(function, sequence, startValue)

from functools import reduce

l = range(1,50)
print(reduce(lambda x,y:x+y, l))
# 1225

7. singledispatch

单分发器,用于实现泛型函数。根据单一参数的类型来判断调用哪个函数。

from functools import singledispatch
@singledispatch
def fun(text):
	print('String:' + text)

@fun.register(int)
def _(text):
	print(text)

@fun.register(list)
def _(text):
	for k, v in enumerate(text):
		print(k, v)

@fun.register(float)
@fun.register(tuple)
def _(text):
	print('float, tuple')
fun('i am is hubo')
fun(123)
fun(['a','b','c'])
fun(1.23)
print(fun.registry)	# 所有的泛型函数
print(fun.registry[int])	# 获取int的泛型函数
# String:i am is hubo
# 123
# 0 a
# 1 b
# 2 c
# float, tuple
# {<class 'object'>: <function fun at 0x106d10f28>, <class 'int'>: <function _ at 0x106f0b9d8>, <class 'list'>: <function _ at 0x106f0ba60>, <class 'tuple'>: <function _ at 0x106f0bb70>, <class 'float'>: <function _ at 0x106f0bb70>}
# <function _ at 0x106f0b9d8>

8. singledispatchmethod

与泛型函数类似,可以编写一个使用不同类型的参数调用的泛型方法声明,根据传递给通用方法的参数的类型,编译器会适当地处理每个方法调用。

class Negator:
    @singledispatchmethod
    def neg(self, arg):
        raise NotImplementedError("Cannot negate a")

    @neg.register
    def _(self, arg: int):
        return -arg

    @neg.register
    def _(self, arg: bool):
        return not arg

9. total_ordering

它是针对某个类如果定义了ltlegtge这些方法中的至少一个,使用该装饰器,则会自动的把其他几个比较函数也实现在该类中

from functools import total_ordering

class Person:
    # 定义相等的比较函数
    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()))

p1 = Person()
p2 = Person()

p1.lastname = "123"
p1.firstname = "000"

p2.lastname = "1231"
p2.firstname = "000"

print p1 < p2  # True
print p1 <= p2  # True
print p1 == p2  # False
print p1 > p2  # False
print p1 >= p2  # False

10. update_wrapper

使用 partial 包装的函数是没有__name____doc__属性的。
update_wrapper 作用:将被包装函数的__name__等属性,拷贝到新的函数中去。

from functools import update_wrapper
def wrap2(func):
	def inner(*args):
		return func(*args)
	return update_wrapper(inner, func)

@wrap2
def demo():
	print('hello world')

print(demo.__name__)
# demo

11. wraps

warps 函数是为了在装饰器拷贝被装饰函数的__name__
就是在update_wrapper上进行一个包装

from functools import wraps
def wrap1(func):
	@wraps(func)	# 去掉就会返回inner
	def inner(*args):
		print(func.__name__)
		return func(*args)
	return inner

@wrap1
def demo():
	print('hello world')

print(demo.__name__)
# demo

参考文献

Python-functools详解

Python的functools模块

Python的Functools模块简介_函数

cached_property/缓存属性

盖若 gairuo.com

到此这篇关于Python库functools详解的文章就介绍到这了,更多相关Python库functools内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Python 3.8中实现functools.cached_property功能

    前言 缓存属性( cached_property )是一个非常常用的功能,很多知名Python项目都自己实现过它.我举几个例子: bottle.cached_property Bottle是我最早接触的Web框架,也是我第一次阅读的开源项目源码.最早知道 cached_property 就是通过这个项目,如果你是一个Web开发,我不建议你用这个框架,但是源码量少,值得一读~ werkzeug.utils.cached_property Werkzeug是Flask的依赖,是应用 cached_p

  • 浅谈python标准库--functools.partial

    一.简单介绍: functools模块用于高阶函数:作用于或返回其他函数的函数.一般而言,任何可调用对象都可以作为本模块用途的函数来处理. functools.partial返回的是一个可调用的partial对象,使用方法是partial(func,*args,**kw),func是必须要传入的,而且至少需要一个args或是kw参数. 创建一个功能函数,实现三个数的相加,如果其中的一个或是多个参数不变,那么可以使用partial,实例化一个传入了add和12参数的对象,如上图所示,传入两个参数后

  • Python中functools模块的常用函数解析

    1.partial 首先是partial函数,它可以重新绑定函数的可选参数,生成一个callable的partial对象: >>> int('10') # 实际上等同于int('10', base=10)和int('10', 10) 10 >>> int('10', 2) # 实际上是int('10', base=2)的缩写 2 >>> from functools import partial >>> int2 = partial(

  • Python的functools模块使用及说明

    目录 partial update_wrapper wraps reduce cmp_to_key lru_cache singledispatch partial 用于创建一个偏函数,将默认参数包装一个可调用对象,返回结果也是可调用对象. 偏函数可以固定住原函数的部分参数,从而在调用时更简单. from functools import partial int2 = partial(int, base=8) print(int2('123')) # 83 update_wrapper 使用 p

  • Python functools模块学习总结

    文档 地址 functools.partial 作用: functools.partial 通过包装手法,允许我们 "重新定义" 函数签名 用一些默认参数包装一个可调用对象,返回结果是可调用对象,并且可以像原始对象一样对待 冻结部分函数位置函数或关键字参数,简化函数,更少更灵活的函数参数调用 复制代码 代码如下: #args/keywords 调用partial时参数 def partial(func, *args, **keywords):     def newfunc(*farg

  • python高阶函数functools模块的具体使用

    目录 functools模块 reduce partial/partialmethod wraps/update_wrapper singledispatch/singledispatchmethod cmp_to_key total_ordering functools模块提供了一些常用的高阶函数(处理其他可调用对象/函数的特殊函数:以函数作为输入参数,返回也是函数). functools模块 functools模块中的高阶函数可基于已有函数定义新的函数: cmp_to_key, total_

  • Python使用functools实现注解同步方法

    在 Python 中没有类似 Java 中使用的 synchronized 关键字来同步方法,因此在 Python 中要实现同步方法,通常我们是使用 threading.Lock() 来实现.在进入函数的地方获取锁,出函数的时候释放锁,这样实现代码看起好非常不好看.另外网上也有人给出了其它几种实现方式,但看起来都不美气. 今天我在做项目的时候突然想到是不是可以通过 functools 来实现通过注解来标注方法为同步方法. 首先要求自己的类中有一个锁对象并且在类初始化的时候初始化这个锁对象,比如:

  • Python中functools模块函数解析

    Python自带的 functools 模块提供了一些常用的高阶函数,也就是用于处理其它函数的特殊函数.换言之,就是能使用该模块对可调用对象进行处理. functools模块函数概览 functools.cmp_to_key(func) functools.total_ordering(cls) functools.reduce(function, iterable[, initializer]) functools.partial(func[, args][, *keywords]) func

  • python可视化大屏库big_screen示例详解

    目录 big_screen 特点 安装环境 输入数据 本地运行 在线部署 对于从事数据领域的小伙伴来说,当需要阐述自己观点.展示项目成果时,我们需要在最短时间内让别人知道你的想法.我相信单调乏味的语言很难让别人快速理解.最直接有效的方式就是将数据如上图所示这样,进行可视化展现. 具体如下: big_screen 特点 便利性工具, 结构简单, 你只需传数据就可以实现数据大屏展示. 安装环境 pip install -i https://pypi.tuna.tsinghua.edu.cn/simp

  • python进阶collections标准库使用示例详解

    目录 前言 namedtuple namedtuple的由来 namedtuple的格式 namedtuple声明以及实例化 namedtuple的方法和属性 OrderedDict popitem(last=True) move_to_end(key, last=True) 支持reversed 相等测试敏感 defaultdict 小例子1 小例子2 小例子3 Counter对象 创建方式 elements() most_common([n]) 应用场景 deque([iterable[,

  • C语言编程gcc如何生成静态库.a和动态库.so示例详解

    目录 一.什么是静态库和动态库 二.gcc生成.a静态库和.so动态库 1.生成静态库(.a) 1.1编辑生成例子程序hello.h.hello.c和main.c 1.2将hello.c编译成.o文件 1.3由.o文件创建静态库 1.4在程序中使用静态库 1.5验证静态库的特点 2.生成动态库(.so) 2.1由.o文件创建动态库文件 2.2在程序中使用动态库 三.实例 1.实例1 1.1代码 1.2 静态库.a文件的生成与使用 1.3 动态库.so文件的生成与使用 2.实例2 2.1代码 2.

  • python库h5py入门详解

    目录 h5py简单介绍 1.创建一个h5py文件 2.创建dataset数据集 3.创建group组 本文只是简单的对h5py库的基本创建文件,数据集和读取数据的方式进行介绍,作者刚接触h5py,完全靠看文档自学,如果哪里说的不对,欢迎纠正!如果读者需要进一步详细的学习h5py的更多知识,请参考h5py的官方文档. h5py简单介绍 h5py文件是存放两类对象的容器,数据集(dataset)和组(group),dataset类似数组类的数据集合,和numpy的数组差不多.group是像文件夹一样

  • 熵值法原理及Python实现的示例详解

    目录 1.简单理解 信息熵 2.编制指标 (学术情景应用) 3.python实现 3.1 数据准备 3.2 数据预处理 3.3 熵值.权重计算 3.4 编制综合评价指标 熵值法也称熵权法,是学术研究,及实际应用中的一种常用且有效的编制指标的方法. 1.简单理解 信息熵 机器学习中的决策树算法是对信息熵的一种典型的应用. 在信息论中,使用 熵 (Entropy)来描述随机变量分布的不确定性. 假设对随机变量X,其可能的取值有x1,x2,...,xn .即有n种可能发生的结果.其对应发生的概率依次为

  • Python selenium find_element()示例详解

    selenium有以下定位方式: driver.find_element_by_id('id') driver.find_element_by_xpath('xpath') driver.find_element_by_link_text('link_text') driver.find_element_by_partial_link_text('partial_link_text') driver.find_element_by_name('name') driver.find_element

  • python支付宝支付示例详解

    本文实例为大家分享了python支付宝支付示例代码,供大家参考,具体内容如下 项目演示: 1.输入金额 2.扫码支付: 3.支付完成: 一.注册账号 https://openhome.alipay.com/platform/appDaily.htm?tab=info 二.设置应用公钥 三.代码实现 1.项目结构: 2.把生成的     应用私钥     和    支付宝的公钥       放入keys目录下: 注意: 支付宝公钥 商户私钥 --- 配置商户应用私钥--copy到key目录下 --

  • 使用typescript+webpack构建一个js库的示例详解

    目录 入口文件 tsconfig配置 webpack配置文件 webpack入口文件配置 webpack为typescript和less文件配置各自的loader webpack的output配置 运行webpack进行打包 测试验证 输出esm模块 已经输出了umd格式的js了, 为什么还要输出esm模块? ----TreeShaking 用tsc输出esm和类型声明文件 package.json中添加exports配置声明模块导出路径 完善package.json文件 用api-extrac

  • Python ini配置文件示例详解

    目录 INI介绍 关于configparser INI文件格式 读取配置文件 写入配置文件 总结 INI介绍 INI是英文“初始化”(initialization)的缩写,被用来对操作系统或特定程序初始化或进行参数设置.由节(section). 键(key).值(value)构成.在windows系统中有很多INI文件,例如“System32.ini”和“Win.ini”,相信大家并不陌生.Python 中操作配置文件的模块为configparser,这个模块可以用来解析与Windows上INI

  • Golang官方限流器库实现限流示例详解

    目录 前言 例子 实现 小结 前言 在翻Golang官方库的过程中,发现一个有趣的库golang.org/x/time ,里面只有一个类rate,研究了一下发现它是一个限流器,实现了很多的功能,当然它的核心原理并不复杂,也就是令牌桶算法. 令牌桶算法的原理是:令牌桶会不断地把令牌添加到桶里,而请求会从桶中获取令牌,只有拥有令牌地请求才能被接受.因为桶中可以提前保留一些令牌,所以它允许一定地突发流量通过. 例子 下面是限流算法常见的写法,首先判断是否有令牌,如果有就通过,否则直接失败. packa

随机推荐