【参考】:http://python.jobbole.com/81683/
【参考】:https://www.cnblogs.com/lianyingteng/p/7743876.html
1、闭包函数:
(1)闭包概念
i、如果内部函数里引用了外部函数里定义的变量,那么此时内部函数就称为闭包函数。闭包函数所引用的外部定义变量(非全局变量)叫做自用变量。闭包可以将自己的代码和作用域以及外部函数结合使用。
def count():
a, b = 1, 1
def sum():
c = 1
return a + b + c
return sum
(2)自由变量赋值
i、闭包中的如果给“自由变量”直接赋值,会导致其变成局部变量,在调用到get_avg函数时,会提示变量未被定义
def make_avg():
count = 0
total = 0
def get_avg(new_value):
count +=1
total += new_value
return total/ count
return get_avg
avg = make_avg()
avg(10)
/// 执行结果
Traceback (most recent call last):
File "D:/Richard/Test/test001.py", line 13, in <module>
avg(10)
File "D:/Richard/Test/test001.py", line 6, in get_avg
count +=1
UnboundLocalError: local variable 'count' referenced before assignment
Process finished with exit code 1
ii、“自由变量”的赋值,在python3中引入了nonlocal声明, 可以在闭包内把变量count标记为“自由变量”:
def make_avg():
count = 0
total = 0
def get_avg(new_value):
nonlocal count, total
count +=1
total += new_value
return total/ count
return get_avg
avg = make_avg()
avg(10)
2、函数装饰器
python装饰器本质上就是一个函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外的功能,装饰器的返回值也就是,必须是一个函数的对象。装饰器函数的外部函数传入我要装饰的函数名字,返回经过修改后的函数名字;内部函数(闭包)负责修饰装饰函数:
- 实质:一个函数;
- 参数:是你要装饰的函数名(并非函数调用,[缺少()])
- 返回:是装饰完的函数名(非函数调用)
- 作用:为已经存在对象添加额外的功能;
- 特点:不需要对对象做任何的代码上的改动
- 执行:在函数执行前就会被调用、 函数装饰器在导入模块时会被立即执行,而被装饰的函数,只有在调用的时候才会执行
{装饰器的最大作用,定义一些基本的功能,然后再需要调用借本功能的函数前使用}
class Coordinate: def __init__(self, x, y): self.x = x self.y = y def __repr__(self): return "Coord:" + str(self.__dict__) def wrapper(func): def checker(a, b): if a.x < 0 or a.y < 0: a = Coordinate(a.x if a.x > 0 else 0, a.y if a.y > 0 else 0) if b.x < 0 or b.y < 0: b = Coordinate(b.x if b.x > 0 else 0, b.y if b.y > 0 else 0) ret = func(a, b) if ret.x < 0 or ret.y < 0: ret = Coordinate(ret.x if ret.x > 0 else 0, ret.y if ret.y > 0 else 0) return ret return checker @wrapper def add(a, b): return Coordinate(a.x + b.x, a.y + b.y) @wrapper def sub(a, b): return Coordinate(a.x - b.x, a.y - b.y) if __name__ == "__main__": coor_a = Coordinate(-100, 200) coor_b = Coordinate(100, -200) print(add(coor_a,coor_b))
3、类装饰器:
类似于函数装饰器,只不过应用场景是类,用于管理类自身或拦截类实例创建等;
# --coding='utf-8'-- #单实例管理 instances = {} def getInstance(aClass, *args): if aClass not in instances: instances[aClass] = aClass(*args) return instances[aClass] def singleton(aClass): def onCall(*args): return getInstance(aClass, *args) return onCall @singleton class Person: def __init__(self, name, hours, rate): self.name = name self.hours = hours self.rate = rate def pay(self): return self.hours * self.rate @singleton class Spam: def __init__(self, val): self.attr = val if __name__ == "__main__": bob = Person('Bob', 40, 10) print(bob.name, bob.pay()) sue = Person('sue', 50, 20) print(sue.name, sue.pay()) X = Spam(42) Y = Spam(22) print(X.attr, Y.attr)
# -- coding:utf-8 -- #跟踪对象接口 def Tracer(aClass): class Wrapper: def __init__(self, *args, **kargs): self.fetchers = 0 self.wrapped = aClass(*args, **kargs) def __getattr__(self, attrname): print('Trace:' + attrname) self.fetchers += 1 return getattr(self.wrapped, attrname) return Wrapper @Tracer class Spam: def display(self): print('spam' * 8) @Tracer class Person: def __init__(self, name, hours, rate): self.name = name self.hours = hours self.rate = rate def pay(self): return self.hours * self.rate if __name__ == "__main__": food = Spam() food.display() print(food.fetchers) bob = Person('Bob', 12, 22) print(bob.name, bob.pay()) sue = Person('Sue', 10, 27) print(sue.name) print(bob.fetchers) print(sue.fetchers)