Python 将decorator参数传递给内部函数

Python 将decorator参数传递给内部函数,python,python-decorators,Python,Python Decorators,我正在继续学习python。但我有一些想法,但面临着实施问题。 我正在使用硒,当然,对于每种元素,我都有多种情况,如: submit_btn = (By.XPATH, "//button[@type='submit']") revert_btn = (By.XPATH, "//button[@class='revert']") 这让我很恼火,因为我总是通过.CSS_选择器或xpath复制。 我想制作一个decorator,它接受path参数,并且默认设置

我正在继续学习python。但我有一些想法,但面临着实施问题。 我正在使用硒,当然,对于每种元素,我都有多种情况,如:

submit_btn = (By.XPATH, "//button[@type='submit']")
revert_btn = (By.XPATH, "//button[@class='revert']")
这让我很恼火,因为我总是通过.CSS_选择器或xpath复制。 我想制作一个decorator,它接受path参数,并且默认设置为“css”的参数 并用于操纵WebDriver,如:

@by("[data-qa='selected']")
def save_form(self):
   self.find_element().click()
我的方法find_元素如下所示:

 def find_element(self, locator, time=10):
        try:
            el = WebDriverWait(self.browser, time).until(ec.presence_of_element_located(locator),
                                                         message=f"Can't find elements by locator {locator}")
            return el
        except TimeoutException:
            return False
        except StaleElementReferenceException:
            return WebDriverWait(self.browser, time).until(ec.staleness_of(locator),
                                                           message=f"Can't find element by locator {locator}")
或者另一种方式。 我试图创建一个装饰器,比如:

def by(selector, what="css", data_qa=True):
    def inner_function(function):
        def wrapper(param):
            if what == "css":
                find_by = By.CSS_SELECTOR
            elif what == "xpath":
                find_by = By.XPATH
            if data_qa:
                path = (find_by, f"[data-qa='{param}']")
            else:
                path = (find_by, selector)
            return function(path)

        return wrapper

    return inner_function
如果能把它用作

@by('selected')
def get_selected_el(self)
   # set path returned by decorator to find element method
   self.find_element(smth_returned_by_decorator)
所以我想将定位器作为装饰器实现传递。
如何做到这一点?

这样做的一种可能方法是在修饰函数中包含一个参数,该参数在修饰器返回的函数中不公开:

#自动转发参数的装饰程序
def自动参数(参数):
def装饰器(f):
def包装器(自身):
f(自我,参数)
返回包装器
返回装饰器
类别MyClass:
def方法1(自身、参数):
打印(参数)
@自动参数('method2值')
def方法2(自身、参数):
self.method1(参数)
#试验
obj=MyClass()
#调用method2不需要参数
目标方法2()
#方法2值

看起来像是一场维护噩梦,因为方法定义似乎需要一个参数,但调用时却不需要。非常混乱。@barny嗯,是的,这是一个缺点,您需要设计一些东西,以便清楚地知道这是“框架”提供的“特殊”参数,或者只是将其正确地记录在方法docstring中。Python中的几个web框架使用类似的思想将GET或POST数据转换为函数参数(尽管通常以这种方式修饰的函数不是由用户直接调用的,而是由web框架本身调用的)。似乎您希望的是,您的装饰程序将无形中为装饰函数提供一个恒定的附加参数-我不清楚这是怎么可能的。也许只需在函数定义中提供该参数,如
def get_selected_el(self,by='selected'):
,它实际上输入更少、更清晰,并且可以在调用时重写。是的,谢谢,也许我想在java中使用smth,但看起来像是Crunchs。我认为在函数中设置keyarg是一个好主意。如果函数都是类的方法,那么装饰器可以将class属性设置为装饰器的参数。但是,这似乎比在函数定义中指定带有默认值的附加参数要复杂得多。装饰师不是万能的,也不是万能的。