zoukankan      html  css  js  c++  java
  • javascript的闭包计数器实现,python实现各种方法来实现计数器

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

    
    
    
  • 相关阅读:
    SparkSQL访问Hive源,MySQL源
    SparkStreaming算子操作,Output操作
    JVM 配置常用参数和常用 GC 调优策略
    SparkStreaming与Kafka,SparkStreaming接收Kafka数据的两种方式
    consul service
    Centos7 vnc
    Centos7 創建快捷方式
    Consul Session
    python consul
    python 形参
  • 原文地址:https://www.cnblogs.com/ydf0509/p/8064464.html
Copyright © 2011-2022 走看看