【问题标题】:Python using self as an argument [closed]Python使用self作为参数[关闭]
【发布时间】:2012-01-24 14:52:57
【问题描述】:

我有两个类,一个处理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()

【问题讨论】:

  • 我该如何解决这个困境?顺便说一句,其他人可以编辑我的帖子吗?由于我没有写()init(),所以我写了init :O
  • 显然我遇到了一个错误,这需要解决。我已经提出了不起作用的解决方法。

标签: python class arguments self


【解决方案1】:

你调用 change_state 函数,因为它是一个类方法

(见:http://docs.python.org/library/functions.html#classmethod

然而事实并非如此,而且你不能这样做,因为它引用了自我:

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

    【讨论】:

    • 不,我在 Client 类上调用 change_state 类方法,如果您查看 GUI 上的方法 connect,我已经完成了您所说的操作,我正在实例化 self.client = Client() ,你是说我应该在顶层调用 gui = GUI() 然后在 GUI 中全局调用它?
    • 您应该将显示 GUI() 的那一行更改为 gui = GUI(),然后将所有方法调用从 GUI.method() 替换为 gui.method()。另外,请检查 bpgergo 答案中的链接。
    • 这就是我尝试过的,它确实奏效了,谢谢。虽然我没有说:全局 gui,但是当从 GUI 类中调用顶级变量时,它确实有效。这只是一个好奇的问题.. :)
    • 没错,只有当你要为全局变量赋值时才需要全局语句。参考见:docs.python.org/release/2.4/ref/global.html.
    猜你喜欢
    • 1970-01-01
    • 2012-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-04
    • 1970-01-01
    • 2023-03-07
    • 2021-03-12
    相关资源
    最近更新 更多