首页 > 解决方案 > 如何使装饰器功能成为类的一部分

问题描述

我希望这些函数成为我正在构建的类的一部分,但我得到一个错误装饰器函数可能是部门中的一个函数。有解决问题的方法吗?谢谢你。

import engineio

class Websocket:

    def __init__(self):
        self.eio = engineio.Client()
        self.eio.connect('http://localhost:5000')
        self.eio.wait()

    # get error in this function       
    @eio.on('connect')
    def on_connect():
        print('connection established')

标签: pythonclassdecorator

解决方案


您不能在装饰器表达式引用实例属性的方法上使用装饰器。那是因为装饰器是在创建它们装饰的函数时执行的。在class语句体内部,这意味着当应用装饰器时,还没有类,没有类,也不能有任何实例。

你有两个选择:

  • 只需调用你self.eio.on('connect')__init__类,传入一个绑定方法:

    class Websocket:
    
        def __init__(self):
            self.eio = engineio.Client()
            self.eio.connect('http://localhost:5000')
            self.eio.on('connect', self.on_connect)
            # don't call wait, see below
    
        def on_connect(self):
            print('connection established')
    

    这是有效的,因为在__init__被调用时,您已经拥有了一个类和该类的一个实例(由 引用self),并self.on_connect返回对绑定方法的引用(调用它会self传入)。@....装饰器语法只是语法糖,您不必使用它。该engineio.Client.on()方法接受处理程序作为第二个参数,但您也可以使用self.eio.on('connect')(self.on_connect),它是装饰器语法的字面翻译。

  • 在 内部使用嵌套函数__init__,并装饰它:

    class Websocket:
    
        def __init__(self):
            self.eio = engineio.Client()
            self.eio.connect('http://localhost:5000')
    
            @self.eio.on('connect')
            def on_connect():
                print('connection established')
    
            # don't call wait, see below
    
    
    but that makes it much harder to use that function directly from other code. 
    

请注意,该engineio.Client.wait()方法阻塞,它不会返回,直到连接结束。您通常不会将这种调用放在类的__init__方法中!

使用类来处理engineio事件很好,但不要从类中启动客户端连接。我会这样做:

class Websocket:
    def __init__(self, socket_url):
        self.eio = engineio.Client()
        self.eio.connect(socket_url)
        self.eio.on('connect', self.on_connect)
        # other registrations

    def on_connect(self):
        # handle connection

    # other handlers

    def wait(self):
        self.eio.wait()

websocket = Websocket('http://localhost:5000)
websocket.wait()

推荐阅读