Python: Calling method A from class A within class

2019-05-26 09:37发布

问题:

There are a number of questions that are similar to this, but none of the answers hits the spot - so please bear with me.

I am trying my hardest to learn OOP using Python, but i keep running into errors (like this one) which just make me think this is all pointless and it would be easier to just use methods.

Here is my code:

class TheGUI(wx.Frame):
    def __init__(self, title, size):
        wx.Frame.__init__(self, None, 1, title, size=size)

        # The GUI is made ...

        textbox.TextCtrl(panel1, 1, pos=(67,7), size=(150, 20))
        button1.Bind(wx.EVT_BUTTON, self.button1Click)

        self.Show(True) 

    def button1Click(self, event):
        #It needs to do the LoadThread function!

class WebParser:

    def LoadThread(self, thread_id):
        #It needs to get the contents of textbox!


TheGUI = TheGUI("Text RPG", (500,500))
TheParser = WebParser

TheApp.MainLoop()

So the problem i am having is that the GUI class needs to use a function that is in the WebParser class, and the WebParser class needs to get text from a textbox that exists in the GUI class.

I know i could do this by passing the objects around as parameters, but that seems utterly pointless, there must be a more logical way to do this that doesn't using classes seem so pointless?

Thanks in advance!

回答1:

You seem to have several misconceptions.

  1. You are using methods here. (Did you mean "functions", as in not belonging to a class?)

  2. Classes are not some kind of container or namespace for functionality. They define a data type. The point of having the class WebParser is that you can have more than one WebParser.

  3. In Python, classes are objects too. Right now, you aren't making TheParser be a WebParser; you are making it an alias for the class itself. In other words, TheParser is now equal to "the concept of a web parser", more or less.

  4. Passing parameters around is not "pointless"; it's how you get information between functions. You don't (normally!) pass classes around; you pass around instances of the classes. Whether you use classes or not, you will have fundamentally the same communication problem.

It is very simple to fix this. First off, the WebParser needs to be created, so we take care of that by using its constructor. Next, our instance of TheGUI (a poor name btw - "the" doesn't really belong) needs to know about our instance, so we pass it to the constructor. That way, the instance can keep a reference to it, and use it to call the LoadThread method. It also needs to keep a reference to the textbox, so that this information can be passed along to LoadThread.

It looks like:

class MyGUI(wx.Frame):
    def __init__(self, title, size, loader):
        wx.Frame.__init__(self, None, 1, title, size=size)

        # The GUI is made ...

        textbox.TextCtrl(panel1, 1, pos=(67,7), size=(150, 20))
        self.textbox = textbox
        button1.Bind(wx.EVT_BUTTON, self.button1Click)
        self.loader = loader
        self.Show(True) 

    def button1Click(self, event):
        self.loader.LoadThread(get_thread_id(), self.textbox)


class WebParser:
    def LoadThread(self, thread_id, a_textbox):
        do_something_with(a_textbox)


TheGUI = MyGUI("Text RPG", (500,500), WebParser())

TheApp.MainLoop()


回答2:

The general answer to that problem is called Model View Controller.

The Model is a representation of the data you want to present, in your case the state of the text RPG. The view is the component that handles the actual viewing on the screen. It gets the data it views from the model. The controller handles all input and other events that change the data and the view. This makes it pretty clear which object needs to know which.



回答3:

There is some good sample code of the MVC model applied in wxPython at http://wiki.wxpython.org/ModelViewController