【问题标题】:how to make a decorator function to be part of class如何使装饰器功能成为类的一部分
【发布时间】:2019-05-14 10:12:44
【问题描述】:

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

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

【问题讨论】:

  • eio 在这种情况下指的是什么?定义函数时会应用装饰器(因此当 Python 找到 def ... 语句并执行它时)。在类体内,这意味着还没有类对象,更不用说该类的实例了。
  • 另外,self.eio.wait() blocks,你不想在类的 __init__ 方法中使用它。

标签: python class decorator


【解决方案1】:

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

你有两个选择:

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

    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 返回对绑定方法的引用(调用它将具有 @ 987654331@ 传入)。 @.... 装饰器语法只是语法糖,您没有 使用它。 engineio.Client.on() method 接受处理程序作为第二个参数,但您也可以使用 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() method 会阻塞,它不会返回,直到连接结束。您通常不会将这种调用放在类的 __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()

【讨论】:

  • @JoshKatz:很高兴能帮上忙!如果您觉得它对您有用,请随时 accept my answer。 :-)
猜你喜欢
  • 2022-01-09
  • 2011-04-16
  • 1970-01-01
  • 2011-02-14
  • 2011-01-30
  • 1970-01-01
  • 2017-05-13
  • 2015-05-25
  • 1970-01-01
相关资源
最近更新 更多