Python class 中的内部装饰器
Inner decorators in Python class
我想在我的 Python class 中使用它创建一个内部装饰器来包装 selenium 框架切换进出操作。所以我尝试了这个:
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 但在装饰器上下文中它对 self 一无所知,所以我不得不在 ´framed_function´ 中定义和内部函数使解决方案很多不太优雅:
# My workaround
def framed_function(self):
@framed('//myxpath/iframe')
def actual_framed():
#...
actual_framed()
建议?
在为 class 定义方法时,还没有 class 对象。当然还没有 class 的实例,所以 self
没有任何东西可以绑定到 或者 。相反,方法在实例对象上查找时绑定到实例,请参阅 Python descriptor HOWTO。只是 return 来自装饰器的新函数对象将被绑定。
此外,Python 没有隐私模型,因此也没有 'inner' 的概念(对于 classes 或方法或任何东西)。只需将你的装饰器放在 class 之外,这样更易于维护和重用,并避免污染你的 class API.
这意味着您的 wrapped()
函数将成为一个方法,并且在绑定时将传递给 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):
所以framed()
returnsdecorator()
,进而用来修饰framed_function()
;这样做 returns wrapper()
,它被添加到实际生成的 MyPage
class 对象中。然后,在 MyPage()
的实例上,访问 instance.framed_function()
会将 wrapper()
绑定到该实例,因此 self
将绑定到该 instance
对象。在 wrapper
中,您可以作为 self
访问实例,以及原始 function
对象(未绑定)和 frame_query
字符串。
我想在我的 Python class 中使用它创建一个内部装饰器来包装 selenium 框架切换进出操作。所以我尝试了这个:
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 但在装饰器上下文中它对 self 一无所知,所以我不得不在 ´framed_function´ 中定义和内部函数使解决方案很多不太优雅:
# My workaround
def framed_function(self):
@framed('//myxpath/iframe')
def actual_framed():
#...
actual_framed()
建议?
在为 class 定义方法时,还没有 class 对象。当然还没有 class 的实例,所以 self
没有任何东西可以绑定到 或者 。相反,方法在实例对象上查找时绑定到实例,请参阅 Python descriptor HOWTO。只是 return 来自装饰器的新函数对象将被绑定。
此外,Python 没有隐私模型,因此也没有 'inner' 的概念(对于 classes 或方法或任何东西)。只需将你的装饰器放在 class 之外,这样更易于维护和重用,并避免污染你的 class API.
这意味着您的 wrapped()
函数将成为一个方法,并且在绑定时将传递给 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):
所以framed()
returnsdecorator()
,进而用来修饰framed_function()
;这样做 returns wrapper()
,它被添加到实际生成的 MyPage
class 对象中。然后,在 MyPage()
的实例上,访问 instance.framed_function()
会将 wrapper()
绑定到该实例,因此 self
将绑定到该 instance
对象。在 wrapper
中,您可以作为 self
访问实例,以及原始 function
对象(未绑定)和 frame_query
字符串。