python-3.x 使用知道“self”状态的装饰器

bfrts1fy  于 2023-01-22  发布在  Python
关注(0)|答案(1)|浏览(140)

简而言之,我有一个DataFormatter类,它有两种可能的状态:traininfer,它们的作用应该与许多具有fittransform函数的sklearn库类似:如果mode是train,我想在self.metadata中存储一个函数调用和参数的列表,这样它们就可以在infer时按顺序逐字地重新应用。
所以至少,我有:

import inspect

class DataFormatter:
    def __init__(self, mode, data=None):
        self.data = data
        self.metadata = []

    # The decorator function: broken, but something like--
    def meta(self, f, *args):
        def wrapper(*args):
            return f(*args)

        if self.mode == 'train':
            print('caching metadata')
            meta = {
                f.__name__: {
                    param: arg for param, arg in zip(
                        inspect.getfillargspec(f).args, args)}}
            self.metadata.append(meta)
        return wrapper

    @meta
    def drop(self, cols):
        self.data = self.data.drop(cols)

如果我用途:

formatter = DataFormatter('train', my_data)
formatter.drop(['col1', 'col5'])
print(formatter.metadata)

...我想得到:[{'drop': {'cols': ['col1', 'col5']}}]
我尝试了self的各种排列和放置,并将装饰器func完全拉到类之外,但到目前为止还没有成功。
@kindall说:“你不能在装饰的时候得到self,因为装饰器是在函数定义的时候应用的。事实上,该类还不存在。”(Possible to create a @synchronized decorator that's aware of a method's object?),所以甚至不确定这是否可能...

mzsu5hc0

mzsu5hc01#

"看到" self的是 * decorated * 函数--它由你称为"wrapper"的函数表示:

import inspect

# The decorator function: should be out of the class body

def meta( f): ,
    def wrapper(self, *args):
        # call the decorated function:
        # (but you could run other code, including inspecting
        # and modifying arguments, here as well)
        result = f(self, *args)
        # now, your original method had run, and you have
        # access to self:
        if self.mode == 'train':
            print('caching metadata')
            meta = {
                f.__name__: {
                    param: arg for param, arg in zip(
                        inspect.getfillargspec(f).args, args)}}
            self.metadata.append(meta)
        return result
    return wrapper

class DataFormatter:
    def __init__(self, mode, data=None):
        self.data = data
        self.metadata = []

    @meta
    def drop(self, cols):
        self.data = self.data.drop(cols)

那会有用的。

相关问题