Python使用self作为参数

-3 投票
2 回答
611 浏览
提问于 2025-04-17 08:43

我有两个类,一个是处理图形界面的 GUI = GUI(),另一个是处理客户端连接到我的 server = Client()。所以,我的错误报告是:

TypeError: change_state() takes exactly 2 arguments (1 given)

GUI()change_state() 方法中有一个 self 参数,而我从 Client() 中调用 GUI.change_state('NORMAL')

但是如果在 change_state() 中没有 self 这个参数,我就无法通过 self 调用 GUI 类中的其他函数。而且把 GUI.change_state() 改成 GUI().change_state 每次都会调用 GUI 的初始化方法 __init__

我希望你能明白我说的这些。

代码:

#!/usr/bin/python
import socket
import time
import tkinter
import threading
from tkinter import *

root = Tk()
root.geometry("363x200")
root.resizable(0,0)
root.title("Emsg")
b1 = None
b2 = None
class Client:
    def __init__(self, host='localhost', port=5000):
##        global b1
##        global b2
##        global b3
        try:
            self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.server_socket.connect((host, port))
            time.sleep(0.5)
            GUI.set_info("Connected...")
            self.boool = True
            self.gotten = ""
            self.data = ""
            GUI.change_state('NORMAL') <<<<<<<<< Problem
            threading.Timer(1.0, self.listen).start()
        except socket.error as error:
            self.boool = False
            GUI.set_info(str(error)[14:])
##        except:
##            self.boool = False
##            GUI.set_info("An unknown error occured")


    def leave(self):
        self.boool = False
        self.server_socket.close()
        GUI.change_state('DISABLED')
        GUI.set_info("You have left the chat")
        GUI.set_v("", "")
        self.data = ""

    def listen(self):       
        while self.boool:
            try:
                time.sleep(0.1)
                self.data = self.server_socket.recv(512)
                if self.data == bytes('quit', 'UTF-8'):
                    self.leave()
                    GUI.set_info("Server has left the chat")
                    GUI.set_v("", "")
                elif self.data != self.gotten:
                    GUI.set_v("Server:", self.data, True)
                    self.gotten = self.data
            except socket.error:
                self.leave()


    def send(self, message=''):
        self.server_socket.send(bytes(message, 'UTF-8'))
        GUI.set_v("Client:", message)
        GUI.reset_cmsg()


class GUI:
    def __init__(self):
        self.client = None
        self.setup_buttons()

    def setup_buttons(self):
        global b1
        global b2
        global b3
        b1 = Button(root, text="Send", width=8, state=DISABLED, command=self.send)
        b1.grid(row=0, column=2)
        b2 = Button(root, text="Leave", width=8, state=DISABLED, command=self.leave)
        b2.grid(row=0, column=3)
        b3 = Button(root, text = "Connect", width = 8, command = self.connect)
        b3.grid(row = 0, column = 4)

    def connect(self):
        self.client = Client()
        self.first = True

    def leave(self):
        if self.client:
            self.client.leave()

    def send(self):
        if self.client:
            self.client.send(textEntry.get())

    def set_v(name, value, encoding=False):
        if encoding:
            v.set("%s: %s\n%s" % (name, str(value, 'UTF-8'), v.get()))
        else:
            v.set("%s: %s\n%s" % (name, value, v.get()))
        if name == "":
            v.set("")


    def change_state(self, _state):
        global b1
        global b2
        global b3
        if _state == 'DISABLED':
            b1.config(state=DISABLED)
            b2.config(state=DISABLED)
            b3.config(command=self.connect) <<<<<<<< Problem if changedto GUI().connect
            b3.config(text="Connect")
            textEntry.config(state=DISABLED)
        elif _state == 'NORMAL':
            b1.config(state=NORMAL)
            b2.config(state=NORMAL)
            b3.config(command=self.leave)
            b3.config(text="Disconnect")
            textEntry.config(state=NORMAL)

    def set_info(value):
        info.set(value)

    def reset_cmsg():
        c_msg.set("")












v = StringVar()
info = StringVar()
c_msg = StringVar()

Label(root, text="Enter: ").grid(row=0, column=0)
textEntry = Entry(root, state=DISABLED, textvariable=c_msg)
textEntry.grid(row=0, column=1)
statusField = Label(root, textvariable=info, wraplength=200)
statusField.grid(row=1, column=0, columnspan=5, sticky="w")
msgField = Message(root, textvariable=v, width=330, fg="blue")
msgField.grid(row=2, column=0, columnspan=5, sticky="w")

GUI()

root.mainloop()

2 个回答

0

你把 change_state 函数当成类的方法来调用了。

(可以看看这个链接: http://docs.python.org/library/functions.html#classmethod

但是它其实不是这样,你也不能把它变成这样,因为它引用了 self:

b3.config(command=self.connect) <<<<<<<< Problem if changedto GUI().connect

所以你应该在一个实例上调用 change_state

gui = GUI()
gui.change_state('DISABLED') 
2

你的问题有点模糊,不过我能理解的是,你在尝试在GUI类上调用change_state这个类方法。这样做是行不通的,你应该先创建一个GUI对象,然后再在这个对象上调用change_state方法:

gui = GUI()
gui.change_state('NORMAL')

撰写回答