首页 > 编程语言 >python-functools

python-functools

时间:2023-10-18 18:34:50浏览次数:35  
标签:__ return python functools add func print def

python-functools

目录

functools模块用于高阶函数:作用与或者返回其它函数的函数。一般来说,对于该模块,任何可调用对象都可以视为一个函数

partial偏函数

偏函数,把函数部分的参数固定下来,相当于为部分的参数添加了一个固定的默认值,形成一个新的函数并返回
从partial生成的新函数, 并且可以像原始对象一样对待,这样可以简化函数调用。

partial(func,*args,**keywords)
仅仅作用函数,输入 函数,函数的参数,返回函数对象
主要作用:减少可调用对象的参数个数
## 等价于
def partial(func, /, *args, **keywords):
    def newfunc(*fargs, **fkeywords):
        newkeywords = {**keywords, **fkeywords}
        return func(*args, *fargs, **newkeywords)
    newfunc.func = func
    newfunc.args = args
    newfunc.keywords = keywords
    return newfunc

案例1-普通使用

import functools
def add(x, y) -> int:
    return x + y

newadd = functools.partial(add, y=5)

print(newadd(7))     	  # 12
print(newadd(7, y=6)) 	  # 13
print(newadd(y=10, x=6))  # 16

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

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)

案例2-延迟执行

import time
import functools

class DelayFunc:
  def __init__(self, duration, func):
    self.duration = duration
    self.func = func

  def __call__(self, *args, **kwargs):
    print(f'Wait for {self.duration} seconds...')
    time.sleep(self.duration)
    return self.func(*args, **kwargs)

  def eager_call(self, *args, **kwargs):
    print('Call without delay')
    return self.func(*args, **kwargs)

def delay(duration):
  """
  装饰器:推迟某个函数的执行。
  同时提供 .eager_call 方法立即执行
  """
  # 此处为了避免定义额外函数,
  # 直接使用 functools.partial 帮助构造 DelayFunc 实例
  return functools.partial(DelayFunc, duration)

@delay(duration=2)
def add(a, b):
  return a+b

print(add(3,5))
# Wait for 2 seconds...
# 8

案例3-回调函数添加参数

partial() 通常被用来微调其他库函数所使用的回调函数的参数

def output_result(result, log=None):
    if log is not None:
        log.debug('Got: %r', result)
# A sample function
def add(x, y):
    return x + y
if __name__ == '__main__':
    import logging
    from multiprocessing import Pool
    from functools import partial
    logging.basicConfig(level=logging.DEBUG)
    log = logging.getLogger('test') p = Pool()
    p.apply_async(add, (3, 4), callback=partial(output_result, log=log))
    p.close()
    p.join()

partialmethod

partialmethod  仅作用于方法
其行为类似 partial但它被设计用作方法定义而非直接用作可调用对象。
class Cell(object):
    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)

c = Cell()
c.alive         # False
c.set_alive()
c.alive         # True

reduce

该函数的作用是将一个序列归纳为一个输出。

reduce(function, iterable[, initializer])

# 大致等于
def reduce(function, iterable, initializer=None):
    it = iter(iterable)
    if initializer is None:
        value = next(it)
    else:
        value = initializer
    for element in it:
        value = function(value, element)
    return value
from functools import reduce

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

l = range(1, 10)
res=reduce(foo, l)
print(res)  # 45

res2=reduce(foo, l, 10)   # 初始值=10
print(res2) # 55

wraps

任何时候你定义装饰器的时候,都应该使用 functools 库中的 @wraps 装饰器来注解底层包装函数

wraps 装饰器能消除装饰器带来的副作用

from functools import wraps

def decorator(func):
    # @wraps(func)
    def wrapper(*args, **kwargs):
        """wrapper func"""
        return func(*args, **kwargs)
    return wrapper

@decorator
def add(x, y):
    """add func"""
    return x + y


print(add.__name__)  # wrapper
print(add.__doc__)    # wrapper func
print(add)   # <function __main__.wrapper>
print(add(1,2))   

# 函数的 __name__ 属性变成了 wrapper ,实际上add 函数整个变成了 decorator(add)
# 这就是装饰器函数的副作用

增加 @wrap 修饰,消除装饰器的副作用

from functools import wraps

def decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        """wrapper func"""
        return func(*args, **kwargs)
    return wrapper

@decorator
def add(x, y):
    """add func"""
    return x + y

print(add.__name__)  # add
print(add.__doc__)    # add func

print(add)   # <function __main__.add>
print(add(1,2))   

update_wrapper

update_wrapper 的作用与 wraps 类似,不过功能更加强大,换句话说,wraps 其实是 update_wrapper 的特殊化

实际上 wraps(wrapped) 相当于 partial(update_wrapper, wrapped=wrapped, **kwargs)

cache(user_function)

简单轻量级未绑定函数缓存

返回值与 lru_cache(maxsize=None) 相同,创建一个查找函数参数的字典的简单包装器。 因为它不需要移出旧值,所以比带有大小限制的 lru_cache()更小更快。

@cache
def factorial(n):
    return n * factorial(n-1) if n else 1
    
 factorial(10)   # 3628800
 factorial(12)   # 479001600

lru_cache(maxsize)

LRU缓存,一个为函数提供缓存功能的装饰器,缓存 maxsize 组传入参数,在下次以相同参数调用时直接返回上一次的结果。用以节约高开销或I/O函数的调用时间。可以减少频繁调用相同的函数使用相同参数的I/O消耗。提升递归函数的执行效率

由于使用字典来缓存结果,因此传给该函数的位置和关键字参数必须为hashable

使用前提
    同样的函数参数一定得到同样的结果
    函数执行时间很长,且要多次执行
本质是函数调用的参数=>返回值
# 缓存同一个函数 相同参数执行的结果
@lru_cache(maxsize=128)
def work(n):
    if n == 1:
        return 1
    else:
        return work(n - 1) * n

print(work(6))
720

@lru_cache(maxsize=None)
def fib(n):
    if n < 2:
        return n
    return fib(n-1) + fib(n-2)
fiblist=[fib(n) for n in range(16)]
print(fiblist)
# [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]

singledispatch

要定义一个泛型函数,用装饰器 @singledispatch 来装饰它,函数根据传参类型不同,做出不同的操作.

from functools import singledispatch
@singledispatch
def typecheck(a):
    print(a, type(a), 'a')


@typecheck.register(str)
def _(text):
    print(text, type(text), 'str')


@typecheck.register(list)
def _(text):
    print(text, type(text), 'list')

@typecheck.register(int)
def _(text):
    print(text, type(text), 'int')

if __name__ == '__main__':
    typecheck([1,2,3,4])

 # [1, 2, 3, 4] <class 'list'> list

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

参考资料

https://docs.python.org/zh-cn/3.10/library/functools.html?highlight=partial#

http://juzizhou.net/article/322

https://blog.csdn.net/xhtchina/article/details/128487830

标签:__,return,python,functools,add,func,print,def
From: https://www.cnblogs.com/tian777/p/17773050.html

相关文章

  • 利用 python 抽取pdf 中表格到 excel
    首先推荐camelotpdf_file_input="TTAF086-2021.pdf"tables=camelot.read_pdf(pdf_file_input,pages='11',flavor='stream')df=tables[0].dfdf.to_excel("TTAF086-2021.xlsx",index=False)pdf表格效果如下其......
  • Python基础习题1
    请大家不要上网搜索或在pycharm里试运行,尽量要闭卷做练习,做错的我们统一讲解。 1. 关于 Python的编程环境,下列的哪个表述是正确的?(   )A、Python的编程环境是图形化的;B、 Python只有一种编程环境ipython;C、Python自带的编程环境是IDLE;D、用windows自带的......
  • Linux 下安装 miniconda,管理 Python 多环境
    安装miniconda1、下载安装包Miniconda3-py37_22.11.1-1-Linux-x86_64.sh,或者自行选择版本2、把安装包上传到服务器上,这里放在/home/software3、安装bashMiniconda3-py37_22.11.1-1-Linux-x86_64.sh4、按回车WelcometoMiniconda3py37_22.11.1-1Inordertocontin......
  • mac搭建python3 开发环境
    #这是linux版的,macos版的https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/Miniconda3-py38_4.8.2-MacOSX-x86_64.shcurlhttps://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/Miniconda3-py38_4.8.2-Linux-x86_64.sh-o/tmp/miniconda.shbash/tmp/minic......
  • 【小白必看】轻松获取王者荣耀英雄皮肤图片的Python爬虫程序
    前言当谈到王者荣耀游戏时,无法忽视的是其丰富多样的英雄皮肤。这些皮肤不仅为玩家提供了个性化的游戏体验,还展示了设计师们的创造力和努力。然而,要手动下载每个英雄的皮肤图片是一项枯燥且费时的任务。幸运的是,我们可以利用编程的力量来自动化这一过程。本文将介绍如何使用Pytho......
  • 【Python&RS】基于GDAL栅格数据/图片位深度(bit)转换
    ​    最近在用OpenCv库处理图片时发现cv库无法读取64位的tif影像,所有想通过Python将64位的图片转换成8位的。今天就跟大家分享一下如何利用Python的GDAL库,实现栅格数据/图片的位深度转换。        在数字图像处理中,我们常常会听到不同的位数术语,比如64位、16......
  • 【小白必看】Python爬虫数据处理与可视化
    前言本文分析了一段Python代码,主要功能是从网页中提取数据并进行数据处理与可视化。代码通过发送HTTP请求获取网页内容,使用XPath解析网页内容,并提取所需数据。然后使用pandas库构建数据结构,对数据进行统计与分组,并使用matplotlib库进行数据可视化。最后,对数据进行筛选、排序和保......
  • 【小白必看】使用Python批量下载英雄联盟皮肤图片的技术实现
    前言英雄联盟是一款备受喜爱的团队对战游戏,游戏中每位英雄都有各种精美的皮肤供玩家选择。本文将介绍一个使用Python编写的英雄联盟皮肤下载器,可以快速获取所有英雄的皮肤图片,让您更方便地欣赏和收藏这些皮肤。运行效果截图导入必要的模块和库importrequests#pipi......
  • 【小白必看】使用Python爬取喜马拉雅音频并保存的示例代码
    前言本文介绍了如何使用Python中的requests库来获取音频文件并保存到本地。在这个例子中,我们使用了喜马拉雅平台上的一个API接口来获取音频ID和名称,并使用这些信息构造音频地址,然后通过发送HTTP请求将音频内容下载保存到本地。运行效果截图导入requests库importrequests......
  • 【小白必看】Python爬取NBA球员数据示例
    前言使用Python爬取NBA球员数据的示例代码。通过发送HTTP请求,解析HTML页面,然后提取出需要的排名、姓名、球队和得分信息,并将结果保存到文件中。导入需要的库和模块importrequestsfromlxmlimportetree使用requests库发送HTTP请求。使用lxml库进行HTML解析。......