【问题标题】:How to Access Functions from Methods in Python如何从 Python 中的方法访问函数
【发布时间】:2013-02-14 20:21:48
【问题描述】:

问题

在同一个类中,如何从方法中访问函数?

背景

世界你好!我目前正在使用 Tkinter 开发一个 GUI IM 程序。要通过套接字发送消息,我需要从方法访问函数。我的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

【问题讨论】:

  • 你好。我已经更新了我的答案。但是,我认为您遇到了 XY 问题,因为在我看来,您试图以一种不清楚的方式做某事,并且我看到您的用户页面,其中您说 “我刚开始编程"。为什么你认为把一个函数放在一个方法中会给你发送消息的方法?我觉得你们班的概念不好。但是我们看不到您的课程,只有您向我们提出的 Y 问题
  • 第 XY 问题 (meta.stackexchange.com/questions/66377/what-is-the-xy-problem)。在 (mywiki.wooledge.org/XyProblem) 中,我们读到 “有时被称为 XY 问题是一种心理障碍,会导致人们浪费大量时间和精力,无论是在寻求帮助的人,还是在提供帮助的那部分人。”
  • 正如@eyquem 在他的回答中提到并解释的那样,方法中的函数是一种错误的做法。我不确定为什么 Python 甚至允许这样做。仅提取该函数并将其编写为方法然后在您想要的类中的任何位置访问它有什么问题?

标签: python oop sockets tkinter


【解决方案1】:

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

在第二个代码中,我将pass 放在network() 函数中,因为我不知道你的真实函数的内容,但你会用这个内容代替这个pass

我已将这些方法放在一个类 NENE 中以展示它是如何工作的。因为send_message() 必须是与network() 是方法的实例相同的实例的方法
然后,在每次创建新实例时,send_message() 也成为 network() 方法的属性。
因此,send_message() 完全是实例及其方法之一的属性;但没关系,除了它实现了你的目标:send_message() 现在是network() 的一个属性,可以通过network 属性调用,它知道它适用于什么实例。

请原谅我的英语不好

【讨论】:

  • __dict__ 是什么意思?另外,instance 是什么意思?
  • 名为__dict__的属性是表示对象的命名空间的字典,即对象的所有属性与这些属性的标识符(=名称)之间的映射。 Python 大量使用字典来表示命名空间。对Python的理解需要对这方面的理解。指令self.network.__dict__['send'] = send_messagenetwork 的命名空间中创建了一个新属性:将对象send_message 分配给标识符send,该标识符是network 的命名空间键的一部分。
  • @xxmbabanexx instance 只是一个名称,一个标识符。之所以这样命名,是因为必须作为参数传递给函数 send_message() 的对象实际上是您的类的一个实例(您不知道这个类是什么,然后我在第二个代码中将其称为 NENE )。 send_message() 不是第一个代码中的方法,它不在类中,这就是为什么我有权将参数命名为 instance 而不是常见的 self 名称。
【解决方案2】:

如果send_message需要在network之外访问,那么它应该在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 目前没有返回任何内容,那么您可以在network 中定义send_message,并在最后返回。

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)

如果网络已经有返回值,那么你可以把网络的局部变量放在类范围内,这样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)

【讨论】:

  • 问题在于,当我尝试这样做时,未定义套接字。难道没有更简单的方法来做到这一点吗?我可以创建一个 GUI 类继承自的网络类吗??
  • s 是套接字吗?这是在哪里定义的?
  • s 确实是套接字。有什么方法可以让我简单地从方法中访问函数。除此之外,我可以创建两个类,一个GUI 类和一个Network 类,它们在需要发送内容时可以相互访问?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-14
  • 2017-09-08
  • 2019-02-20
  • 2020-11-06
相关资源
最近更新 更多