python中静态变量的作用_函数中静态变量的Python等效项是什么?

这篇博客探讨了如何在 Python 中实现类似于 C/C++ 的静态变量功能,特别是在函数级别。文中给出了多种实现方式,包括使用装饰器、函数内部的 __dict__ 属性、异常处理以及静态变量装饰器。这些方法允许在多次调用同一函数时保持状态。此外,还讨论了在类中使用静态变量的情况,并提供了相关示例。
摘要由CSDN通过智能技术生成

此C / C ++代码的惯用Python等效项是什么?

void foo()

{

static int counter = 0;

counter++;

printf("counter is %d\n", counter);

}

具体来说,如何在函数级别(而不是类级别)实现静态成员? 并将函数放入类中是否会发生任何变化?

#1楼

我个人更喜欢以下装饰器。 给每个人自己。

def staticize(name, factory):

"""Makes a pseudo-static variable in calling function.

If name `name` exists in calling function, return it.

Otherwise, saves return value of `factory()` in

name `name` of calling function and return it.

:param name: name to use to store static object

in calling function

:type name: String

:param factory: used to initialize name `name`

in calling function

:type factory: function

:rtype: `type(factory())`

>>> def steveholt(z):

... a = staticize('a', list)

... a.append(z)

>>> steveholt.a

Traceback (most recent call last):

...

AttributeError: 'function' object has no attribute 'a'

>>> steveholt(1)

>>> steveholt.a

[1]

>>> steveholt('a')

>>> steveholt.a

[1, 'a']

>>> steveholt.a = []

>>> steveholt.a

[]

>>> steveholt('zzz')

>>> steveholt.a

['zzz']

"""

from inspect import stack

# get scope enclosing calling function

calling_fn_scope = stack()[2][0]

# get calling function

calling_fn_name = stack()[1][3]

calling_fn = calling_fn_scope.f_locals[calling_fn_name]

if not hasattr(calling_fn, name):

setattr(calling_fn, name, factory())

return getattr(calling_fn, name)

#2楼

这是一个完全封装的版本,不需要外部初始化调用:

def fn():

fn.counter=vars(fn).setdefault('counter',-1)

fn.counter+=1

print (fn.counter)

在Python中,函数是对象,我们可以通过特殊属性__dict__简单地向其添加或修改成员变量。 内置的vars()返回特殊属性__dict__ 。

编辑:请注意,与替代的try:except AttributeError答案不同,通过这种方法,变量将始终为初始化后的代码逻辑做好准备。 我认为以下方法的try:except AttributeError替代方法将减少DRY和/或具有笨拙的流程:

def Fibonacci(n):

if n<2: return n

Fibonacci.memo=vars(Fibonacci).setdefault('memo',{}) # use static variable to hold a results cache

return Fibonacci.memo.setdefault(n,Fibonacci(n-1)+Fibonacci(n-2)) # lookup result in cache, if not available then calculate and store it

EDIT2:仅当从多个位置调用该函数时,才建议使用上述方法。 相反,如果只在一个地方调用该函数,则最好使用nonlocal :

def TheOnlyPlaceStaticFunctionIsCalled():

memo={}

def Fibonacci(n):

nonlocal memo # required in Python3. Python2 can see memo

if n<2: return n

return memo.setdefault(n,Fibonacci(n-1)+Fibonacci(n-2))

...

print (Fibonacci(200))

...

#3楼

还可以考虑:

def foo():

try:

foo.counter += 1

except AttributeError:

foo.counter = 1

推理:

大量的pythonic( ask for forgiveness not permission )

使用异常(仅抛出一次)而不是if分支(认为StopIteration异常)

#4楼

在这个问题的提示下,我可以提出另一种选择,它可能会更好用,并且对于方法和函数来说都一样:

@static_var2('seed',0)

def funccounter(statics, add=1):

statics.seed += add

return statics.seed

print funccounter() #1

print funccounter(add=2) #3

print funccounter() #4

class ACircle(object):

@static_var2('seed',0)

def counter(statics, self, add=1):

statics.seed += add

return statics.seed

c = ACircle()

print c.counter() #1

print c.counter(add=2) #3

print c.counter() #4

d = ACircle()

print d.counter() #5

print d.counter(add=2) #7

print d.counter() #8

如果您喜欢这种用法,请执行以下操作:

class StaticMan(object):

def __init__(self):

self.__dict__['_d'] = {}

def __getattr__(self, name):

return self.__dict__['_d'][name]

def __getitem__(self, name):

return self.__dict__['_d'][name]

def __setattr__(self, name, val):

self.__dict__['_d'][name] = val

def __setitem__(self, name, val):

self.__dict__['_d'][name] = val

def static_var2(name, val):

def decorator(original):

if not hasattr(original, ':staticman'):

def wrapped(*args, **kwargs):

return original(getattr(wrapped, ':staticman'), *args, **kwargs)

setattr(wrapped, ':staticman', StaticMan())

f = wrapped

else:

f = original #already wrapped

getattr(f, ':staticman')[name] = val

return f

return decorator

#5楼

很多人已经建议测试“ hasattr”,但是答案很简单:

def func():

func.counter = getattr(func, 'counter', 0) + 1

没有try / except,没有测试hasattr,只有默认的getattr。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值