functools module & inspect module

1. functools module

看名字是函数工具,里面应该就是一些和函数相关的方法.

1.1functools.update_wrapper(wrapper, wrapped)

完整版是:
functools.update_wrapper(wrapper,wrapped,assigned=WRAPPER_ASSIGNMENTS,updated=WRAPPER_UPDATES)

用wrapped的函数信息,更新给wrapper。

调用它:

functools.update_wrapper(test_add, add)

1.2 装饰器functools.wraps(wrapped)

完整版是下面这个,不过一些默认参数我们应该不用:

functools.wrap(wrapped,assigned=WRAPPER_ASSIGNMENTS,updated=WRAPPER_UPDATES)

wrapped是要被包装的函数,就是以哪个函数的name和doc为参考,

然后下面写要更改的函数。

例:

  from functools import wrap
  @wrap(add)
  def test_add():
      ....
      ....
      return ....

这样就把add函数的信息,赋给了test_add函数。

1.3 functools.reduce(function,iterable)

它的作用是,把这个iterable的元素,按function函数的方法,削减成一个元素。
“Apply function of two arguments cumulatively to the items of sequence, from left to right, so as to reduce the sequence to a single value.”

参数列表里面还有一个初始值参数,initializer=None,可以不管它。

这是reduce的原码:

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

看原码,这个function要传入两个参数,element是从iterable里迭代出来的,value每次都会被上一次的计算结果覆盖,用于新的计算,给我一种类似于迭代的感觉。

例一:

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

reduce(add, range(5)) #每次的和,都要与下一个元素相加
10 

例二:

str="fuck fuck pig pig damn nooooo"
list=str.split(' ')

def fun(x,y):
    if y in x:
        x[y]=x[y]+1
    else:
        x[y]=1
    return x

result=reduce(fun,list,{}) #不断增添的对象是一个字典
{'fuck': 2, 'pig': 2, 'damn': 1, 'nooooo': 1}

这是一个计算词频的函数,挺有用的,但是不是我写的是抄的,感受一下。

1.4 functools.partial()

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

这个方法的作用是,给func函数设定几个默认值,这样在执行这个函数(此函数非彼函数了)的时候,可以调用这些默认值。

原码:

def partial(func, *args, **keywords): #给一个函数,和默认值,都被收集在args和keyword里

    def newfunc(*fargs, **fkeywords): #这里是调用时候传给实参的形参
        newkeywords = keywords.copy() #拷贝一份partial给的默认参数
        newkeywords.update(fkeywords) #用传入的实参来更新partial给的默认值
        return func(*args, *fargs, **newkeywords) #返回这些实参,注意前面的arg是partial设置的默认参数,fargs是调用时传入的实参,都是位置传参。

    newfunc.func = func #这三个是创造一个属性,记住原来函数的名字,partial给的位置参数,和关键字参数
    newfunc.args = args
    newfunc.keywords = keywords

    return newfunc

不写例子了,现在脑仁疼。

1.5 装饰器 functools.lru_cache

这个装饰器是缓存用的,就是说,用这个装饰器装饰了函数,那么这个函数执行过多次之后,如果再执行,参数是以前执行过的,那么可以立即得到返回值,不用再次通过计算得出来。

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

maxsize是指最大能缓存多少条,一般是2的n次方的时候,效率最高。

typed是控制,如果两次输入的参数内容相等,但类型不同,是不是归于同一种结果,例如int 3和float 3.0,数值一样,但是类型不一样

“Since a dictionary is used to cache results, the positional and keyword arguments to the function must be hashable.”

上面是帮助文档里面的介绍,就是说,参数必须是可哈希的,因为这个缓存,它是一个字典,用参数作为key,用返回值作为value,所以不可哈希的值不能做key。

2. inspect module

2.1 inspect里的一些判断函数

inspect module 里面有一些判断函数,通过名字就可以看出来:

inspect.isfunction(object) #判断是不是一个函数
inspect.isgeneratorfunction(object) #判断是不是一个生成器函数
inspect.isgenerator(object) #判断是不是一个生成器
....

还有很多功能,可以在帮助文档,搜索inspect module里找到。

2.2 inspect的signature

用法如下:

inspect.signature(callable, *, follow_wrapped=True)

举一个例子,注意和参数注解的区别:

def accumlate(x:int, y:int) -> int: #定义一个函数
return x*y

print(accumlate.__annotations__) #看看这个函数的参数注解
{'x': <class 'int'>, 'y': <class 'int'>, 'return': <class 'int'>}

print(inspect.signature(accumlate))
(x:int, y:int) -> int

a = inspect.signature(accumlate)
type(a)
inspect.Signature #注意,这个a是一个签名类型

对于签名类型的数据,可以调用parameters方法,调出函数的形式参数及其类型。

print(a.parameters)  #打印出来看,是一个有序的字典
OrderedDict([('x', <Parameter "x:int">), ('y', <Parameter "y:int">)]) #注意这个字典里面的键值对的value,都是parameter类型的

type(a.parameters) #然后看一下类型,是一个不知道啥啥的类型
mappingproxy

parameter类型的对象,有五种属性:

.name 这是参数的名字,字符串形式的
.default 这是参数的默认值,如果没给默认值的话,就是empty
.annotation 这是参数注解,显示的是参数注释的类型
.kind 这是参数的传参方式
.empty 特殊的类,用来标记default属性或者annotation的值

位置传参的可变参数,和关键件传参的可变参数,也有annotation,但是是empty。

对于签名类型的数据,可以调用.return_annotation方法,调出函数的返回值类型。

return1 = a.return_annotation
print(return1)
type(return1)

int
type

猜你喜欢

转载自blog.csdn.net/LittleHuang950620/article/details/82179895