【发布时间】:2021-03-22 00:15:51
【问题描述】:
在我创建的类中使用导入包中的装饰器时遇到问题。我创建了两个类和一个main()。 class A 的实例在main() 中创建,class B 的实例在class A 中创建。 Class B 需要更新在main() 中创建的实例的属性。此外,我需要使用导入包中的装饰器。
我不知道如何解决无法从class B 实例中的装饰confirm_connect 函数引用main() 中创建的实例的属性的问题。我让它工作的唯一方法是将main()中创建的实例声明为global并删除class B中的所有self引用。但是,将其设为 global 会导致我的应用程序出现其他问题。 (在class B 中将socketio 的实例设置为global 是可以容忍的,但我也不想拥有它。)
函数confirm_connect 接收来自服务器的消息。如果我将函数定义为def conform_connect(self, data),则会收到错误消息connect_confirm() missing 1 required positional argument: 'data'/。如果我从声明中删除self,则会收到错误NameError: name 'self' is not defined。
这是我的脚本。我怎样才能让我的脚本做我需要它做的事情?
import socketio
class A():
def __init__(self):
self.pin = None
def connect_to_server(self):
self.io = B()
self.io.connect_to_server()
def start_the_process(self):
self.b = B(self)
self.b.connect_to_server()
def do_something_with_pin(self):
print(self.pin)
class B():
global sio
sio = socketio.Client()
def __init__(self, a):
self.a = a
def connect_to_server(self):
sio.connect('http://my_url_is_this.org')
sio.emit('manual_connection_parameter', {'foo': 'bar'})
@sio.event
def connect_confirm(data):
self.a.pin = data
self.a.do_something_with_pin()
def main():
a = A()
a.start_the_process()
if __name__ == '__main__':
main()
【问题讨论】:
-
停止思考类和实例。我们称其为面向对象的编程,而不是面向类的编程,这是有原因的。您的
Binstance 是由您的A实例的方法创建的,它需要能够与该Ainstance 进行交互;因此,它需要知道它是哪一个。因此,它需要某种参考。比如你传递给B.__init__的那个,当你做self.b = B(self)时。该系统应该可以正常工作。只需始终如一地应用它;有什么问题? -
发现你遇到的实际问题是在定义
connect_confirm(是connect_confirm,还是confirm_connect?你需要注意这些事情;如果您在谈论代码时给函数起不同的名称,而不是在实际编写代码时,这表明您的注意力不集中)以符合socketio模块的期望的方式。 -
那么 - 当您阅读文档时发生了什么?似乎它期望
@sio.event装饰一个普通的函数,而不是一个实例方法。它有没有说什么?它是否提出了任何解决方法? -
global sio在类定义中没有任何意义。 -
现在我已经写了一个答案,我意识到这实际上是一个关于一般技术的非常好的问题,答案是“只有在你是荷兰人时才明显”。它可能出现在很多其他情况下,这让我想以更一般的方式来写它,所以我有一个很好的重复目标....
标签: python socket.io decorator