创建一个保存方法输入的装饰器 - 返回'NoneType'对象不可调用

问题描述 投票:4回答:2

我目前正在使用无服务器解决方案(ML -engine),我需要不时地在云存储中保存进程的数据帧。为此,我创建了名为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

为什么我会收到此错误?

python decorator python-decorators
2个回答
4
投票

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

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)

2
投票

您的代码存在缩进问题。你返回func的方式也是错误的。以下代码应该适合您:

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):
        for arg in args:
           if type(value) == 'pandas.core.frame.DataFrame':
               save_current_data_frame_to_track( value, 'some_file')
        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)
© www.soinside.com 2019 - 2024. All rights reserved.