首页 > 解决方案 > 创建一个保存方法输入的装饰器 - 返回“NoneType”对象不可调用

问题描述

我目前使用的是无服务器解决方案(ML 引擎),我需要不时将进程的数据帧保存在云存储中。为此,我创建了名为的方法save_current_data_frame_to_track,我想将其转换为装饰器,如下所示:

import numpy as np
import pandas as pd

def save_current_data_frame_to_track(current_data_frame, filename):
    current_data_frame.to_csv(filename + '.csv')
    pass

def save_input_to_track(func):
    def func_wrapper(*args, func):
        for arg in args:
            for key, value in locals():
                if type(value) == 'pandas.core.frame.DataFrame':
                    save_current_data_frame_to_track( value, key)
            return (func)
        return func_wrapper

rp = pd.DataFrame(data={'time_delta_from': [60, 90, 170],
                                'time_delta_to': [30, 60, 120]},
                        index=[1, 2, 3], dtype=np.int32)

@save_input_to_track
def add_1(data):
    data['time_delta_from'] = 1
    return data

add_1(rp)

这给了我以下错误:

 add_1(rp)
TypeError: 'NoneType' object is not callable

为什么我会收到此错误?

标签: pythondecoratorpython-decorators

解决方案


我建议你使用包装,在这里阅读有关如何获取包装函数参数的详细信息。看起来你的代码应该是:

import numpy as np
import pandas as pd
from functools import wraps

def save_current_data_frame_to_track(current_data_frame, filename):
    current_data_frame.to_csv(filename + '.csv')

def save_input_to_track(func):
    @wraps(func)
    def func_wrapper(*args, **kwargs):
        for arg in args:
            if isinstance(arg, pd.core.frame.DataFrame):
                save_current_data_frame_to_track(arg, 'somefile')
        return func(*args)
    return func_wrapper

rp = pd.DataFrame(data={'time_delta_from': [60, 90, 170],
                        'time_delta_to': [30, 60, 120]},
                  index=[1, 2, 3], dtype=np.int32)

@save_input_to_track
def add_1(data):
    data['time_delta_from'] = 1
    return data

add_1(rp)

对于作为文件名的键名,我认为简单的解决方案是使用 kwarg,这里示例:

import numpy as np
import pandas as pd
from functools import wraps

def save_current_data_frame_to_track(current_data_frame, filename):
    current_data_frame.to_csv(filename + '.csv')

def save_input_to_track(func):
    @wraps(func)
    def func_wrapper(*args, **kwargs):
        for key, kwarg in kwargs.items():
            if isinstance(kwarg, pd.core.frame.DataFrame):
                save_current_data_frame_to_track(kwarg, key)
        return func(*args, **kwargs)
    return func_wrapper

rp = pd.DataFrame(data={'time_delta_from': [60, 90, 170],
                        'time_delta_to': [30, 60, 120]},
                  index=[1, 2, 3], dtype=np.int32)

@save_input_to_track
def add_1(data1, data2):
    data1['time_delta_from'] = 1
    data2['time_delta_from'] = 2
    return data1, data2

add_1(data1=rp, data2=rp)

推荐阅读