如何在两个类之间共享数据
问题
有没有办法让两个类同时互相继承呢?
背景
我现在在做一个Socket服务器项目。在这个项目中,我有两个类,一个是Server
类,另一个是GUI
类。它们的功能很明显。但我显然需要让这两个类能够互相沟通。在程序中,我先声明Socket_Server
类,然后再声明GUI
类。
我之前问过一个类似的问题,如何在Python中访问方法中的函数,但没有得到满意的回答。希望你们能尝试回答这个问题。
代码和错误
在GUI
类中,我有一个文本框叫self.message
。它用于向所有客户端发送消息。我尝试用以下语法来继承这个类:
class Socket_Server(GUI.messageFun):
接下来,GUI
类继承自Socket_Server
-
class GUI(Frame, Socket_Server):
第二个继承GUI(Socket_Server)
是正确的,但第一个继承失败了。
按钮的命令是这个
self.send = Button (self.messageFrame, text = "Send",
command = lambda: new_server.send_cmd())
new_server
是Socket_Server
类的一个实例。
当前的错误信息是:
Socket Created
Socket Bind Complete
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1410, in __call__
return self.func(*args)
File "D:\Python Programs\Sockets\IM Project\Server\Server GUI InDev Class.py", line 129, in <lambda>
command = lambda: new_server.send_cmd())
File "D:\Python Programs\Sockets\IM Project\Server\Server GUI InDev Class.py", line 82, in send_cmd
message = self.message.get("0.0",END)
AttributeError: Socket_Server instance has no attribute 'message'
2 个回答
你遇到的问题是关于面向对象编程的。你需要去了解一下继承是怎么回事,对象之间是如何互动的等等。这些内容比较复杂,没法在一篇文章里全部讲清楚,需要一些经验才能理解。
关于tkinter的一个小提示,Button的command属性是一个引用。这意味着每次点击按钮时,它都会调用那个函数。
self.send = Button (self.messageFrame, text = "Send",
command = new_server.send_cmd())
这段代码的意思是command等于new_server.send_cmd()的结果。
self.send = Button (self.messageFrame, text = "Send",
command = new_server.send_cmd)
而这一段的意思是command等于send_cmd方法的引用。
这个问题的标题和你一开始问的内容有点不同(而且更准确),但都不太符合你想要的。你需要的是让两个不同类的实例进行沟通;这并不是继承的概念。
当你使用继承时,应该问自己每个X是否也是一个Y:
- 每个
Employee
都是Person
吗?是的 - 每个
Person
都是Employee
吗?不是 - 每个
Employee
都是Car
吗?不是
理解了这个概念后,你会发现第三个例子和GUI
与Server
之间的关系最为相似。因为你真正想问的是:
- 一个
GUI
实例是否使用一个Server
对象?
如果答案是“是”,那么服务器应该是你的GUI
类的一个属性。在下面的例子中,你可以看到GUI
调用了Server
对象的方法,而不是反过来:
import Tkinter as tk
import threading
import socket
class Server():
def __init__(self):
self.addresses = [('localhost', 12345)] # All addresses to send data
def sendtoall(self, data):
for address in self.addresses:
self._send(address, data)
def _send(self, address, data):
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(address)
sock.sendall(data)
finally:
sock.close()
class GUI(tk.Tk):
def __init__(self, server):
tk.Tk.__init__(self)
self.server = server
self.entry = tk.Entry(self)
self.button = tk.Button(self, text="Send", command= self.sendmessage)
self.entry.pack()
self.button.pack()
def sendmessage(self):
message = self.entry.get()
threading.Thread(target=self.server.sendtoall, args=(message,)).start()
server = Server()
gui = GUI(server)
gui.mainloop()
编辑:这段代码看起来更像是一个客户端而不是服务器,所以把它改名为更符合你想法的名称(例如,Notifier
)可能是个好主意。