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