装饰器在运行时传递参数

时间:2017-11-10 15:42:33

标签: python decorator

在python中使用带或不带参数的装饰器有很多问题,但我的情况有点不同。

一般问题

我需要的是一个除了函数本身之外还接受一些参数的装饰器(这个函数是args和kwargs)。但是,这些参数是在声明修饰函数后计算的。

我的具体案例

我编写了许多函数来处理用于机器学习的pd.DataFrame,它们将DF作为输入并返回DF作为输出。在许多情况下,我想在一个DF上调用它们,而不是在多个训练和测试集的串联上。我的动机是我讨厌代码重复,另一种选择是每次调用两次(每组一次)。此外,预处理功能的作者不应该关心用户经常希望一次在2套上使用​​它的事实。

目前的代码如下:

def train_and_test(preprocess):
  def preprocess_wrapper(**kwargs):
    def concat(train, test):
        train['is_train'] = True
        test['is_train'] = False
        return pd.concat([train, test])

    def split(full):
        train = full[full['is_train']]
        test = full[~full['is_train']]
        train = train.drop('is_train', axis=1)
        test = test.drop('is_train', axis=1)
        assert len(full) == (len(train) + len(test))
        return train, test

    train = kwargs['train']
    test = kwargs['test']
    full = concat(train, test)
    processed = preprocess(full)
    return split(processed)

return preprocess_wrapper

@train_and_test # I would like to pass train and test as arguments here but these are loaded by client code
def my_preprocessor(df):
  preprocessed = do_something_smart(df)
  return preprocessed

我想要什么

我希望此代码的客户端能够调用定义的函数 通过将火车和测试装置传递给装饰器来获得一个DF。像这样:

train, test = pd.read_csv('data/train.csv'), pd.read_csv('data/test.csv')

train, test = preprocess(train, test) # In reality preprocess signature expects one DF but user can now treat it like it accepted 2

1 个答案:

答案 0 :(得分:0)

我们需要更深入!

装饰器只是一个对函数进行操作的函数。

那么,为什么不编写一个返回函数操作函数的函数呢?

def paramizer(*args):
    def normal_decorator(f):
        ...stuff that uses the decorator args to customize behavior...
        def wrapper():
            ...stuff decorating f...
            return f()
        return wrapper
    return normal_decorator

@paramizer(arg1, arg2) #=> returns a customized decorator and applies it to function
def function()