广告
返回顶部
首页 > 资讯 > 后端开发 > 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://www.lsjlt.com/news/192239.html(转载时请注明来源链接)

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

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 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+
    2022-11-11
  • 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编程functools模块创建修改的高阶函数解析
    目录partial 函数装饰器 @lru_cachereduce 函数partial 函数 partial 为偏函数(有的地方也叫做部分应用函数),它是对函数的二次封装,将现有函数的...
    99+
    2022-11-12
  • python模块之shutil
    shutil模块提供了一些针对文件和目录的高级操作,主要是拷贝、移动。对于单个文件的操作,还可参考os模块 Warning:即使是高级别的拷贝函数(shutil.copy(),shutil.copy2())也不能拷贝所有的文件元数据。意思...
    99+
    2023-01-31
    模块 python shutil
  • python模块之hashlib
    hashlib模块实现了多种安全哈希和信息摘要算法的通用接口,包括FIPS中定义的SHA1, SHA224, SHA256, SHA384, SHA512以及RFC 1321中定义的MD5 注意点:1. adler32及crc32哈希由z...
    99+
    2023-01-31
    模块 python hashlib
  • Python模块之: configobj
    原来也有写过一篇文章Python模块之: ConfigParser 用来解析INI文件,但是在使用过程中存在一些问题。比如:1,不能区分大小写。2,重新写入的ini文件不能保留原有INI文件的注释。3,重新写入的ini文件不能保持原有的顺序...
    99+
    2023-01-31
    模块 Python configobj
  • Python 模块之fabric
    Fabric是一个Python库和命令行工具,旨在为应用部署和系统管理任务的SSH的流水线式操作,使之更加高效和方便。Fabric提供了一套基本的执行本地和远程shell命令、上传和下载文件的操作,包括一些辅助函数,例如驱动正在运行的用户输...
    99+
    2023-01-31
    模块 Python fabric
  • python之MySQLdb模块
    防伪码:忘情公子著  MySQLdb是用来通过python控制mysql数据库的一个模块。  在说这个模块之前,我们先来想一下在命令行模式下操作mysql数据库的步骤,一般来说分为三步:...
    99+
    2022-10-18
  • python之commands模块
    要获得shell命令的输出只需要`cmd`命令就可以了,需要得到命令执行的状态则需要判断$的值, 在Python中有一个模块commands也很容易做到以上的效果.看一下三个函数:1). commands.getstatusoutput(c...
    99+
    2023-01-31
    模块 python commands
  • python模块之subprocess
    subprocess.run() 运行并等待args参数指定的指令完成,返回CompletedProcess实例。 参数:(*popenargs, input=None, capture_output=False, timeout=Non...
    99+
    2023-01-31
    模块 python subprocess
  • Python之Subprocess模块
    前言其实有一个模块也支持执行系统命令,那个模块就是sys.system,但他执行系统命令会直接通过主进程去执行命令,那假如,该命令的执行需要耗费一个小时,那么主进程会卡一个小时,而不会去干别的事,这样就会导致程序的运行效率低下。 如果由su...
    99+
    2023-01-31
    模块 Python Subprocess
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作