更改包变量以更改装饰器行为

2024-05-15 21:20:44 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个包含模块pymetrics.py的包:

from .utils import minSample
MIN_SIZE = 10


@minSample(MIN_SIZE)
def inventory(df):
    '''for quantisation'''
    return len(df)

(以及使用相同装饰器的许多其他指标)

…以及utils.py

def minSample(sample=None):
    def decorator(method):
        @wraps(method)
        def f(*args, **kwargs):
            if len(args[0]) < sample:
                return None
            return method(*args, **kwargs)
        return f
    return decorator

现在,在我的生产代码(包外)中,我想更改最小样本大小(minu-size),以便它将影响所有修饰函数:在特定情况下,我可以将minu-size=0

然而,我不知道怎么做

import pandas as pd
from package import pymetrics as mtr
mtr.MIN_SIZE = 0


test = pd.DataFrame({'price': [10, 20, 10], 'name': ['foo', 'bar', 'baz']})

mtr.inventory(test)
>>> None

Tags: frompyimportnonesizereturndefargs
2条回答

import行完成时,所有函数都已定义。现在改变已经太晚了。然而,您可以做的是更改定义装饰器的方式,以便它可以接受更改。例如,您可以将其设置为一个类:

class minSample:
    MIN_SIZE = 10
    def __init__(self, function):
        self.function = function

    def __call__(self, *args, **kwargs):
        ...

__call__方法中,可以使用self.MIN_SIZEself.function放置所有的装饰器代码。如果要更改MIN_SIZE,只需更改类变量:

minSample.MIN_SIZE = 0

这样,装饰器就不会附加到原始的MIN_SIZE,而是可以在整个代码中根据需要进行多次更新。您甚至可以更新单个函数:

inventory.MIN_SIZE = 5

尽管上面的答案是绝对正确的,但我最终还是使用了带有附加参数的decorator,因为它看起来更透明

def min_sample(f):
    @wraps(f)
    def new_f(df, *args, min_size=2, **kw):
           if len(df) < min_size: return None
           else: return f(df, *args, **kw)
    return new_f

相关问题 更多 >