Ex43 - Brain being a Jabroni

The code and questions related are below, if you can help, you will be rewarded with lifelong friendship a shiny Charizard and 60+ HP.
I just feel like my brain is starting to burn out and give me answers to things just because it’s tired, not specifically because it’s right, I numbered my questions to help out with tracking my thoughts, if you could reply accordingly.

class Engine(object):

    def __init__(self, scene_map):
        self.scene_map = scene_map  **# 6 would this then take the same argx/param since the instance of Engine was made with the instance of Map as a parameter? Or is it yet to be fulfilled? **
        

    def play(self):
        current_scene = self.scene_map.opening_scene() **# 7 What is going on here??**
        last_scene = self.scene_map.next_scene('Finished')

        while current_scene != last_scene:
            next_scene_name = current_scene.enter()
            current_scene = self.scene_map.next_scene(next_scene_name)
        
        
        current_scene.enter()

class Map(object):                                                              

**# 1 scenes is a class variable right? Not an instance variable..**
    scenes = {
        'central_corridor': CentralCorridor(),                                  
        'laser_weapon_armory' : LaserWeaponArmory(),
        'the_bridge' : TheBridge(),
        'escape_pod' : EscapePod(),
        'death' : Death(),
        'finished' : Finished()
    }
**# 2 which is the parameter that takes the arguments from scenes, start_scene or scene_name or do they represent the same thing?**
    def __init__(self, start_scene):                                           
        self.start_scene = start_scene
    
    def next_scene(self, scene_name):                                         
        val = Map.scenes.get(scene_name)                                        
        return val                                            **# 3 where does VAL get returned to**

    def opening_scene(self):
        return self.next_scene(self.start_scene)

a_map = Map('central_corridor') **# 4 so is this scene_name's argument/parameter?**
a_game = Engine(a_map)  **# 5 and therefor a_map holds that same argx/param right?**
a_game.play() 

Thank you so much
Nick

Hello @Nick

I had to work hard on this one too.

#1 Yes. it is a class variable.

#2 This is the tricky bit to get the brain understand what is obvious for Python.
I’ll do my best to explain.
next_scene and opening_scene are methods in the Map class.

def next_scene(self, scene_name):
    val = Map.scenes.get(scene_name)
    return val

will take the argument and look up the class in scenes.
But it got its argument in the Engine class.
You find it again in the while loop:
current_scene = self.scene_map.next_scene(next_scene_name)

There is a lot going on here.
I had to print it out on paper and start to underline methods and attributes with different colored marker pens.
Another thing Zed use to say is to put print statements in the code:

print(current_scene())

It also helps to see whats happening.

#4 a_map is an instance of the Map class with ‘central_corridor’ as an argument
#5This object then is used as an argument when the instance (a_game) is created.

Then the method play has the information to start the game with a class.

I am sorry for not having a deeper explanation than this.
I am still struggling to fully understand this.
Trying to explain for others is a way for me to better get all the pieces in the jig saw pussle together.

Answers:

  1. Yes, try Map.scenes and you see it’s a variable on the class. The thing that trips people up is it also is a variable on any object, but to be consistent always use the class Map to get at it.
  2. See, now this is the other problem. You say, “start_scene or scene_name”. But wait, you’re only talking about __init__ so where do you see scene_name in __init__? All that init function does is setup Map objects when you make them. When you do:
x = Map('start the stuff here room')

It’s like doing this:

x = Map.__init__('start the stuff here room')

That’s it. The other functions have nothing to do with it. This is actually a common mistake in how beginners view code. To me I focus on only the details that are relevant on that one line. To a beginner, that line, and 10 lines around plus other random things seem relevant for odd reasons. For example, are you thinking scene_name and start_scene are related because they both have the word “scene” in them?

Well, I could write the code like this and it’d still work:

    def __init__(self, elephant_airplanes):                                           
        self.start_scene = elephant_airplanes
    
    def next_scene(self, super_screwdriver_orange_juice):                                         
        val = Map.scenes.get(super_screwdriver_orange_juice)                                        
        return val 

The actual text used to make a variable has no meaning to the computer other than a way for you, the human, to use it. Thinking that using “scene” in both variables connects them is adding extra things that don’t happen. But, that’s just a guess based on other things folks in the past have thought.

  1. Nope, that is __init__(start_scene). Like I mentioned above, where do you see scene_name in the __init__? I believe this is your central confusion.

  2. That doesn’t quite make sense as a question, but I’m guessing you’re saying that by passing a_map to Engine.__init__ you think that gives a_game access to scene_name? No, so again got to narrow your thinking. All that line does is pass a_map to the Engine.__init__ and that is all. Nothing else.

Ok, now a question to you:

What does the __init__ and self do in a class and object?

1 Like

One additional thing:

It looks like you’re trying to understand this code by staring at it and reading it, but you need to run it and inspect what’s inside. I recommend either using print to print out the variables at every stage, or try this out:

https://docs.python.org/3.2/library/pdb.html

At the top of this file put this:

import pdb

Then, right at the top of a confusing function type this:

pdb.set_trace()

When you run your code, it will pause there and then you can use the PDB (Python Debugger) to actually print out what’s there and type commands and step through it. Super useful, so give it a shot and see inside this machine.

1 Like

Absolutely NOTHING to be sorry about, you’ve given me more than just a helping hand, you’ve assured me that i’m not alone on this one either, but I found your answer extremely helpful, and I thank you for the effort and time in compiling a coherent reply. This is gonna help me immensely.

1 Like

Zed thank you so much, I’ll spend the day on this and implement the suggested methods above. I really appreciate the time into answering my questions and sharing with me the extra information in regards to reading and debugging. But holy crap did you read me like a book there, I printed it out and pretty much did exactly what you said I was doing… staring and reading! I feel like I’ve been caught with my hand in the cookie jar! lol! Thanks again for such a great book, and fantastic support! Have a great day.

As for the question @zedshaw

The init is a constructor, it initialises an instance of a class or an object. It’s called when you create a new instance of a class…
And Self is within that function, the object created is assigned Self as a parameter…

Do I have that right?

OH! And as for the example you gave me in regards to:
ford = Truck(‘red’) ----> Truck.init(ford, ‘red’)

would I be correct in the assumption that in the DEF next_scene, val is essentially:

val = Map.scenes.get(scene_name) ----> Map.init(val, start_scene) ??

Hi @Nick.

Have a look at this video at youtube:
Classes and objects

This also helped me much.

NOICE!!! Thanks, just downloaded!

Yep, that’s right for init and self. I think you’re super close so just takes more study.