【问题标题】:Under what circumstances is a class member function not passed self as the first parameter?什么情况下类成员函数不将self作为第一个参数传递?
【发布时间】:2019-03-02 00:29:25
【问题描述】:

问题

我正在使用一个库来促进客户端与服务器的 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

【问题讨论】:

  • .on_open() is 正在传递 self - 请注意,错误消息是在抱怨第二个参数 ws。这完全是由于WebSocketApp 没有使用参数调用该回调。
  • 你用于 websocket 的 pypi 包的链接是什么?
  • 好的,我明白你们在说什么。他们改变了界面。感谢您的帮助

标签: python


【解决方案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>

【讨论】:

    【解决方案2】:

    我可能在这里遗漏了一些基本的东西。

    不,你是正确的。但是,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 尝试中的一个诚实错误。由于没有针对您的特定场景进行测试,因此没有被捕获。

    我已降级到早期版本并修复了我的问题

    请提交错误报告或编写拉取请求以解决问题。

    我的理解是类实例方法总是将self作为第一个参数传递

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-11
      • 1970-01-01
      • 1970-01-01
      • 2017-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-27
      相关资源
      最近更新 更多