在python中实现对C++中函数内static静态变量的模拟

问题抛出

  • 本文旨在解决C,C++语言中静态变量在python里头实现的方法
    void func()
    {
        static counter=0;
        counter+=1;
        std::cout<<counter<<std::endl;
    }
    

结果预览

def static_vars(**kwargs):
    '''模拟一个静态变量'''
    def decorate(func):
        for k in kwargs:
            setattr(func, k, kwargs[k])
        return func
    return decorate

@ static_vars(couter=0)
def func():
    func.couter+=1
    print(f'couter:{func.couter}')

前置知识

1.全局变量global关键字(Global Variables)
  • 概念:在函数外创建的变量被认为是全局变量
  • 当你在函数内部创建一个和全局变量相同名字的变量时候,这时类内的变量被认为是(local)局部的变量,修改类内这个和全局变量相同名字的变量不会更改全局的变量
    var="hello world"
    
    def fun():
        var="bye bye world"
        print(f'fun.var():{var}')
    if __name__ == '__main__':  
    fun()
    # 结果仍然是"hello world"
    print(f'global.var:{var}')
    
  • 然而这时候如果我们引入关键字global修饰函数内的和全局变量相同名字的变量,这时候内部的变量就和全局相同
    var="hello world"
    
    def fun():
        global var="bye bye world"
        print(f'fun.var():{var}')
    if __name__ == '__main__':  
    fun()
    # 结果是"bye bye world"
    print(f'global.var:{var}')
    
    
2.嵌套函数(Nested function in Python)
  • 概念:当一个函数内部又进行另一个函数的定义时,通常被认为时嵌套函数
    
    # nested functions  
    def outerFunction(text):  
        text = text  
        
        def innerFunction():  
            print(text)  
        
        innerFunction()  
        
    if __name__ == '__main__':  
        outerFunction('Hey !')
    # 只有当外层函数被调用时,内部函数才会被调用
    
  • 关于在内部函数访问外部函数的变量时候,会发生什么?
    def outerFunction(): 
        s = 'I love CJLU'
        
        def innerFunction(): 
            s= 'I don\'t like CJLU'
            print(f'inner:{s}') 
            
        innerFunction()
        print(f'outter:{s}') 
    
    if __name__ == '__main__': 
        outerFunction() 
    
  • 这时候上述函数的输出outter的s仍为I love CJLU,说明内嵌函数(inner function)使用的变量s是一个局部的变量,这一点和上一条函数直接修改和全局变量同名的函数时一样的
  • 当然也是由几个方法可以使内嵌函数修改外部函数内的变量值
    • 修改可迭代对象如字符串
    • 使用nonlocal关键字修饰内嵌函数的变量为非局部变量
3.闭包(closure)
  • 概念:在一个内部函数中,对外部作用域的变量进行引用,(并且一般外部函数的返回值为内部函数),那么内部函数就被认为是闭包。
    def outerFunction(text): 
    
        def innerFunction(): 
            print(text) 
    
        # 返回内部函数,注意不要带括号!!
        # 关于这里返回innerFunction的使用请见底下的First Class Objects的说明
        return innerFunction  
    
    if __name__ == '__main__': 
        myFunction = outerFunction('Hey!') 
        myFunction() 
    
  • 上述代码解释了闭包的作用,我们通过使用闭包,将原本作用域只存在于outerFunction的innerFunction的作用域扩展到outerFunction函数的作用域之外,使innerFunction可以在外部被调用。闭包的作用是允许一个函数记住并访问其词法作用域,即使函数在其词法作用域之外执行。
  • 那么闭包有上面作用呢?
    • 它允许我们在函数中封装数据,然后嵌套函数可以使用这些数据。这种封装有助于减少对全局变量的需求,因为数据隐藏在闭包中,只能由嵌套函数访问。(相当于把函数当作一个类来实现)
    def counter(start):
        count = start
    
        def increment():
            nonlocal count
            count += 1
            return count
    
        return increment
    
    if __name__ == '__main__': 
    my_counter = counter(0)
    print(my_counter())  # 输出: 1
    print(my_counter())  # 输出: 2
    print(my_counter())  # 输出: 3
    
4.第一类对象(First Class Objects)
  • 概念:First Class Objects是指在py里,函数可以被作为一个参数使用或者传递
    • 作为值传递
      def fun(test):
          print(test)
      if __name__=='__main__':
          fun('hellom world')
          tmp=fun 
          tmp('hellom world')
      
    • 作为参数传递
      def fun1(test):
          print(f'fun1'+test)
      def fun2(test):
          print(f'fun2'+test)
      def use_fun(func):
          tmp=fun('hello world')
          tmp()
      if __name__=='__main__':
          use_fun(fun1)
          use_fun(fun2)
      
5.装饰器(decorator)
  • 概念:装饰器其实就是一种闭包,用于修改函数或类的行为。
    • 下面这个例子我们使用了一个闭包hello_decorator装饰器,去装饰传入的函数function_to_be_used
      # defining a decorator
      def hello_decorator(func):
          
          def inner1():
              print("Hello, this is before function execution")
              # 第5步调用function_to_be_used
              func()
              print("This is after function execution")
          # 第2步略过内嵌函数,直接返回inner1    
          return inner1
      def function_to_be_used():
          # 第5步调用function_to_be_used
          print("This is inside the function !!")
      
      if __name__=='__main__':
          # 第1步调用hello_decorator
          # 第3步function_to_be_used=inner1 
          function_to_be_used = hello_decorator(function_to_be_used)
          # 第4步调用function_to_be_used--->调用inner1
          function_to_be_used()
          # 第6步执行完function_to_be_used
      
    • 上述过程演示了解释器的底层原理,那么我们现在直接使用解释器的语法
      @hello_decorator
      def fun():
          print('hello world')
      # 这样每次执行fun函数时,都会经过一次装饰器的装饰
      
6.可变参数(*args & **kwargs)
  • 概念:一个可变参数函数是指一个函数拥有不定引数,即是它接受一个可变量目的参数。一个例子你就能明白
  • *args:以元组的形式存储多个参数
    def display_num(*args):
        for arg in args:
            print(arg)
    if __name__=='__main__':
        num1=10
        num2=100
        num3=100
        display_num(mode,num1)
        display_num(mode,num1,num2)
        display_num(mode,num1,num2,num3)
    
  • **kwargs:以字典的形式存储多个参数
    def greet_me(**kwargs):
        for key, value in kwargs.items():
            print("{0} = {1}".format(key, value))
    if __name__=='__main__':
        greet_me(name="yasoob")
    
7.setattr()函数
  • 作用:用于设置对象的属性值。API如下
    setattr(object, name, value)
    

实战

  • 上述的前置知识相信能使你看得懂接下来的代码
    def static_vars(**kwargs):
        '''模拟一个静态变量'''
        def decorate(func):
            for k in kwargs:
                setattr(func, k, kwargs[k])
            return func
        return decorate
    
    @ static_vars(couter=0)
    def func():
        func.couter+=1
        print(f'couter:{func.couter}')
    if __name__ == '__main__':
        for i in range(6):
             func()
    
  • 这样上述main函数运行时,每次执行func(),都会被装饰器static_vars装饰,且装饰器static_vars使用字典的形式存储传入的变量
  • 每次装饰时会把上一次存储的值赋值给couter,使couter可以实现模拟函数内静态变量的作用
参考链接
  • https://www.w3schools.com/python/python_variables_global.asp
  • https://www.geeksforgeeks.org/python-inner-functions/
  • https://www.programiz.com/python-programming/closure
  • https://www.geeksforgeeks.org/decorators-in-python/
  • https://book.pythontips.com/en/latest/args_and_kwargs.html
  • 43
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值