Python类中的内部装饰器
我想在Python类中创建一个内部装饰器,用它包装selenium框架的输入和输出操作。所以我试了一下:Python类中的内部装饰器,python,python-3.x,oop,decorator,python-decorators,Python,Python 3.x,Oop,Decorator,Python Decorators,我想在Python类中创建一个内部装饰器,用它包装selenium框架的输入和输出操作。所以我试了一下: class MyPage(object): # ... def framed(self, frame_query: str): def decorator(function): @functools.wraps(function) def wrapper(*args, **kwargs):
class MyPage(object):
# ...
def framed(self, frame_query: str):
def decorator(function):
@functools.wraps(function)
def wrapper(*args, **kwargs):
frame = self.driver.find_element(By.XPATH, frame_query)
self.driver.switch_to.frame(frame)
out = function(*args, **kwargs)
self.driver.switch_to.default_content()
return out
return wrapper
return decorator
# ...
@framed('//myxpath/iframe')
def framed_function(self):
# ...
但是我收到了这个错误:
TypeError: framed() missing 1 required positional argument: 'frame_query'
显然,它需要2个参数,包括self,但在decorator上下文中,它对self一无所知,因此我必须在“framed_function”中定义和内部函数,这使得解决方案不那么优雅:
# My workaround
def framed_function(self):
@framed('//myxpath/iframe')
def actual_framed():
#...
actual_framed()
建议?为类定义方法时,还没有类对象。当然,还没有该类的实例,因此
self
也没有绑定到任何一个类。相反,方法在查找实例对象时绑定到实例,请参见。只需从decorator返回一个将被绑定的新函数对象
此外,Python没有隐私模型,因此也没有“内部”的概念(对于类、方法或任何东西)。只需将您的decorator放在类之外,这将使维护和重用变得更简单,并避免污染类API
这意味着您的wrapped()
函数将成为一个方法,并在绑定时传递self
参数。使用它,并显式地将其传递给包装函数对象(因为该函数未绑定):
因此
framed()
返回decorator()
,它反过来用于修饰framed_函数()
;这样做会返回wrapper()
,它被添加到实际生成的MyPage
类对象中。在MyPage()
的实例上,访问instance.framed\u function()
将wrapper()
绑定到该实例,以便self
绑定到该实例
对象。在wrapper
中,您可以作为self
访问实例,以及原始函数
对象(未绑定)和框架查询
字符串。为类定义方法时,还没有类对象。当然,还没有该类的实例,因此self
也没有绑定到任何一个类。相反,方法在查找实例对象时绑定到实例,请参见。只需从decorator返回一个将被绑定的新函数对象
此外,Python没有隐私模型,因此也没有“内部”的概念(对于类、方法或任何东西)。只需将您的decorator放在类之外,这将使维护和重用变得更简单,并避免污染类API
这意味着您的wrapped()
函数将成为一个方法,并在绑定时传递self
参数。使用它,并显式地将其传递给包装函数对象(因为该函数未绑定):
因此
framed()
返回decorator()
,它反过来用于修饰framed_函数()
;这样做会返回wrapper()
,它被添加到实际生成的MyPage
类对象中。在MyPage()
的实例上,访问instance.framed\u function()
将wrapper()
绑定到该实例,以便self
绑定到该实例
对象。在wrapper
中,您可以以self
的身份访问实例,以及原始函数
对象(未绑定)和框架查询
字符串。可以工作,但当您不知道如何将装饰程序添加到对象实例时,肯定会很棘手(我的失败),我将看一看您引用的这篇文章,以了解更多关于此的信息。虽然有效,但当您不知道如何将装饰器添加到对象实例时(我的失败),我将看一看您引用的这篇文章,以了解更多关于此的信息。
def framed(frame_query: str):
def decorator(function):
@functools.wraps(function)
def wrapper(self, *args, **kwargs):
frame = self.driver.find_element(By.XPATH, frame_query)
self.driver.switch_to.frame(frame)
out = function(self, *args, **kwargs)
self.driver.switch_to.default_content()
return out
return wrapper
return decorator
class MyPage(object):
@framed('//myxpath/iframe')
def framed_function(self):