Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python类中的内部装饰器_Python_Python 3.x_Oop_Decorator_Python Decorators - Fatal编程技术网

Python类中的内部装饰器

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):

我想在Python类中创建一个内部装饰器,用它包装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,但在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):