1.Partial方法

2.偏函数,把函数部分的参数固定下来,相当于为部分参数添加了一个固定的默认值,形成一个新的函数返回。

3. 一定返回的是新的函数,原来的函数包在内了。

(1)例题

from functools import partial

def add(x,y):

    return x +y

newadd = partial(add,4)

print(newadd(5))

例题,把x固定了。

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:579817333 
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
from functools import partial

import inspect

def add(x,y):

    return x +y

newadd = partial(add,x=4)

print(newadd(y=5))
print(inspect.signature(newadd))

#打印出的:
9
( *,x=4, y)

根据签名得到,被固定的参数的前面增加,*,

#课堂例子:
import functools

def add(x,y):

    return x+y

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

print(newadd(7))

print(newadd(7,y=6))

print(newadd(y=10,x=6))

import inspect

print(inspect.signature((newadd)))
#12

13

16

(x, *, y=5)

被固定的是add的函数的y的值,所以签名是(x,*,y=5),所以传参的方式x使用位置或者关键字均可以,y可以使用关键字传参,不传参的话可以使用默认值。

(2)例题:

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:579817333 
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
import functools

def add(x,y,*args):

    print(args)

    return x+y

newadd = functools.partial(add,1,3,5,6)

print(newadd(7))

print(newadd(7,10))

print(newadd(9,10,x=2,y=4))   #  一定不可以,因为x,y被固定了,被填充满了,在添加值是不可以的。

print(newadd())

import inspect

print(inspect.signature(newadd))

4 partial函数的本质。(本质就是元组和字典合并。)

def partial(func,*args,**kwargs):

    def newfunc(*fargs,**fkwargs):#包装函数

        newkwargs = kwargs.copy()  #关键字参数拷贝  (调用时候才会执行)

        newkwargs.update(fkargs)  #关键词传参参数全部更新,(调用时候才会执行)

        return func(*(args+fargs),**newkwargs)  #元素依次的合并,返回一个新的元组,不去重的。(调用时候才会执行)

    newfunc.func = func  #保留原来的函数

    newfunc.args = args   #保留原函数的位置参数    空元组

    newfunc.kwargs = kwargs  #保留原函数的关键字参数。  #字典。

    return newfunc   #返回一个新的函数

def add(x,y):

    return x+y

foo = partial(add,4)

foo(5)

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

lru 最近最少使用,cache缓存。

如果maxsize设置的是none,所以禁用了LRU功能,并且缓存可以无限制的增长,当maxsize是2的次幂的时候,LRU执行良好。

如果typed设置为True,则不同类型的函数参数将单独缓存,例如;f(3)和f(3.0)视为不同结果的不同调用。

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:579817333 
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
import functools

@functools.lru_chache()

def add(x,y,z=5):

    time.sleep(z)

    return x+y

print(add(4,5))

print(add(4.0,5))

print(add(4,6))

print(add(4,6,3))

print(add(6,4))

print(add(4,y=6))

print(add(x=4,y=6))

print(add(y=6,x=4))

总结:

第一个print和第二个一样。

第七个和第八个一样。其余的不一样。

缓存机制是什么:利用字典,结果放在value中,k为add的参数。

lru_cache装饰器。

通过一个字典缓存被装饰函数的调用和返回值。

#第一个类型

import functools

functools._make_key((4,6),{'z':3},False)

#打印[4, 6, <object at 0x7f98aa654090>, 'z', 3]

返回的是一个列表。前面的元素是args。。后面是kwargs。<object at 0x7f98aa654090>代表的是符号。

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:579817333 
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
#第二个类型

import functools

functools._make_key((4,6,3),{},False)

生成的是列表。

#打印出[4, 6, 3]
#第三个类型

functools._make_key(tuple(),{'z':3,'x':4,'y':6},False)
#打印出[<object at 0x7f98aa654090>, 'x', 4, 'y', 6, 'z', 3]进行了排序。
#第四个类型

functools._make_key(tuple(),{'z':3,'x':4,'y':6},True)

#打印出[<object at 0x7f98aa654090>, 'x', 4, 'y', 6, 'z', 3, int, int, int]

总结:pyted改为True显示类型。缺省值就是false。

Object把二元组里面的元素加进去。

_make_key…

顺序,拆开k显示的是不同的。

@functools.lru_cache()改造斐波那契数列。

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:579817333 
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
import functools

@functools .lru_cache(maxsize=100)

def fib(n):

    if n<3:

        return 1

    else:

        return fib(n-1)+fib(n-2)

n=fib(5)

print(n)
import functools

@functools .lru_cache(maxsize=100)

def fib(n):

    if n<3:

        return 1

    else:

        return fib(n-1)+fib(n-2)

print([fib(x) for x in range(35)])

原因利用缓存:因为计算的结果下一项利用到了上一项。倒向运算。所有的计算所需的数据都来自缓存,无须再次计算啦。

6总结:

使用前提,同样的函数参数一定得到同样的结果。

函数执行时间长,且要执行很多次。

本质上是函数调用函数 =》返回值。

缓存的缺点,不支持缓存过期,key无法过期,失效。不支持清除操作,不支持分布式,是一个单机的缓存。

使用场景,单机上需要空间换时间的地方,可以用缓存来将计算变成快速的查询。