69 lines
1.7 KiB
Python
69 lines
1.7 KiB
Python
# 我们有时候可以用函数来拓展闭包,使闭包获得类似类的效果
|
||
def sample():
|
||
n = 0
|
||
|
||
def func():
|
||
print("n=", n)
|
||
|
||
def get_n():
|
||
return n
|
||
|
||
def set_n(value):
|
||
# nonlocal让我们可以访问闭包内的变量,有点类似类里的self
|
||
nonlocal n
|
||
n = value
|
||
# 我们能这么做的本质原因还是因为Python里的万物皆类特性
|
||
func.get_n = get_n
|
||
func.set_n = set_n
|
||
return func
|
||
|
||
|
||
f = sample()
|
||
f()
|
||
# 可以看到这里并没有出现代码提示,因为基类没有包含这些东西,它们是在动态编译的时候加入的
|
||
f.set_n(10)
|
||
f()
|
||
f.get_n()
|
||
|
||
import sys
|
||
# 比如下面有个类
|
||
class ClosureInstance:
|
||
def __init__(self, locals=None):
|
||
if locals is None:
|
||
locals = sys._getframe(1).f_locals
|
||
self.__dict__.update((key, value) for key, value in locals.items() if callable(value))
|
||
|
||
def __len__(self):
|
||
return self.__dict__['__len__']()
|
||
|
||
# 这是用这个类实现的栈实例
|
||
def Stack():
|
||
items = []
|
||
|
||
def push(item):
|
||
items.append(item)
|
||
|
||
def pop():
|
||
items.pop()
|
||
|
||
def __len__():
|
||
return len(items)
|
||
|
||
return ClosureInstance()
|
||
|
||
# 这是正常的写法
|
||
class Stack2:
|
||
def __init__(self):
|
||
self.items = []
|
||
|
||
def push(self, item):
|
||
self.items.append(item)
|
||
|
||
def pop(self):
|
||
return self.items.pop()
|
||
|
||
def __len__(self):
|
||
return len(self.items)
|
||
|
||
# 从执行来说,闭包的写法比正常写法块8%,因为不需要访问额外的self变量
|
||
# 不!要!这!么!做!除非有非得这样干的理由,否则别这样搞,老老实实写类,这样的闭包只有类的功能而没有继承多态这些类属性 |