在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
答案 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()