菜鸟教程的javascript闭包章节中,演示了js计数器的实现。    教程地址 http://www.runoob.com/js/js-function-closures.html

代码1

var add = (function(){
var counter = 0;
return function(){
return counter += 1;}
})(); add();
add();
add();

大概感觉会输出 1 2 3,但是第一次看的时候看得马马虎虎。

代码中用了匿名函数 闭包 自调用。教程中说要保持避免计数器的变量在全局被其他代码修改,就不使用全局变量了。

如果全局变量实现计数器就很简单了。

代码2

var counter = 0;

function add() {
return counter += 1;
} add();
add();
add();

但还是需要理解闭包,计数器是个好例子。

在第一段代码中

var add变量指向外层函数的自调用,自调用以后,通过外层函数里面的return,add就指向了内层函数的函数名。

那么执行 add()就是执行内层函数了,所以会实现加1的功能,同时又能不使用全局变量。

把js第一段闭包代码翻译成python闭包代码就是这样

代码3

def outer():
counter = 0
def inner():
nonlocal counter
counter += 1
return counter
return inner add = outer()
print(add())
print(add())
print(add())

使用全局变量,把js第二段代码翻译成python是

代码4

counter= 0

def func():
global counter
counter += 1
return counter print (func())
print (func())

细心的就会发现python中还是与js区别了一点点,加了global nonlocal修饰,如果去掉这会是个python中很经典的错误

UnboundLocalError: local variable 'counter' referenced before assignment

这个不是本篇要讨论的啦,但还是说下,在python中函数访问局部变量是不需要特意去声明global的,但如果在函数中修改了那个变量,比如给变量赋值,那么就会把该变量当做成是局部变量了,但当成局部变量时候却没有初始化,所以会报错,这点需要注意。

在py2总没有nonlcal修饰符

可以这样做,可以使用字典对象什么的。

代码5

def outer():
counter = {0:0}
def inner():
# nonlocal counter counter[0] += 1
return counter[0]
return inner add = outer()
print(add())
print(add())
print(add())

闭包总难以理解的,很蛋疼有没有。

不就是要消全局吗,可以使用类来实现。实例属性在类的所有实例方法中(非staticmethod和classmethod)可以访问。

代码6

class Couter():
def __init__(self):
self.x = 0
def add(self):
self.x += 1
return self.x c = Couter()
print(c.add())
print(c.add())
print(c.add())

这样做,既不需要全局变量,也不需要闭包了,很容易理解。

如果使用函数又不闭包。可以这样做,这样避开了闭包,又避开了py2不支持 nonlocal语法

代码7

def func():
if not hasattr(func,'counter'):
func.counter = 0
else:
func.counter += 1
return func.counter print (func())
print (func())

总之就是避免一个问题啦,函数的局部变量每次都初始化,需要用全局变量。c语言中有静态变量修饰符,很容易解决这个计数器。

代码8

int f(){
static i=0;
i++;
return i;
}
f()
f()

在c语言中,可以通过加入static修饰符来声明静态变量,如果去掉static修饰符不管调用多少次函数都是返回0.。

闭包写起来很麻烦,但调用起来很实用。

如果是实现一个计数器,我认为使用类,就是代码6的方法比较好。这样还能很方便再在内中写个减数函数啥的,很容易扩展到其他的功能。

最后再加一种python方式,利用函数可变类型的默认参数

def add(l=[0]):
l[0] += 1
return l[0] print add()
print add()
print add() python的默认值参数只会在函数定义处被解析一次,此后每次调用函数的时候,默认值参数都会是这个值了。
这个笔试很爱考这个陷阱,可以利用这个笔试陷阱,来实现计数器。
笔试通常如下:

												

最新文章

  1. 三分钟集成elmah xml 格式日志到mvc站点
  2. .net core 学习笔记(2)-中间件
  3. Nodejs学习(四)- express目录的分析
  4. Struts2获取Session方法
  5. QT下实现对Linux Shell调用的几种方法
  6. hdu 5092 Seam Carving
  7. 关于ALTERA生成IP核卡住
  8. MD5加密工具
  9. Raspiberry Camera详解+picamera库+Opencv控制
  10. C语言 字符串前加L的意义 如:L“A”
  11. kubernetes 手绘画,先收藏一下
  12. 源码推荐:移动端商城(微信小程序源代码) WebView离线缓存
  13. Objective-C RunTime 学习笔记 之 atomic/nonatomic 关键字
  14. Docker技术应用场景(转载)
  15. API setContentType(MIME) 参数说明
  16. Chapter5_初始化与清理_成员初始化
  17. 强制ubuntu登陆用户退出
  18. [UE4]把枪打飞addImpulse
  19. JUC知识点总结图
  20. 了不起的Node.js--之一

热门文章

  1. Spark算子总结(带案例)
  2. Linux文本编辑器(九)
  3. Publishing to IIS 发布到IIS
  4. librtmp编译for android and ios 不要openssl
  5. 安装Nginx+Lua+OpenResty开发环境配置全过程实例
  6. 漂亮的圆角文本框 CSS3实现
  7. 关于Unity中的声音管理模块(专题七)
  8. Netty 介绍
  9. Java Management Extensions (JMX) - Best Practices 最佳实践
  10. css3 -- 自动生成序号(不使用JS,可任意排序)