Python 在decorator don';t重置

Python 在decorator don';t重置,python,python-decorators,static-variables,Python,Python Decorators,Static Variables,这里的代码实现了静态变量的装饰器。但是,我发现如果我多次运行这个函数,那么每次调用该函数时静态变量都不会重新初始化 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_

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

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
def static_vars(**kwargs):
def装饰(func):
对于kwargs中的k:
setattr(func,k,kwargs[k])
返回函数
返修
@静态变量(计数=0)
def滚动单元系列(val):
'''
对于向量V=[V_1,…,V_N]返回一个序列
指数
所以对于V=[1,1,1,3,1,1,1,1]
将生成结果向量
V_hat=[1,2,3,4,5,6,7]
'''
温度=滚动\连续计数
滚动_序列计数+=1
返回温度
#像这样调用它
从有用的导入(滚动_序列)
df=
self.df['ts_index']=self.df.ts.apply(滚动序列)
#示例输出一个新列,sa:[1,2,3,…,N]
#如果我再次运行它,我的问题就会出现
df=
self.df['ts_index']=self.df.ts.apply(滚动序列)
#输出:[N+1,N+2,…]而不是在0处重新启动

如果重新启动jupyter内核,静态变量将被清除。但是我更希望不必重新启动内核。有人能帮我吗?

您的装饰程序只被调用一次,而不是每次调用您的函数。确切地说,它在定义时被调用:

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))
印刷品:

{'count': 0}
---- BEGIN ----
0
1
2
static\u vars()
中作为参数的
kwargs
将变为闭包,并随着对
rolling\u serial()
的每次调用而递增

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


@
装饰器是一个阻碍因素,因为它打算在函数定义时装饰一次

因此,在传入函数上修剪它并将其简化为
setattr
关键字args。这是您必须手动执行的操作,减去
@
语法速记

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))
输出:

0
1
0

另外,FWIW,您不使用
val
,数据帧也不是紧密相关的,最好只发布
rolling_serial
的一些预期结果。

我认为您看到的正是我们所期望的。不是每次调用rolling_serial时都执行装饰程序,而是在启动时仅执行一次。由于只有一个函数
rolling\u serial
,因此也只有一个变量
count
。也许,如果您描述了您试图实现的目标,我们可以建议一种替代解决方案?静态变量不应该在每次调用函数时重置。如果你想让它们每次都复位,这就是普通局部变量的作用。为什么要使用此装饰程序?看起来您可能忽略了这样一个事实:
apply
重复调用函数,并且依赖于
count
在这些调用之间不重置。具有函数属性的全局函数看起来不像是作业的工具;一个闭包工厂可能是合适的,但是用
apply
以外的东西创建这个新专栏可能是最好的方法。我正在寻找一个静态变量行为(函数保持状态)的自包含解决方案,因为它们很难发现,而不是我的组织中使用的一个非常典型的模式。试图让它们“正常工作”。感谢关于闭包工厂的建议,我将对此进行研究。如果每次我要生成新序列时都要重新初始化静态变量,您有什么建议?@AaronSoellinger我更新了答案,每次调用修饰函数时都使用globals()设置变量。
0
1
0