菜鸟教程的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的默认值参数只会在函数定义处被解析一次,此后每次调用函数的时候,默认值参数都会是这个值了。
这个笔试很爱考这个陷阱,可以利用这个笔试陷阱,来实现计数器。
笔试通常如下:

												

javascript的闭包计数器实现,python实现各种方法来实现计数器的更多相关文章

  1. javascript中用闭包递归遍历树状数组

    做公司项目时,要求写一个方法,方法的参数为一个菜单数组集合和一个菜单id,菜单数组的格式为树状json,如下面所示: [{"id":28,"text":&quo ...

  2. Javascript的闭包及其使用技巧实例

    Javascript的闭包及其使用技巧实例 一.闭包的基本概念 闭包(Closure)是一个引用了自由变量的函数,记录了该函数在定义时的scope chain.又称词法闭包(Lexical Closu ...

  3. 深入理解JavaScript的闭包特性如何给循环中的对象添加事件

    初学者经常碰到的,即获取HTML元素集合,循环给元素添加事件.在事件响应函数中(event handler)获取对应的索引.但每次获取的都是最后一次循环的索引.原因是初学者并未理解JavaScript ...

  4. JavaScript作用域闭包简述

    JavaScript作用域闭包简述 作用域 技术一般水平有限,有什么错的地方,望大家指正. 作用域就是变量起作用的范围.作用域包括全局作用域,函数作用域以块级作用域,ES6中的let和const可以形 ...

  5. JavaScript的闭包原理

    什么是js(JavaScript)的闭包原理,有什么作用? 一.定义 官方解释:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分. 个人的理解是 ...

  6. Js(javaScript)的闭包原理

    问题?什么是js(javaScript)的闭包原理,有什么作用? 一.定义 官方解释:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.  小编 ...

  7. 深入理解javascript的闭包

    闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域 ...

  8. 如何给循环中的对象添加事件--深入理解JavaScript的闭包特性

    初学者经常碰到的,即获取HTML元素集合,循环给元素添加事件.在事件响应函数中(event handler)获取对应的索引.但每次获取的都是最后一次循环的索引.原因是初学者并未理解JavaScript ...

  9. javascript,jquery(闭包概念)(转)

    偶尔听人说javascript闭包,让我联想起以前学编译原理和数字逻辑里讲的闭包,以前上课讲的闭包很难懂,而且含有递归的意思在里面,现在不想再查看里面的闭包概念. 但javascript我是经常要用, ...

随机推荐

  1. 【jquery】ajax 请求成功后新开窗口被拦截解决方法

    问题: 前面开发项目时碰到一个问题,ajax 异步请求成功后需要新开窗口打开 url,使用的是 window.open() 方法,但是很可惜被浏览器给拦截了,怎么解决这个问题呢? 分析: 浏览器之所以 ...

  2. svn出现skips remain conficted,不能更新代码问题

    出现: skips remain conficted One or more files are in a conflicted state 然后commit的时候出现,很多都已经deleted,但是 ...

  3. JAVA多线程笔试题

    一.题目内容 二.我的答案 利用了线程池.考虑了超时处理.不知道这样写是否还有其他问题,或者更好更优的解决方案? import java.util.*; import java.util.concur ...

  4. 浅谈跨域以WebService对跨域的支持

    跨域问题来源于JavaScript的同源策略,即只有 协议+主机名+端口号 (如存在)相同,则允许相互访问.也就是说JavaScript只能访问和操作自己域下的资源,不能访问和操作其他域下的资源. 在 ...

  5. [hadoop读书笔记] 第九章 构建Hadoop集群

    P322 运行datanode和tasktracker的典型机器配置(2010年) 处理器:两个四核2-2.5GHz CPU 内存:16-46GN ECC RAM 磁盘存储器:4*1TB SATA 磁 ...

  6. 【Python】#!/usr/bin/python 作用

    脚本语言的第一行,目的就是指出,你想要你的这个文件中的代码用什么可执行程序去运行它 #!/usr/bin/python是告诉操作系统执行这个脚本的时候,调用/usr/bin下的python解释器.#! ...

  7. (笔记)Mysql实例:建库建表并插入数据1

    drop database if exists school;  // 如果存在school则删除create database school;  // 建立库schooluse school;  / ...

  8. Java数组扩展

    Java中,数组初始化后如何扩展数组? 示例 以下示例显示如何在创建新并初始化数组后扩展数组. package com.yiibai; public class ExtendingArray { pu ...

  9. (转) 解密H264、AAC硬件解码的关键扩展数据处理

    出自:http://blog.itpub.net/30168498/viewspace-1576794/       通过上一篇文章,我们用ffmpeg分离出一个多媒体容器中的音视频数据,但是很可能这 ...

  10. Linux CPU Load Average

    理解Linux系统负荷 LINUX下CPU Load Average的一点研究 Linux load average负载量分析与解决思路 Understanding Linux CPU Load - ...