一、高阶函数
举例: def counter(base): def inc(step=1) base += step return base return inc
1、自定义sort函数
- 仿照内建函数sorted,自行实现一个sort函数(不使用内建函数),能够为列表元素排序
- 内建函数sorted函数是返回一个新的列表,可以设置升序或者降序,可以设置一个排序的函数
- sorted函数的实现原理,扩展到map,filter函数的实现原理
方式一: def sort(iterable,reverse=False): ret = [] for x in iterable: for i,y in enumerate(ret): flag = x>y if reverse else x<y if flag: #找到大的就地插入 ret.insert(i,x) break else: ret.append(x) return ret print(sort([1,3,4,52,6,10]) 方式二: def sort(iterable,fn=lambda a,b:a>b): ret = [] for x in iterable: for i,y in enumerate(ret): if fn(x,y): #fn函数的返回值是bool ret.insert(i,x) break else: ret.append(x) return ret print(sort([1,3,4,52,6,10])
2、sorted(iterable[,key][,reverse]) 排序函数
- 返回一个新的列表,对一个可迭代对象的所有元素排序,排序规则为key定义的函数,reverse表示排序反向
sorted(lst,key=lambda x:6-x) 排序返回一个新列表 >>> lst = [1,3,4,52,6,10] >>> sorted(lst,key=lambda x:6-x) [52, 10, 6, 4, 3, 1] list.sort(key=lambda x:6-x) 就地修改lst,没有返回一个新列表 >>> lst.sort(key=lambda x:6-x) >>> lst [52, 10, 6, 4, 3, 1] >>>
3、filter(function,iterable)
举例:过滤出数列中能被3整除的数字 >>> lst = filter(lambda x:x%3==0,[1,9,55,150,-3,78,28,123]) >>> list(lst) [9, 150, -3, 78, 123] >>>
4、map(function,*iterables) --> map object
- 对多个可迭代对象的元素按照指定的函数进行映射,返回一个迭代器
>>> list(map(lambda x:2*x+1,range(5))) [1, 3, 5, 7, 9] >>> >>> dict(map(lambda x:(x%5,x),range(500))) {0: 495, 1: 496, 2: 497, 3: 498, 4: 499} >>>
二、柯里化
如:z = f(x,y)z转换成z = f(x)(y)的形式 将加法函数柯里化 def add(x,y): return x + y 转换如下: def add(x): def_add(y) return x + y return _add add(5)(6)
三、装饰器
1、无参装饰器
@logger # 等价于add = logger(add) def add(x,y): #业务函数 return x+y def logger(fn): #装饰器函数 def wrapper(*args,**kwargs): print('begin') x = fn(*args,**kwargs) print('end') return x return wrapper print(logger(add)(5,y=50)) 等价于print(add(45,40))
2、装饰器和高阶函数
- 装饰器是高阶函数,但是装饰器是对传入函数的功能的装饰(功能增强)
举例: import datatime import time def logger(fn): def wrap(*args,**kwargs): #befor 功能增强 print("args={},kwargs={}".format(args,kwargs)) start = datetime.datetime.now() ret = fn(*args,**kwargs) #after duration = datetime.datetime.now() - start print("function {} took {}s".format(fn.__name__,duration.total_seconds())) return ret return wrap @logger def add(x,y): print('==========call add===========') time.sleep(2) print(add(4,y=7))
3、文档字符串
举例: >>> def add(x,y): """This is a function addition""" a = x+y return x+y >>> print("name={} doc={}".format(add.__name__,add.__doc__)) name=add doc=This is a function addition >>> print("name={}\ndoc={}".format(add.__name__,add.__doc__)) name=add doc=This is a function addition >>>
4、带参装饰器
1, 提供一个函数,被封装函数属性==copy==》包装函数属性,改造成带参装饰器 def copy_properties(src): def _copy(dst): dst.__name__ = src.__name__ dsr.__doc__ = src.__doc__ return dst return _copy def logger(fn): @copy_properties(fn) # wrapper = wrapper(fn)(wrapper) def wrapper(*args,**kwargs): 'I am wrapper' print('begin') x = fn(*args,**kwargs) print('end') return x return wrapper @logger def add(x,y): '''This is a function for add''' return x+y print("name={},doc={}".format(add.__name__,add.__doc__)) 2, 需求:获取函数的执行时长,对时长超过阈值的函数记录一下 import time import datetime def copy_properties(src): def _copy(dst): dst.__name__ = src.__name__ dst.__doc__ = src.__doc__ return dst return _copy def logger(duration): def _logger(fn): @copy_properties(fn) def wrapper(*args,**kwargs): start = datetime.datetime.now() ret = fn(*args,**kwargs) print(111,args,kwargs) delta = (datetime.datetime.now() - start).total_seconds() print(2222,delta,duration) # duration阈值设置为5秒,由logger函数传入 print('so slow') if delta > duration else print('so fast') return ret return wrapper return _logger @logger(5) # add = logger(5)(add) def add(x,y): time.sleep(3) return x+y print(add(5,6))
改进装饰器logger函数
def logger(dutation,func=lambda name,dutation:print('{} took {}s'.format(name,dutation))): def _logger(fn): @copy_properties(fn) def wrapper(*args,**kwargs): start = datetime.datetime.now() ret = fn(*args,**kwargs) delta = (datetime.datetime.now() - start).total_seconds() if delta > duration: func(fn.__name__,duration) return ret return wrapper return _logger
四、functools 模块
import datetime,time,functools def logger(duration,func=lambda name,duration:print('{}took {}s'.format(name,duration))): def _logger(fn): @functools.wraps(fn) def wrapper(*args,**kwargs): '''I am wrapper''' start = datetime.datetime.now() ret = fn(*args,**kwargs) delta = (datetime.datetime.now() - start).total_seconds() if delta > duration: func(fn.__name__,duration) return ret return wrapper return _logger @logger(5) def add(x,y): '''I adm add''' time.sleep(5) return x+y print(add(5,6))
1、functools模块 partial方法
1、partial方法举例 : import functools def add(x,y) -> int: 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)) 2、@functool.lru_cache(maxsize=128,type=False)装饰器 如果maxsize设置为None,则禁用LRU功能,并且缓存可以无限制增长 当maxsize是二的幂时,LRU功能执行的最好 如果typed设置为Ture,则不同类型的函数参数将单独缓存:如:f(3)和f(3.0)将被视为具有 不同结果的不同调用 3、lru_cache装饰器 通过一个字典缓存被装饰器的调用和返回值
五、参数注解
1、inspect模块
>>> import inspect >>> def add(x:int,y:int,*args,**kwargs) -> int: return x + y >>> sig = inspect.signature(add) >>> print(sig) (x:int, y:int, *args, **kwargs) -> int >>> print('params:',sig.parameters) #有序字典 params: OrderedDict([('x', <Parameter "x:int">), ('y', <Parameter "y:int">), ('args', <Parameter "*args">), ('kwargs', <Parameter "**kwargs">)]) >>> print('return:',sig.return_annotation) return: <class 'int'> >>> print(sig.parameters['y']) y:int >>> print(sig.parameters['args']) *args >>> print(sig.parameters['args'].annotation) <class 'inspect._empty'> >>> 使用举例 import inspect def add(x,y:int=7,*args,z,t=10,**kwargs)-> int: return x + y sig = inspect.signature(add) print(sig) print('params:',sig.parameters) print('return:',sig.return_annotation) print('~~~~~~~~~~') for i,iterm in enumerate(sig.parameters.items()): name,param = iterm print('=========',i+1,name,param.annotation,param.kind,param.default) print(param.default is param.empty,end='\n\n')