函数式编程——闭包与装饰器

闭包延伸了作用域的函数。

需求:

假如有个名为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()

原文地址:https://www.cnblogs.com/liuguangshou123/p/13457272.html