views:

2470

answers:

5

I'm trying to create a character generation wizard for a game. In one class I calculate the attributes of the character. In a different class, I'm displaying to the user which specialties are available based on the attributes of the character. However, I can't remember how to pass variables between different classes.

Here is an example of what I have:

class BasicInfoPage(wx.wizard.WizardPageSimple):            
    def __init__(self, parent, title):
         wiz.WizardPageSimple.__init__(self, parent)
         self.next = self.prev = None
         self.sizer = makePageTitle(self, title)

                    <---snip--->

         self.intelligence = self.genAttribs()

class MOS(wx.wizard.WizardPageSimple):
     def __init__(self, parent, title):
         wiz.WizardPageSimple.__init__(self, parent)
         self.next = self.prev = None
         self.sizer = makePageTitle(self, title)
      def eligibleMOS(self, event):
          if self.intelligence >= 12: 
               self.MOS_list.append("Analyst")

The problem is that I can't figure out how to use the "intelligence" variable from the BasicInfoPage class to the MOS class. I've tried several different things from around the Internet but nothing seems to work. What am I missing?

Edit I realized after I posted this that I didn't explain it that well. I'm trying to create a computer version of the Twilight 2000 RPG from the 1980s.

I'm using wxPython to create a wizard; the parent class of my classes is the Wizard from wxPython. That wizard will walk a user through the creation of a character, so the Basic Information page (class BasicInfoPage) lets the user give the character's name and "roll" for the character's attributes. That's where the "self.intelligence" comes from.

I'm trying to use the attributes created her for a page further on in the wizard, where the user selects the speciality of the character. The specialities that are available depend on the attributes the character has, e.g. if the intelligence is high enough, the character can be an Intel Anaylst.

It's been several years since I've programmed, especially with OOP ideas. That's why I'm confused on how to create what's essentially a global variable with classes and methods.

A: 

If I understood you correctly, then the answer is: You can't.

intelligence should be an attribute of WizardPageSimple, if you'd want both classes to inherit it.

Depending on your situation, you might try to extract intelligence and related attributes into another baseclass. Then you could inherit from both:

class MOS(wiz.WizardPageSimple, wiz.IntelligenceAttributes): # Or something like that.

In that case you must use the co-operative super. In fact, you should be using it already. Instead of calling

wiz.WizardPageSimple.__init__(self, parent)

call

super(MOS, self).__init__(self, parent)
Antti Rasinen
A: 

All you need is a reference. It's not really a simple problem that I can give some one-line solution to (other than a simple ugly global that would probably break something else), but one of program structure. You don't magically get access to a variable that was created on another instance of another class. You have to either give the intelligence reference to MOS, or take it from BasicInfoPage, however that might happen. It seems to me that the classes are designed rather oddly-- an information page, for one thing, should not generate anything, and if it does, it should give it back to whatever needs to know-- some sort of central place, which should have been the one generating it in the first place. Ordinarily, you'd set the variables there, and get them from there. Or at least, I would.

If you want the basic answer of "how do I pass variables between different classes", then here you go, but I doubt it's exactly what you want, as you look to be using some sort of controlling framework:

class Foo(object):
    def __init__(self, var):
        self.var = var

class Bar(object):
    def do_something(self, var):
        print var*3

if __name__ == '__main__':
    f = Foo(3)
    b = Bar()
    # look, I'm using the variable from one instance in another!
    b.do_something(f.var)
Devin Jeanpierre
+2  A: 

You may have "Class" and "Instance" confused. It's not clear from your example, so I'll presume that you're using a lot of class definitions and don't have appropriate object instances of those classes.

Classes don't really have usable attribute values. A class is just a common set of definitions for a collection of objects. You should think of of classes as definitions, not actual things.

Instances of classes, "objects", are actual things that have actual attribute values and execute method functions.

You don't pass variables among classes. You pass variables among instances. As a practical matter only instance variables matter. [Yes, there are class variables, but they're a fairly specialized and often confusing thing, best avoided.]

When you create an object (an instance of a class)

b= BasicInfoPage(...)

Then b.intelligence is the value of intelligence for the b instance of BasicInfoPage.

A really common thing is

class MOS( wx.wizard.PageSimple ):
    def __init__( self, parent, title, basicInfoPage ):
        <snip>
        self.basicInfo= basicInfoPage

Now, within MOS methods, you can say self.basicInfo.intelligence because MOS has an object that's a BasicInfoPage available to it.

When you build MOS, you provide it with the instance of BasicInfoPage that it's supposed to use.

someBasicInfoPage= BasicInfoPage( ... ) 
m= MOS( ..., someBasicInfoPage )

Now, the object m can examine someBasicInfoPage.intelligence

S.Lott
+3  A: 

Each page of a Wizard -- by itself -- shouldn't actually be the container for the information you're gathering.

Read up on the Model-View-Control design pattern. Your pages have the View and Control parts of the design. They aren't the data model, however.

You'll be happier if you have a separate object that is "built" by the pages. Each page will set some attributes of that underlying model object. Then, the pages are independent of each other, since the pages all get and set values of this underlying model object.

Since you're building a character, you'd have some class like this

class Character( object ):
    def __init__( self ):
        self.intelligence= 10
        <default values for all attributes.>

Then your various Wizard instances just need to be given the underlying Character object as a place to put and get values.

S.Lott
A: 

My problem was indeed the confusion of classes vs. instances. I was trying to do everything via classes without ever creating an actual instance. Plus, I was forcing the "BasicInfoPage" class to do too much work.

Ultimately, I created a new class (BaseAttribs) to hold all the variables I need. I then created in instance of that class when I run the wizard and pass that instance as an argument to the classes that need it, as shown below:

#---Run the wizard
if __name__ == "__main__":
    app = wx.PySimpleApp()
    wizard = wiz.Wizard(None, -1, "TW2K Character Creation")
    attribs = BaseAttribs

#---Create each page
    page1 = IntroPage(wizard, "Introduction")
    page2 = BasicInfoPage(wizard, "Basic Info", attribs)
    page3 = Ethnicity(wizard, "Ethnicity")
    page4 = MOS(wizard, "Military Occupational Specialty", attribs)

I then used the information S.Lott provided and created individual instances (if that's what it's called) within each class; each class is accessing the same variables though.

Everything works, as far as I can tell. Thanks.

crystalattice