闭包:延伸了作用域的函数。
需求:
假如有个名为avg的函数,它的作用是计算不断增加的系列值的均值;
使用类实现:
class Averager(): def __init__(self): self.series=[] def __call__(self,new_value): self.series.append(new_value) total=sum(self.seires) return total/len(self.series) >>>avg=Averager() >>>avg(10) 10.0 >>>avg(11) 10.5 >>>avg(12) 11.0
函数式实现:
def make_averager(): series=[] def averager(new_value): series.append(new_value) total=sum(series) return total/len(series) return averager
>>>avg=make_averager()
>>>avg(10)
10.0
>>>avg(11)
10.5
这种方法,需要将所有值存储在一个列表中,然后每次调用的时候使用sum,更好的实现方式是只存储目前的总值和元素的个数。
def make_averager(): count=0 total=0 def averager(new_value): nonlocal count,total count+=1 total+=new_value return total/count
声明nonlocal,与声明global的原理类似,因为如果不做这样的声明,函数内部对变量赋值会变成局部变量。
装饰器:装饰一个函数,将函数作为参数。返回一个函数或者可调用对象
装饰器的关键特性:它们是在被装饰的函数定义之后立即运行。通常是在python加载模块时
常见装饰器:
一:时间装饰器,输出函数的运行时间
import time def clock(func): def clocked(*args):#接受任意个参数 t0=time.perf_counter() result=func(*args) elapsed=time.perf_counter()-t0 name=func.__name__ arg_str=‘, ’。join(repr(arg) for arg in args) print('[%0.8fs]%s(%s)->%r'%(elapsed,name,arg_str,result)) return result return clocked
from clockdeco import clock @clock def factorial(n): return 1 if n<2 else n*factorial(n-1) if __name__=='__main__': print('6!=',factorial(6))
升级:让用户控制控制被装饰函数的输出结果
#clockdeco_param.py
import time DEFAULT_FMT='[{elapsed:0.8f}s]{name}({args})->{result}' def clock(fmt=DEFAULT_FMT): def decorate(func): def clocked(*_args): t0=time.time() _result=func(*_args) elapsed=time.time()-t0 name=func.__name__ args=', '.join(repr(arg) for arg in _args) result=repr(_result)#返回对象的一个string格式 print(fmt.fomat(**loclas()))#调用clocked函数的局部变量 return _result return clocked return decorate
更改不同的显示格式:
import time from clockdeco_param import clock @clock('{name}({args}) dt={elapsed:0.3f}s') def snooze(seconds): time.sleep(seconds) for i in range(3): snooze(.123)
@classmethod
定义备选的构造方法。
class test(object):
def __init__(self,arg):
self.pig=arg
@classmethod
def froml(cls):
a=5
return cls(a)
def p(self):
print(self.pig)
a=test.froml()
a.p()