首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在装饰器中实现的Python静态变量不会重置

在装饰器中实现的Python静态变量不会重置
EN

Stack Overflow用户
提问于 2018-07-20 01:40:39
回答 2查看 467关注 0票数 3

我这里有实现静态变量装饰器的代码。但是,我发现如果我多次运行这个函数,每次调用该函数时都不会重新初始化静态变量。

代码语言:javascript
复制
def static_vars(**kwargs):
    def decorate(func):
        for k in kwargs:
            setattr(func, k, kwargs[k])
        return func
    return decorate


@static_vars(count=0)
def rolling_serial(val):
    '''
    For a vector V = [v_1, ..., V_N] returns a serial
    index.

    so for V = [1, 1, 1, 3, 1, 1, 1]
    a resulting vector will be generated
    V_hat = [1, 2, 3, 4, 5, 6, 7]
    '''
    temp = rolling_serial.count
    rolling_serial.count += 1

    return temp

# invoke it like this
from useful import (rolling_serial)

df = <...some dataframe with a column called ts>

self.df['ts_index'] = self.df.ts.apply(rolling_serial)
# Example output a new column, sa: [1, 2, 3, ..., N]

# My issue arises if I run it again
df = <...some dataframe with a column called ts>
self.df['ts_index'] = self.df.ts.apply(rolling_serial)
# output: [N+1, N+2, ...] instead of restarting at 0

如果我重新启动jupyter内核,静态变量就会清除。但我不希望重启内核。有谁可以帮我?

EN

回答 2

Stack Overflow用户

发布于 2018-07-20 01:52:25

你的装饰器只被调用一次,而不是每次调用你的函数时。确实,它是在定义时调用的:

代码语言:javascript
复制
def static_vars(**kwargs):
    def decorate(func):
        for k in kwargs:
            print(kwargs)
            setattr(func, k, kwargs[k])
        return func
    return decorate


@static_vars(count=0)
def rolling_serial(val):
    '''
    For a vector V = [v_1, ..., V_N] returns a serial
    index.

    so for V = [1, 1, 1, 3, 1, 1, 1]
    a resulting vector will be generated
    V_hat = [1, 2, 3, 4, 5, 6, 7]
    '''
    temp = rolling_serial.count
    rolling_serial.count += 1
    return temp

print('---- BEGIN ----')
print(rolling_serial(10))
print(rolling_serial(20))
print(rolling_serial(30))

打印:

代码语言:javascript
复制
{'count': 0}
---- BEGIN ----
0
1
2

您在static_vars()中作为参数的kwargs将成为闭包,并且会在每次调用rolling_serial()时递增。

一种解决方案是通过globals()传递变量:

代码语言:javascript
复制
# This function creates decorator:
def static_vars(**global_kwargs):
    # This is decorator:
    def decorate(func):
        # This function is called every time:
        def _f(*args, **kwargs):
            for k in global_kwargs:
                globals()[func.__name__+'_'+k] = global_kwargs[k]
            return func(*args, **kwargs)
        return _f
    return decorate

@static_vars(count=0, temp=40)
def rolling_serial():
    global rolling_serial_count, rolling_serial_temp

    temp1, temp2 = rolling_serial_count, rolling_serial_temp
    rolling_serial_count += 1
    rolling_serial_temp += 1
    return temp1, temp2

print(rolling_serial()) # prints (0, 40)
print(rolling_serial()) # prints (0, 40)
print(rolling_serial()) # prints (0, 40)
票数 1
EN

Stack Overflow用户

发布于 2018-07-20 09:56:38

@装饰器是一个障碍,因为它的目的是在函数定义时进行一次装饰。

因此,对传入函数进行裁剪并将其简化为setattr关键字args。这是您必须手动完成的工作,去掉了@语法速记。

代码语言:javascript
复制
def static_vars(func, **kwargs):
    for k in kwargs:
        setattr(func, k, kwargs[k])
    return func


def rolling_serial(val):
    temp = rolling_serial.count
    rolling_serial.count += 1
    return temp    

static_vars(rolling_serial, count=0)
print (rolling_serial(3))
print (rolling_serial(3))

#reset it
static_vars(rolling_serial, count=0)
print (rolling_serial(3))

输出:

代码语言:javascript
复制
0
1
0

另外,FWIW,你不使用val,而且dataframe不是紧要关头的,最好只发布rolling_serial的一些预期结果。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51428879

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档