简体   繁体   English

在类中使用装饰器访问self中的属性

[英]Using decorator in a class to access an attribute in self

I have a class which provides some generic structure for a sequential data processing pipeline. 我有一个为顺序数据处理管道提供一些通用结构的类。 I would like to time the execution of a method, and save that to a dictionary attribute of self ( self.timings ). 我想定时执行一个方法,并将其保存到self( self.timings )的字典属性中。

from functools import wraps
import time

class Pipeline(object):

    def __init__(self):
        self.steps = {}
        self.timings = {}

    # Decorator for adding functions to pipeline
    def step(self, step_name):
        def step_decorator(f):
            self.steps[step_name] = f
        return step_decorator

    # Decorator for timing a step
    def time_step(f):
        @wraps(f)
        def timed(*args, **kwargs):
            start = time.time()
            result = f(*args, **kwargs)
            end = time.time()
            self.timings[f.__name__] = end - start
            return result
        return timed

    @time_step
    def example_method(self):
        if 'example_func' in self.steps:
            self.output = self.steps['example_func']()

I can instantiate a Pipeline and add a step to it: 我可以实例化管道并向其添加一个步骤:

pipeline = Pipeline()

@pipeline.step('example_func')
def example_func():
    for i in range(10000):
        pass
    return 'Completed!'

But when I attempt to run pipeline.example_method() , it cannot access self : 但是当我尝试运行pipeline.example_method() ,它无法访问self

pipeline.example_method()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-54-8204774a5649> in <module>()
----> 1 pipeline.example_method()

<ipython-input-51-ffb2e95a110a> in timed(*args, **kwargs)
     21             result = f(*args, **kwargs)
     22             end = time.time()
---> 23             self.timings[f.__name__] = end - start
     24             return result
     25         return timed

NameError: name 'self' is not defined

I have tried adding self to the parameters in the time_step definition, but that causes another error. 我尝试将self添加到time_step定义中的参数,但这会导致另一个错误。 Is there a straightforward way of accessing attributes from a decorated method? 有没有一种从修饰方法访问属性的简单方法?

Your @time_step() decorator is not a bound method, when @time_step runs, it is just a function object. 您的@time_step()装饰器不是绑定方法,当@time_step运行时,它只是一个函数对象。 No self is defined in the function, nor is it defined in the wrapper that this decorator returns. 在函数中没有定义self ,在此装饰器返回的包装器中也没有定义self

If you use time_step() only on methods, then you can count on the returned wrapper function being bound (it's just another function object in the class body in that case, so is treated like any other function attached to a class and looked up on the instance): 如果仅在方法上使用time_step() ,则可以依靠返回的包装器函数进行绑定(在这种情况下,它只是类主体中的另一个函数对象,因此与附加到类的任何其他函数一样对待,并在其上查找实例):

def time_step(f):
    @wraps(f)
    def timed(self, *args, **kwargs):
        start = time.time()
        result = f(self, *args, **kwargs)
        end = time.time()
        self.timings[f.__name__] = end - start
        return result
    return timed

Note that you do have to pass the self argument on to the f() call, since f is also not bound. 请注意,由于f也未绑定,因此必须将self参数传递给f()调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM