Python 模块简介 -- functools

Python 的 functools 模块可以说主要是为函数式编程而设计,用于增强函数功能。

functools.partial

用于创建一个偏函数,它用一些默认参数包装一个可调用对象,返回结果是可调用对象,并且可以像原始对象一样对待,这样可以简化函数调用。实际上 partial 相当于一个高阶函数,其大致的实现如下(实际在标准库中它是用 C 实现的):

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

一个简单的使用示例:

from functools import partial

def add(x, y):
    return x + y

add_y = partial(add, 3)  # add_y 是一个新的函数
add_y(4)

一个很实用的例子:

def json_serial_fallback(obj):
    """JSON serializer for objects not serializable by default json code"""
    if isinstance(obj, (datetime.datetime, datetime.date)):
        return str(obj)
    if isinstance(obj, bytes):
        return obj.decode("utf-8")
    raise TypeError ("%s is not JSON serializable" % obj)

json_dumps = partial(json.dumps, default=json_serial_fallback)

可以在 json_serial_fallback 函数中添加类型判断来指定如何 json 序列化一个 Python 对象

functools.update_wrapper

用 partial 包装的函数是没有 __name____doc__,这使得依赖于这些属性的代码可能无法正常工作。update_wrapper 可以拷贝被包装函数的 __name____module____doc____dict__属性到新的封装函数中去,其实现也非常简单:

WRAPPER_ASSIGNMENTS = (‘__module__‘, ‘__name__‘, ‘__doc__‘)
WRAPPER_UPDATES = (‘__dict__‘,)
def update_wrapper(wrapper,
                   wrapped,
                   assigned = WRAPPER_ASSIGNMENTS,
                   updated = WRAPPER_UPDATES):

    for attr in assigned:
        setattr(wrapper, attr, getattr(wrapped, attr))
    for attr in updated:
        getattr(wrapper, attr).update(getattr(wrapped, attr, {}))

    return wrapper

update_wrapper 主要用在装饰器函数中,以确保被装饰的保留原理的属性。示例:

def wrap(func):
    def call_it(*args, **kwargs):
        print "calling", func.__name__
        return func(*args, **kwargs)
    return call_it

@wrap
def hello():
    print "hello"

from functools import update_wrapper
def wrap2(func):
    def call_it(*args, **kwargs):
        print "calling", func.__name__
        return func(*args, **kwargs)
    return update_wrapper(call_it, func)

@wrap2
def hello2():
    print "hello2"

# Script starts from here

if __name__ == ‘__main__‘:
    print hello.__name__  # call_it
    print hello2.__name__  # hello2

functool.wraps

wraps 函数是为了在装饰器中方便的拷贝被装饰函数的签名,而对 update_wrapper 做的一个包装,其实现如下:

def wraps(wrapped,
          assigned = WRAPPER_ASSIGNMENTS,
          updated = WRAPPER_UPDATES):

    return partial(update_wrapper, wrapped=wrapped,
                   assigned=assigned, updated=updated)

示例:

from functools import wraps
def wrap3(func):
    @wraps(func)
    def call_it(*args, **kwargs):
        print "calling", func.__name__
        return func(*args, **kwargs)
    return call_it

@wrap3
def hello3(func):
    print "hello3"

print hello3.__name__  # hello3

functools.reduce

在 Python2 中等同于内建函数 reduce,但是在 Python3 中内建的 reduce 函数被移除,只能使用 functools.reduce。该函数的作用是将一个序列归纳为一个输出,其原型如下:

reduce(function, sequence, startValue)

使用示例:

>>> def foo(x, y):
...     return x + y
...
>>> l = range(1, 10)
>>> reduce(foo, l)
45
>>> reduce(foo, l, 10)
55

functools.cmp_to_key

在 list.sort 和 内建函数 sorted 中都有一个 key 参数,这个参数用来指定取元素的什么值进行比较,例如按字符串元素的长度进行比较:

>>> x = [‘hello‘,‘abc‘,‘iplaypython.com‘]
>>> x.sort(key=len)
>>> x
[‘abc‘, ‘hello‘, ‘iplaypython.com‘]

也就是说排序时会先对每个元素调用 key 所指定的函数,然后再排序。同时,sorted 和 list.sort 还提供了 cmp 参数来指定如何比较两个元素,但是在 Python 3 中该参数被去掉了。cmp_to_key 函数就是用来将老式的比较函数转化为 key 函数。用到 key 参数的函数还有 sorted(), min(), max(), heapq.nlargest(), itertools.groupby() 等。

functools.total_ordering

这个一个类装饰器,如果一个类实现了 __lt____le____gt____ge__ 这些方法中的至少一个,该装饰器会自动实现其他几个方法。示例:

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

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

print dir(Student)

stu = Student("Huoty", "Kong")
stu2 = Student("Huoty", "Kong")
stu3 = Student("Qing", "Lu")

print stu == stu2
print stu > stu3

输出结果:

[‘__doc__‘, ‘__eq__‘, ‘__ge__‘, ‘__gt__‘, ‘__init__‘, ‘__le__‘, ‘__lt__‘, ‘__module__‘]
True
False

functools.lru_cache

这个装饰器是在 Python3 中新加的,在 Python2 中如果想要使用可以安装第三方库 functools32。该装饰器用于缓存函数的调用结果,对于需要多次调用的函数,而且每次调用参数都相同,则可以用该装饰器缓存调用结果,从而加快程序运行。示例:

from functools import lru_cache
@lru_cache(None)
def add(x, y):
    print("calculating: %s + %s" % (x, y))
    return x + y

print(add(1, 2))
print(add(1, 2))  # 直接返回缓存信息
print(add(2, 3))

输出结果:

calculating: 1 + 2
3
3
calculating: 2 + 3
5

由于该装饰器会将不同的调用结果缓存在内存中,因此需要注意内存占用问题,避免占用过多内存,从而影响系统性能。

functools.singledispatch

单分发器,Python 3.4 新增,用于实现泛型函数,由一个单一参数的类型来决定调用哪个函数。示例:

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

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

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

fun("Hello world.")
fun(18)
fun(["a", "b"])

输出:

Hello world.
18
0 a
1 b

一个还可以支持多个泛型:

@fun.register(float)
@fun.register(Decimal)
def _(arg, verbose=False):
    print(arg)

fun.registry 中保存了所有的泛型函数,使用 fun.registry[float] 或者 fun.dispatch(float) 可以获取相应的函数:

>>> fun.registry
mappingproxy({int: <function singledispatch._>,
              float: <function singledispatch._>,
              list: <function singledispatch._>,
              object: <function singledispatch.fun>,
              decimal.Decimal: <function singledispatch._>})
>>> fun.dispatch(float)
<function singledispatch._>
>>> fun.registry[int]
<function singledispatch._>

原文地址:https://www.cnblogs.com/paisenpython/p/10339481.html

时间: 2024-10-03 04:50:53

Python 模块简介 -- functools的相关文章

以写代学:python 模块简介&输出用户指定位数密码的脚本

什么是模块 (1)模块是从逻辑上组织python代码的形式 (2)当代码量变的相当大的时候,最好把代码分成一些有组织的代码段,前提是保证它们的彼此交互 (3)这些代码段之间有一定的联系,可能是一个包含数据成员和方法的类,也可能是一组相关但彼此独立的操作函数 (4)模块名不能乱起,字母数字下划线组成,首字母不能是数字 导入模块 (1)使用import导入模块,模块被导入后,程序会自动生成pyc的字节码文件以提升性能 (2)模块属性通过"模块名.属性"的方法调用,如果仅需要模块中的某些属性

python模块简介

import 模块的实质就是把要导入模块里面的代码,从上到下执行一遍 找模块的顺序是,先从当前目录下找,找不到的话,再环境变量里面找 标准模块: python自带的,不需要安装的,直接import就能用的 自己写的模块: 也就是自己写的python 第三方模块: 别人已经开发好的功能,需要安装的 安装方式第一种: 这是操作系统命令,不是在python命令行里面执行 pip install xxx 安装某个模块 pip list 查看已经安装的模块 pip uninstall xxx卸载模块 pi

进阶第一课 Python模块简介

一.前面我们说过,Python自从出世以来,就是免费.开放的.如今造就了数目庞大的模块.那么问题来了,模块是什么? 对于Python而言,模块是若干功能的集合. 一个模块有自己的属性,就像一个人有自己的姓名.身高.体重.性别... 一个模块也有自己的方法.所谓方法,就是这个模块能做的事情.举个栗子-_-!! 1 import time 2 a=time.time() 3 print(a) 分析一下: 1)既然是模块,就只有在导入(有的模块需要自行安装,还涉及包依赖,以后会讲到).格式是:impo

python paramiko模块简介及安装

一:简介 paramiko是用python语言写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接. 由于使用的是python这样的能够跨平台运行的语言,所以所有python支持的平台,如Linux, Solaris, BSD, MacOS X, Windows等,paramiko都可以支持,因此,如果需要使用SSH从一个平台连接到另外一个平台,进行一系列的操作时,paramiko是最佳工具之一. 举个常见的例子,现有这样的需求:需要使用windows客户端,远程连接到L

Kemaswill 机器学习 数据挖掘 推荐系统 Python optparser模块简介

Python optparser模块简介 原文地址:https://www.cnblogs.com/ppybear/p/12350129.html

python学习笔记-Day05-第二部分(模块简介)

模块是一种组织形式,他是 实现了某个功能的代码的集合,它将彼此有关系的代码组织到一个文件或一个目录中(目录中包含多个文件,这里改称为 "包"). 模块分三类 内置模块 第三方模块 自定义模块 模块的定义: package/└── mod01.py package/├── mod01.py├── mod02.py└── mod03.py package/├── __init__.py├── mod01.py├── mod02.py└── mod03.py package/├── __in

6.python模块(导入,内置,自定义,开源)

一.模块 1.模块简介 模块是一个包含所有你定义的函数和变量的文件,其后缀名是.py.模块可以被别的程序引入,以使用该模块中的函数等功能.这也是使用python标准库的方法. 类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性和代码间的耦合.而对于一个复杂的功能来,可能需要多个函数才能完成(函数又可以在不同的.py文件中),n个 .py 文件组成的代码集合就称为模块. 2.模块的引入 在Python中用关键字import来引入某个模块,比如要引用模

Python模块之configpraser

Python模块之configpraser   一. configpraser简介 用于处理特定格式的文件,其本质还是利用open来操作文件. 配置文件的格式: 使用"[]"内包含section,section下为类似key-value的配置内容(例如:samba配置文件) G:\Python项目实战\模块\configparser>start example.txt #基于windows平台 # 注释1 :注释2 [global] #节点 workgroup = WORKGRO

python 模块介绍 - Base16, Base32, Base64 数据编码

简介 功能:RFC 3548: Base16, Base32, Base64 数据编码.转换二进制数据为适合明文协议传输的 ASCII 序列.转换8bits 为每个字节包含 6,5 或 4bits 的有效数据,比如 SMTP, URL 的一部分或者 HTTP POST 的一部分.参考:RFC 3548.编码算法不同于 uuencode.类型:标准库相关模块:uu, binhex, uu, quopri Base64 是一种基于 64 个可打印字符来表示二进制数据的表示方法.由于 2 的 6 次方