将self传递给decorator对象

时间:2015-09-16 15:57:35

标签: python decorator python-2.x python-decorators

有这样的装饰对象

class wait_for_page_load(object):

    def __init__(self, driver, time_to_wait=20):
        self.driver = driver
        self.time_to_wait = time_to_wait

    def __call__(self, function):
        @functools.wraps(function)
        def wrapper(*args):
            old_page = self.driver.find_element_by_tag_name('html')
            function(*args)
            WebDriverWait(self.driver, self.time_to_wait).until(staleness_of(old_page))
        return wrapper

我想将它应用于另一个类的方法,如下所示:

class VehiclePage(object):

    def __init__(self, driver):
        self.driver = driver

    @wait_for_page_load(self.driver)
    def open(self):
        self.driver.get('%s/vehicles/' % BASE_URL)

这给了我一个错误。有没有办法将self.driver传递给装饰者?

2 个答案:

答案 0 :(得分:3)

您不必将self传递给装饰器对象。如果装饰器返回一个函数,那么该函数将在调用时访问self。例如

def pass_value(function):
    def wrapper(self):
        function(self, self.value)
    return wrapper

class Printer(object):
    def __init__(self, value):
        self.value = value

    @pass_value
    def print_(self, v):
        print v

Printer("blah").print_()

此方法的一个问题是它需要self来实现特定的接口(例如,有一个名为driver的字段,而不是直接将驱动程序传递给装饰器。)

你的装饰师会变成:

def wait_for_page_load(time_to_wait=20):
    def decorator(function):
        @functools.wraps(function)
        def wrapper(self, *args):
            old_page = self.driver.find_element_by_tag_name('html')
            function(self, *args)
            WebDriverWait(self.driver, time_to_wait).until(staleness_of(old_page))
        return wrapper
    return decorator

用作:

@wait_for_page_load() # brackets are needed
def open(self):
    ...

答案 1 :(得分:0)

简答:没有。

答案很长: 实例化类时设置driver属性。但是,在解释类时会运行装饰器。也就是说,当解释器在加载模块时首先读取它。此时,您还没有准备好任何实例。要做这种事情,你必须重构你的代码。

此外,即使这样可行,您最终也会为所有对象使用装饰器类的单个实例。可能不是你所期望的。

但是,一个简单的解决方法可能是在__init__中应用装饰器。虽然不是很优雅,但如果您真的需要应用装饰器,那就可以了。

def __init__(self, driver):
    self.driver = driver
    self.open = wait_for_page_load(self.driver)(self.open)

但是我相信你需要通过调用types来自己将包装器绑定到类.MethodType - 老实说,你可能更好地重新组织你的代码。