返回顶部
首页 > 资讯 > 后端开发 > Python >python模块之functools
  • 449
分享到

python模块之functools

模块pythonfunctools 2023-01-31 07:01:54 449人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

functools模块提供了某些高阶函数(high-order function)。 functools.cmp_to_key(func) 比较函数是接收两个参数进行比较的函数,返回一个负数表示<,返回0表示=,返回一个正数表示&g

functools模块提供了某些高阶函数(high-order function)。

functools.cmp_to_key(func)

比较函数是接收两个参数进行比较的函数,返回一个负数表示<,返回0表示=,返回一个正数表示>。key函数接收一个参数并返回另一个值作为进行排序的键。
将比较函数转换为key函数,常在用到key关键字的函数如sotred(), min(), heapq.nlargest(), itertools,groupby()中使用。cmp_to_key主要作为过渡工具python2中支持的比较函数进行转换。

def numeric_compare(x, y):
    return x - y

# Python2
print(sorted([5, 2, 4, 1, 3], cmp=numeric_compare))

# python3
print(sorted([5, 2, 4, 1, 3], key=cmp_to_key(numeric_compare)))

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

使用memoize包装函数,保存最近maxsize次的函数调用结果。在I/O-bound函数上装饰,处理相同参数时可以节省函数执行时间。

  • 如果maxsize为None,会禁用LRU缓存特性(并非禁用缓存)且缓存大小会无限增长。maxsize设置为2的n次方时性能最优。
  • 如果typed为True,不同类型函数参数的执行结果会被分别缓存,例如f(3)f(3.0)会被视为有两个不同结果的不同调用。

因为该装饰器使用字典缓存函数执行结果,所以函数的位置参数和关键字参数必须是可哈希的。

不同的参数模式可能会被视为不同的缓存实体。例如f(a=1, b=2)f(b=2, a=1)虽然只是关键字顺序不同但可能有两个单独的缓存实体。

被包装的函数可以调用cache_info(),它返回一个(hits, misses, maxsize, currsize)形式的命名元组;可以调用cache_clear()清空或使缓存无效;还可以调用__wrapped__属性绕过缓存,访问原始的底层函数。

LRU(least recently used)缓存通常应仅用在需要重用先前计算的值的场景,其他场景如使用LRU有不良影响、每次调用需要返回不同结果、time()、random()等应禁止使用。maxsize表示缓存大小限制,确保不会无限制增长。

@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)

@functools.total_ordering

类装饰器,包装在定义了一个或多个富比较排序方法的类上,会补足其他的比较方法。
该类必须定义__lt__(), __le__(), __gt__(), 或__ge__()中至少一个方法,并建议定义__eq__()方法。

@total_ordering
class Student:
    def __init__(self, lastname, firstname):
        self.lastname = lastname
        self.firstname = firstname

    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()))

NOTE:使用这个装饰器的代价是,装饰器自动补足的比较方法耗费了更多的执行时间并拥有更复杂的堆栈跟踪。如果应用性能基准测试表明是使用此装饰器造成的瓶颈,手动实现所有六种富比较方法可以带来直观的速度提升。

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

偏函数,返回一个partial对象,调用时等同调用了使用预设位置参数和关键字参数的func函数。如果partial对象调用时又提供了额外的位置参数,追加到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()用于"冻结"函数的部分位置参数和/或关键字参数而产生一个代表某部分函数功能的简化标志。

>>> from functools import partial
>>> basetwo = partial(int, base=2)
>>> basetwo.__doc__ = 'Convert base 2 string to an int.'
>>> basetwo('10010')
18

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

后续补充

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

将可迭代对象iterable中的元素从左到右累计到接收两个参数的函数func中。例如reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])的计算等同于((((1+2)+3)+4)+5)
如果设置了可选参数initializer,它被放置在要计算的序列之前,并在序列为空时作为默认值;如果未提供initializer的值且序列仅包含一个元素,返回该元素。

@functools.singledispatch

将函数转换为单分派泛函数(single-dispatch generic function)。

使用@singledispatch装饰器定义一个泛函数,单分派仅限于第一个参数的类型:

from functools import singledispatch

@singledispatch
def fun(arg, verbose=False):
    if verbose:
        print("Let me just say,", end=" ")
    print(arg)

使用泛函数的reGISter()属性添加重载实现,该属性是一个装饰器。对于使用类型注解的函数,该装饰器将自动推断第一个参数的类型:

@fun.register
def _(arg: int, verbose=False):
    if verbose:
        print("Strength in numbers, eh?", end=" ")
    print(arg)

@fun.register
def _(arg: list, verbose=False):
    if verbose:
        print("Enumerate this:")
    for i, elem in enumerate(arg):
        print(i, elem)

如果不使用类型注解,可以显式地给装饰器传递类型参数:

@fun.register(complex)
def _(arg, verbose=False):
    if verbose:
        print("Better than complicated.", end=" ")
    print(arg.real, arg.imag)

也可以以函数的形式使用register()注册lambda函数和已定义的函数:

def nothing(arg, verbose=False):
    print("Nothing.")

fun.register(type(None), nothing)

register()属性返回允许装饰器堆叠、序列化以及创建独立的单元测试的未装饰的函数:

from decimal import Decimal

@fun.register(float)
@fun.register(Decimal)
def fun_num(arg, verbose=False):
    if verbose:
        print("Half of your number:", end=" ")
    print(arg / 2)

>>> fun_num is fun
False

调用时,泛函数只分派第一个参数的类型:

>>> fun("Hello, world.")
Hello, world.
>>> fun("test.", verbose=True)
Let me just say, test.
>>> fun(42, verbose=True)
Strength in numbers, eh? 42
>>> fun(['spam', 'spam', 'eggs', 'spam'], verbose=True)
Enumerate this:
0 spam
1 spam
2 eggs
3 spam
>>> fun(None)
Nothing.
>>> fun(1.23)
0.615

如果某个类型没有相应的实现,将查找更通用的实现进行解析。使用@singledispatch装饰的原始函数注册为object类型,将在没有更好实现的情况下使用。调用dispatch()属性查看泛函数使用了哪个实现:

>>> fun.dispatch(float)
<function fun_num at 0x1035a2840>
>>> fun.dispatch(dict)    # note: default implementation
<function fun at 0x103fe0000>

调用registry属性查看注册的所有实现:

>>> fun.registry.keys()
dict_keys([<class 'NoneType'>, <class 'int'>, <class 'object'>, <class 'decimal.Decimal'>, <class 'list'>, <class 'float'>])
>>> fun.registry[float]
<function fun_num at 0x1035a2840>
>>> fun.registry[object]
<function fun at 0x103fe0000>

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

更新包装函数(wrapper),使其看起来更像被包装的原始函数(wrapped)。元组类型的可选参数assigned指定wrapped函数的哪些属性直接分派到wrapper函数对应的属性上,updated参数指定使用wrapped函数的哪些属性更新wrapper函数对应的属性。

WRAPPER_ASSIGNMENTS的默认值是'__module__', '__name__', '__qualname__', '__doc__','__annotations__'
WRAPPER_UPDATES的默认值是'__dict__'

通过访问包装函数的__wrapped__属性可以获取到被包装的原始函数。

该函数主要用于装饰器使用场景下,如果不更新包装函数,返回函数的元数据将指向包装函数而非被包装的原始函数,一般来说没太大意义。

def wrapper(f):
    def wrapper_function(*args, **kwargs):
        """this is a wrapper function"""
        return f(*args, **kwargs)
    # update_wrapper(wrapper_function, f)
    return wrapper_function

@wrapper
def wrapped():
    """this is a wrapped function"""
    pass

print(wrapped.__doc__)
print(wrapped.__name__)
# 不使用update_wrapper的结果:
>>> this is a wrapper function
>>> wrapper_function

# 使用update_wrapper的结果:
>>> this is a wrapped function
>>> wrapped

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

等同于partial(update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated),不过是作为包装函数定义时的装饰器使用。

def wrapper(f):
    @wraps(f)
    def wrapper_function(*args, **kwargs):
        """this is a wrapper function"""
        return f(*args, **kwargs)
    return wrapper_function

@wrapper
def wrapped():
    """this is a wrapped function"""
    pass

print(wrapped.__doc__)
print(wrapped.__name__)

partial对象

partial对象是由partial()方法创建的可调用对象,它有三个只读属性:
partial.func
一个可调用对象或函数。调用partial对象将使用新的位置参数和关键字参数转发到func。
partial.args
调用partial()时提供的位置参数
partial.keywords
调用partial()时提供的关键字参数

--结束END--

本文标题: python模块之functools

本文链接: https://lsjlt.com/news/192239.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • python模块之functools
    functools模块提供了某些高阶函数(high-order function)。 functools.cmp_to_key(func) 比较函数是接收两个参数进行比较的函数,返回一个负数表示<,返回0表示=,返回一个正数表示&g...
    99+
    2023-01-31
    模块 python functools
  • Python的functools模块
    (wrapperwrappedassigned = WRAPPER_ASSIGNMENTSupdated = WRAPPER_UPDATES):  类似咱们自己写的copy_preperties功能;  wrapper包装函数, wrapp...
    99+
    2023-01-31
    模块 Python functools
  • 5-functools模块
    functools 包含了用于创建装饰函数,启动面向切面的编程,超出面向对象编程范围的代码复用,同时提供了装饰函数用于丰富的快捷比较的API, partial 模块还创建了包含函数参数的函数引用,也就是偏函数 partial 偏函数 p...
    99+
    2023-01-31
    模块 functools
  • Python中functools模块函数解析
    Python自带的 functools 模块提供了一些常用的高阶函数,也就是用于处理其它函数的特殊函数。换言之,就是能使用该模块对可调用对象进行处理。 functools模块函数概览 functoo...
    99+
    2022-06-04
    函数 模块 Python
  • Python的functools模块使用总结
    本篇文章给大家带来了关于Python的相关知识,主要介绍了Python的functools模块使用及说明,具有很好的参考价值,下面一起来看一下,希望对大家有帮助。【相关推荐:Python3视频教程 】partial用于创建一个偏函数,将默认...
    99+
    2022-08-08
    python
  • Python的functools模块使用及说明
    目录partialupdate_wrapperwrapsreducecmp_to_keylru_cachesingledispatchpartial 用于创建一个偏函数,将...
    99+
    2024-04-02
  • Python中functools模块的常用函数解析
    1.partial 首先是partial函数,它可以重新绑定函数的可选参数,生成一个callable的partial对象: >>> int('10') # 实际上等同于int('10'...
    99+
    2022-06-04
    函数 模块 常用
  • python高阶函数functools模块如何使用
    本篇内容主要讲解“python高阶函数functools模块如何使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“python高阶函数functools模块如何使用”吧!functools模块提...
    99+
    2023-07-05
  • Python使用functools模块中的partial函数生成偏函数
    python 中提供一种用于对函数固定属性的函数(与数学上的偏函数不一样) # 通常会返回10进制 int('12345') # print 12345 # 使用参数 返回 8进制 int('11...
    99+
    2022-06-04
    函数 模块 Python
  • Python时间模块之datetime模块
    目录 简介 函数介绍及运用 date:日期类 1.获取当前时间  2.日期对象的属性 3.date类中时间和时间戳的转换: 4.修改日期使用replace方法  time:时间类  time类操作 datetime:日期时间类 timede...
    99+
    2023-09-12
    python datetime python 日期时间
  • Python模块学习之IPy模块
    IP地址规划是网络设计中非常重要的一个环节,规划的好坏会直接影响路由协议算法的效率,包括网络性能、可扩展性等方面,在这个过程当中,免不了要计算大量的IP地址,包括网段、网络掩码、广播地址、子网数、IP类型等。Python提供了一个强大的第...
    99+
    2023-01-31
    模块 Python IPy
  • python之MySQLdb模块
    防伪码:忘情公子著  MySQLdb是用来通过python控制mysql数据库的一个模块。  在说这个模块之前,我们先来想一下在命令行模式下操作mysql数据库的步骤,一般来说分为三步:...
    99+
    2024-04-02
  • python之re模块
    python 中使用正则表达式需要引入re模块,用来匹配处理字符串  如: import re #第一步,要引入re模块 a = re.findall("匹配规则", "要匹配的字符串") #第二步,调用模块函数 以列表形式返回匹配到的字...
    99+
    2023-01-30
    模块 python
  • python之shutil模块
    shutil:高级的 文件、文件夹、压缩包 处理模块 shutil.copyfileobj(fsrc, fdst[, length])(copyfileobj方法只会拷贝文件内容)将文件内容拷贝到另一个文件中 import shu...
    99+
    2023-01-30
    模块 python shutil
  • python之os模块
    #OS模块 #os模块就是对操作系统进行操作,使用该模块必须先导入模块:import os #getcwd() 获取当前工作目录(当前工作目录默认都是当前文件所在的文件夹) #chdir()改变当前工作目录 #操作时如果书写完整的路径则不...
    99+
    2023-01-30
    模块 python os
  • python模块之collections
    计数器 Counter 计数元素迭代器 elements() 计数对象拷贝 copy() 计数对象清空 clear() from collections import Counter #import collection...
    99+
    2023-01-30
    模块 python collections
  • Python模块之pexpect
    pexpect是一个用来启动子程序并对其进行自动控制的 Python 模块。pexpect 可以用来和像 ssh、passwd、telnet 、rsync等命令行程序进行自动交互下面是我用pexpect写的一个脚本,是用来执行远程主机命令,...
    99+
    2023-01-31
    模块 Python pexpect
  • python之selectors模块
      selectors模块是在python3.4版本中引进的,它封装了IO多路复用中的select和epoll,能够更快,更方便的实现多并发效果。  官方文档见:https://docs.python.org/3/library/...
    99+
    2023-01-31
    模块 python selectors
  • python模块之configparse
    configparser configParser 模块用于操作配置文件 注:Parser汉译为“解析”之意。 配置文件的格式与windows ini文件类似,可以包含一个或多个节(section),每个节可以有多个参数(键=值或者键:值)...
    99+
    2023-01-31
    模块 python configparse
  • python模块之base64
    base64模块提供了在二进制数据和可打印ASCII字符间编解码的功能,包括RFC3548中定义的Base16, Base32, Base64, Ascii85, Base85等编码。 RFC3548中定义的编码适用于将二进制数据编码后,...
    99+
    2023-01-31
    模块 python
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作