在什么情况下,类成员函数不将self作为第一个参数传递?

时间:2019-03-01 14:06:24

标签: python

问题

我正在使用一个库来促进客户端Websocket与服务器的通信。

  • websocket库允许您指定套接字打开,关闭,错误或接收消息时的回调函数

  • 如果我将回调函数设置为另一个类的实例函数,则在调用时需要将其传递给 self 参数。

  • 我了解到,如果您调用类实例方法,它将始终以self作为第一个参数传递。但是,我的回调没有通过 self

例如

from websocket import WebSocketApp
import websocket
class X(object):

    def run(self):
        self.ws  = WebSocketApp('wss://api.bitfinex.com/ws/2'
                            ,on_open=self.on_open
                            ,on_message=self.on_message
                            ,on_error=self.on_error
                            ,on_close=self.on_close)
        websocket.enableTrace(True)
        self.ws.run_forever()


    def on_open(self, ws):
        print('open')
    def on_close(self, ws):
        print('close')
    def on_message(self, ws, message):
        print('message')
    def on_error(self, ws, error):
        print('error')


if __name__=='__main__':
    x = X().run()

输出

error from callback <bound method X.on_open of <__main__.X object at 0x7fd7635e87f0>>: on_open() missing 1 required positional argument: 'ws'
  File "/home/arran/.local/lib/python3.6/site-packages/websocket/_app.py", line 343, in _callback
callback(*args)

我可能在这里缺少一些基本知识。但任何帮助将不胜感激

编辑

看起来这可能是websocket-client库https://github.com/home-assistant/home-assistant/issues/17532的特定版本问题

我已降级到较早的版本并解决了我的问题。 我仍然很好奇,但是知道如何发生此问题。我的理解是,类实例方法将始终通过 self 作为第一个参数

2 个答案:

答案 0 :(得分:1)

这似乎是WebSocket类未传递on_open方法期望的ws参数的问题。我尝试用自己的虚拟类重现它,并且效果很好。

class WS:
    def __init__(self, on_call):
        self.on_call = on_call
    def call(self):
        print("hi")
        self.on_call(self)


class X:
    def on_call(self, ws):
        print(ws)
    def run(self):
        self.ws = WS(self.on_call)
        self.ws.call()

X().run()
hi
<__main__.WS instance at 0x029AB698>

答案 1 :(得分:0)

  

我可能在这里缺少一些基本知识。

不,您在现场。但是,on_open回调不会通过ws参数来调用,尽管它应根据文档进行:

class WebSocketApp(object):
    (...)
        on_open: callable object which is called at opening websocket.
          this function has one argument. The argument is this class object.
    (...)

这是一个known bug,尽管围绕它的修复方式进行了一些讨论,但还是关闭了。

  

尽管仍然想知道如何出现此问题,仍会感到好奇。

我想这是bug fix尝试中的一个诚实错误。由于没有针对您的特定情况的测试,因此没有被抓住。

enter image description here

  

我已降级到较早的版本并解决了我的问题

请提交错误报告或提出请求请求以解决问题。

  

我的理解是,类实例方法将始终以自我作为第一个参数传递

是的,您的理解是正确的。这是一个反映您尝试过的示例。

class Server(object):
    def __init__(self, callback):
        self.callback = callback

    def run(self):
        self.callback(5)

class Client(object):
    def on_message(self, n):
        print("got", n)

client = Client()
server = Server(client.on_message)
server.run()