在python中实现对C++中函数内static静态变量的模拟
在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函数时,都会经过一次装饰器的装饰
- 下面这个例子我们使用了一个闭包hello_decorator装饰器,去装饰传入的函数function_to_be_used
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

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。
更多推荐
所有评论(0)