You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改包变量以改变Python装饰器的行为?

解决动态修改装饰器最小样本量不生效的问题

这个问题的核心在于装饰器是在模块加载时就完成绑定的:当你导入pymetrics模块时,@minSample(MIN_SIZE)这行代码会立即执行,此时MIN_SIZE的初始值10被直接“固化”到了装饰器内部的闭包中。之后你修改mtr.MIN_SIZE=0,只是改变了模块级别的变量,但已经装饰好的inventory函数内部,判断条件用的还是最初绑定的10,所以才会依然返回None。

下面给你两种可行的解决方案,你可以根据需求选择:

方案一:用可变对象包装样本量,实现全局统一修改

因为整数是不可变类型,装饰器捕获的是它的值而非引用,我们可以用一个可变容器(比如字典)来存储样本量,这样装饰器每次都会读取容器里的最新值:

步骤1:修改pymetrics.py

把MIN_SIZE改成字典形式,让它成为可变对象:

from .utils import minSample
# 用字典包装样本量,方便后续动态修改
MIN_SIZE = {'value': 10}

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

# 其他使用@minSample的函数也统一改成@minSample(MIN_SIZE)

步骤2:修改utils.py的装饰器

让装饰器读取容器里的value字段,而不是直接使用传入的数值:

from functools import wraps

def minSample(sample_container):
    def decorator(method):
        @wraps(method)
        def f(*args, **kwargs):
            # 每次调用都读取容器里的最新值
            if len(args[0]) < sample_container['value']:
                return None
            return method(*args, **kwargs)
        return f
    return decorator

生产代码中修改样本量

现在你只需要修改字典里的value,所有被装饰的函数都会自动使用新的样本量:

import pymetrics as mtr
# 修改全局最小样本量为0
mtr.MIN_SIZE['value'] = 0
# 此时调用inventory会按新的样本量判断
result = mtr.inventory(test_df)

方案二:给装饰后的函数添加可修改属性,支持单独/批量修改

这种方法更灵活,既可以统一修改所有函数的样本量,也能单独调整某个函数的阈值:

步骤1:修改utils.py的装饰器

给装饰后的函数添加一个可直接修改的min_sample属性:

from functools import wraps

def minSample(sample=None):
    def decorator(method):
        @wraps(method)
        def f(*args, **kwargs):
            # 每次调用读取函数自身的min_sample属性
            if len(args[0]) < f.min_sample:
                return None
            return method(*args, **kwargs)
        # 给装饰后的函数绑定初始样本量
        f.min_sample = sample
        return f
    return decorator

步骤2:pymetrics.py保持原有代码不变

from .utils import minSample
MIN_SIZE = 10

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

生产代码中修改样本量

  • 单独修改某个函数:
import pymetrics as mtr
# 只修改inventory函数的最小样本量
mtr.inventory.min_sample = 0
  • 批量修改所有被装饰的函数:
import pymetrics as mtr
# 遍历模块内所有对象,找到有min_sample属性的函数并修改
for name, func in vars(mtr).items():
    if callable(func) and hasattr(func, 'min_sample'):
        func.min_sample = 0

两种方案对比

  • 方案一适合需要全局统一控制所有函数样本量的场景,修改一次就能生效所有函数;
  • 方案二更灵活,允许对不同函数设置不同的阈值,也支持批量统一修改。

内容的提问来源于stack exchange,提问作者Philipp_Kats

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:04:33