面向对象思想的实现
class Averager(): def __init__(self): self.series = [] def __call__(self, new_value): self.series.append(new_value) total = sum(self.series) return total/len(self.series)
>>> 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 >>> avg(12) 11.0
nonlocal关键字
def make_averager(): count = 0 total = 0 def averager(new_value): count += 1 total += new_value return total / count return averager
>>> avg = make_averager() >>> avg(10) Traceback (most recent call last): ... UnboundLocalError: local variable "count" referenced before assignment >>>
The problem is that the statement count += 1 actually means the same as count = count + 1, when count is a number or any immutable type. So we are actually assigning to count in the body of averager, and that makes it a local variable. The same problem affects the total variable.
We did not have this problem in the example because we never assigned to the series list, we only called series.append and invoked sum and len on it. So we took advantage of the fact that lists are mutable. But with immutable types like numbers, strings, tuples etc., all you can is read, but never update. If you try to rebind them, as in count = count + 1, then you are implicitly creating a local variable count. It is no longer a free variable, therefore it is not saved in the closure.
To work around this the nonlocal declaration was introduced in Python 3. It lets you flag a variable as a free variable even when it is assigned a new value within the function. If a new value is assigned to a nonlocal variable, the binding stored in the closure is changed.
def make_averager(): count = 0 total = 0 def averager(new_value): nonlocal count, total count += 1 total += new_value return total / count return averager带参数的装饰器
def use_logging(level): def decorator(func): def wrapper(*args, **kwargs): if level == "warn": logging.warn("%s is running" % func.__name__) elif level == "info": logging.info("%s is running" % func.__name__) return func(*args) return wrapper return decorator @use_logging(level="warn") def foo(name="foo"): print("i am %s" % name) foo()Stacked decorators
@d1 @d2 def f(): print("f") # equivalent to def f(): print("f") f = d1(d2(f))
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/38388.html
摘要:作者按每天一个设计模式旨在初步领会设计模式的精髓,目前采用和两种语言实现。诚然,每种设计模式都有多种实现方式,但此小册只记录最直截了当的实现方式原文地址是每天一个设计模式之装饰者模式欢迎关注个人技术博客。 作者按:《每天一个设计模式》旨在初步领会设计模式的精髓,目前采用javascript和python两种语言实现。诚然,每种设计模式都有多种实现方式,但此小册只记录最直截了当的实现方式...
摘要:作者按每天一个设计模式旨在初步领会设计模式的精髓,目前采用和两种语言实现。诚然,每种设计模式都有多种实现方式,但此小册只记录最直截了当的实现方式原文地址是每天一个设计模式之装饰者模式欢迎关注个人技术博客。 作者按:《每天一个设计模式》旨在初步领会设计模式的精髓,目前采用javascript和python两种语言实现。诚然,每种设计模式都有多种实现方式,但此小册只记录最直截了当的实现方式...
阅读 1435·2021-09-22 16:04
阅读 2799·2019-08-30 15:44
阅读 887·2019-08-30 15:43
阅读 765·2019-08-29 15:24
阅读 1844·2019-08-29 14:07
阅读 1134·2019-08-29 12:30
阅读 1728·2019-08-29 11:15
阅读 2740·2019-08-28 18:08