python静态变量计数器_Python:静态变量装饰器

I'd like to create a decorator like below, but I can't seem to think of an implementation that works. I'm starting to think it's not possible, but thought I would ask you guys first.

I realize there's various other ways to create static variables in Python, but I find those ways ugly. I'd really like to use the below syntax, if possible.

@static(x=0)

def f():

x += 1

print x

f() #prints 1

f() #prints 2

I don't care if the implementation of static is long or hackity, as long as it works like above.

I created this version, but it only allows a . syntax, which gets cumbersome pretty quickly with longer function and variable names.

def static(**assignments):

def decorate(func):

for var, val in assignments.items():

setattr(func, var, val)

return func

return decorate

Various things I thought of, but couldn't get to work were:

Changing f (the decorated function) into a callable class, and somehow storing the static vars in self transparently.

Modifying the globals of f() inside the decorator, and somehow inserting 'global x' statements into the code for f.

Changing f into a generator where we bind the variables by hand and then execute f's code directly.

解决方案

Here is a decorator that seems to work.

Note that this requires return locals() at the end of the function due to being unable to set locals from the outside (I don't have much experience programming so if there is a way, I don't know it).

class Static(object):

def __init__(self, **kwargs):

self.kwargs = kwargs

def __call__(self, f):

def wrapped_f():

try:

new_kwargs = {}

for key in self.kwargs:

i = getattr(f, key)

new_kwargs[key] = i

self.kwargs = new_kwargs

except:

pass

for key, value in f(**self.kwargs).items():

setattr(f, key, value)

return wrapped_f

@Static(x=0, y=5, z='...')

def f(x, y, z):

x += 1

y += 5

print x, y, z

return locals()

The output would be:

>>> f()

1 10 ...

>>> f()

2 15 ...

>>> f()

3 20 ...

EDIT:

I found something at http://code.activestate.com/recipes/410698/ and decided to try adding it to this. It works without the return now.

EDIT again: Changed to to make it a few seconds faster.

Edit 3; changed to function instead of class

def static(**kwargs):

def wrap_f(function):

def probeFunc(frame, event, arg):

if event == 'call':

frame.f_locals.update(kwargs)

frame.f_globals.update(kwargs)

elif event == 'return':

for key in kwargs:

kwargs[key] = frame.f_locals[key]

sys.settrace(None)

return probeFunc

def traced():

sys.settrace(probeFunc)

function()

return traced

return wrap_f

tested:

@static(x=1)

def f():

x += 1

global_x = 1

def test_non_static():

global global_x

global_x += 1

print 'Timeit static function: %s' % timeit.timeit(f)

print 'Timeit global variable: %s' % timeit.timeit(test_non_static)

output:

Timeit static function: 5.10412869535

Timeit global variable: 0.242917510783

Using settrace slows it down quite drastically.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值