如何在Python中从方法访问函数

1 投票
2 回答
663 浏览
提问于 2025-04-17 17:27

问题

在同一个类里,怎么在一个方法中访问另一个函数呢?

背景

你好,世界!我现在正在用Tkinter做一个图形界面的即时通讯程序。为了通过网络发送消息,我需要在方法中访问一些函数。我的 self.network 方法里有一个叫 send_message() 的函数,我想要访问它。

代码

为了访问这个函数,我尝试了以下代码:

def messageFun(self):

    //Other widgets are here//

    self.send = Button (self.messageFrame, text = "Send",
                        command = self.network(send_message()))
    self.send.grid(row = 1, column = 1, sticky = S)

我的 self.network 方法和 send_message 函数如下:

def network(self):

    def send_message():   
            #Send some data to the remote server
            message = self.message.get("0.0",END)

            try:
                 #set the whole string
                 s.sendall(message)
            except socket.error:
            #Send Failed
                print "Send failed"
                sys.exit()

尽管我努力调试代码,但总是收到这个消息:

Traceback (most recent call last):
  File "D:\Python Programs\Sockets\First Project\IM Project\Server GUI InDev.py", line 178, in <module>
    app = Application(root)
  File "D:\Python Programs\Sockets\First Project\IM Project\Server GUI InDev.py", line 73, in __init__
    self.messageFun()
  File "D:\Python Programs\Sockets\First Project\IM Project\Server GUI InDev.py", line 156, in messageFun
    command = self.network(send_message()))
NameError: global name 'send_message' is not defined

2 个回答

0

如果你想在 network 之外使用 send_message,那么就应该把它放在 network 之外来定义。

def send_message(self):   
    #Send some data to the remote server
    message = self.message.get("0.0",END)

    try:
        #set the whole string
        s.sendall(message)
    except socket.error:
    #Send Failed
        print "Send failed"
        sys.exit()
def network(self):
    #do network stuff...

def messageFun(self):

    //Other widgets are here//

    self.send = Button (self.messageFrame, text = "Send",
                        command = self.send_message)
    self.send.grid(row = 1, column = 1, sticky = S)

如果 send_message 需要用到 network 内部的变量,而 network 现在又没有返回任何东西,那么你可以把 send_message 放在 network 里面定义,并在最后返回它。

def network(self):
    #create the socket needed for send_message
    s = Socket()

    def send_message():   
        #Send some data to the remote server
        message = self.message.get("0.0",END)

        try:
            #set the whole string
            s.sendall(message)
        except socket.error:
        #Send Failed
            print "Send failed"
            sys.exit()

    #do other network stuff...
    return send_message

def messageFun(self):

    //Other widgets are here//

    self.send = Button (self.messageFrame, text = "Send",
                        command = self.network()
    self.send.grid(row = 1, column = 1, sticky = S)

如果 network 已经有返回值了,那么你可以把 network 内部的变量放到类的范围内,这样 send_message 就能访问到这些变量了。

def send_message(self):   
    #Send some data to the remote server
    message = self.message.get("0.0",END)

    try:
        #set the whole string
        self.s.sendall(message)
    except socket.error:
    #Send Failed
        print "Send failed"
        sys.exit()

def network(self):
    #create the socket needed for send_message
    self.s = Socket()
    #do other network stuff

def messageFun(self):

    //Other widgets are here//

    self.send = Button (self.messageFrame, text = "Send",
                        command = self.send_message
    self.send.grid(row = 1, column = 1, sticky = S)
2

network(send_message()) 这个写法看起来有点奇怪,因为它试图去调用 send_message() 这个函数。

我建议可以用下面这种方式:

def send_message(instance):   
        #Send some data to the remote server
        message = instance.message.get("0.0",END)

        try:
             #set the whole string
             s.sendall(message)
        except socket.error:
        #Send Failed
            print "Send failed"
            sys.exit()

def network(self,what,send_message=send_message):
    if what =='send message":
        send_message(self)


self.send = Button (self.messageFrame, text = "Send",
                    command = self.network("send message"))

或者用这种方式:

class NENE:
    def __init__(self):
        self.network.__dict__['send'] = send_message

    def send_message(self):   
        #Send some data to the remote server
        message = self.message.get("0.0",END)
        try:
             #set the whole string
             s.sendall(message)
        except socket.error:
        #Send Failed
            print "Send failed"
            sys.exit()

    def network(self):
        pass


self.send = Button (self.messageFrame, text = "Send",
                    command = self.network.send_message())

在第二段代码中,我在 network() 函数里放了一个 pass,因为我不知道你真正的函数内容是什么,但你可以把你的内容放在这个 pass 的位置。

我把这些方法放在一个叫 NENE 的类里,目的是为了展示它是怎么工作的。因为 send_message() 必须是和 network() 方法属于同一个实例的方法
这样,每次创建一个新实例的时候,send_message() 也会成为 network() 方法的一个属性。
所以,send_message() 既是这个实例的一个属性,也是它的一个方法的属性;不过这并不重要,重要的是它达到了你的目的:send_message() 现在是 network() 的一个属性,可以通过 network 属性来调用,并且它知道自己是为哪个实例工作的。

抱歉我的英语不好。

撰写回答