实现方法一 类实现
class Average():
def init(self):
self.series []
def call(self, new_values):
self.series.append(new_values)
total sum(self.series)
return total/len(self.series)
avg Average()#avg是Average的实例
avg(10)
avg(11)
实现方法二 高阶函数make_average
def make_average():
series []
def average(new_value): series.append(new_value) total sum(series) return total/len(series) return average
avg make_average()#avg是内部函数average
avg(10)
avg(11)
本来在调用avg时 函数make_avergae早就返回了 作用域也消失了
所以在average函数中series 时自由变量
series []和后面的def average 形成了闭包 延伸到函数作用域之外了
所以闭包是一种函数 会保留定义函数时存在的自由变量的绑定
7.第6条中的series是列表 函数中的函数修改它时没有把它作为局部变量来看
但如果series是一个整型值 在函数中的函数执行series 1 相当于定义 也就是有一个隐性的series局部变量
这时会出错 不在作为自由变量看待 可以加入 nonlocal series 来声明这不是局部变量
8.实现装饰器 输出函数的运行时间 装饰器的特点 接受相同的参数 代替原来的函数 返回本该返回的值 同时还做些额外操作
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#取代被装饰的函数
9.以上的clock装饰器有些缺点:
不支持关键字参数
遮盖了被装饰函数的__name__和__doc__属性
改进
import time
import functools
#使用了functools里的wraps 来把相关属性赋值给clocked
def clock(func):
functools.wraps(func)
def clocked(*args, **kwargs):
t0 time.time()
result func(*arg, **kwargs)
elapsed time.time() - to
name func.name
arg_lst []
if args :
arg_lst.append(’.’.join(repr(arg) for arg in args))
if kwargs:
pairs [’%s %r’ % (k,w) for k, w in sorted(kwargs.items())]
arg_lst.append(’, .join(pairs))
arg_str , ‘.join(arg_lst)
print(’[%0.8fs] %s(%s) - %r ’ % (elapsed, name, arg_str, result))
return result
return clocked
10.标准库的装饰器
property,classmethod,staticmethod
以后会讨论的
11.加入functools.lru_cache做备忘
例
clock
def fibonacci(n):
if n 2:
return n
return fibonacci(n-2) fibonacci(n-1)
fibonacci(6)
改进
import functools
functools.lru_cache()
clock
def fibonacci(n):
if n 2:
return n
return fibonacci(n-2) fibonacci(n-1)
结果在P169
使用 ingledispatch把多个函数绑定在一起组成一个泛函数
例
singleddispatch
def htmlize(obj):
content html.escape(repr(obj))
return ‘
{}’.format(content)
htmlize.register(str)
def _(text):
pass
htmlize.register(numbers.Intergral)
def _(n):
pass
13.叠放装饰器
d1
d2
def f():
pass
等同于
def f():
pass
f d1(d2(f))
14.参数化装饰器 使得装饰器可以接受参数
例
registry set()
def register(active True):
def decorate(func):
if active:
registry.add(func)
else:
registry.discard(func)
return func
return decorate
register(active False)
def f1():
pass
register()
def f2():
pass
15.参数化之前的clock装饰器
def clock(fmt DEFAULT_FMT):
def decorate(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
return decorate



