Exercise 43 Learn Python The Hard Way

May I give up in exercise 43? It was really hard, even I cannot understand exercise 41 as a whole program. I could understand part by part but the logic behind the whole program is difficult to understand. I decided to continue and stuck again in exercise 43 :frowning:

In a wordā€¦No. Iā€™m not well verse with words or tact. I am currently struggling with the same areas. I say currently as in the past two to three monthsā€¦again. (This is my third time through the book to this point because, in short, ā€œLifeā€ happens and I have too man 0 days and I become rusty and go back to refresh or just start over.) Lately, as I have been running ex41.py in python, it has helped me start to piece things together as I struggle with understanding the engine. Each chapter interduces you to something you will use or you will use something you have been introduced to. If we skipped say, functions, you would be lost every time we saw foo() .
Maybe go back to ex41, go over it and note what you do not understand yet and study it. Go over the videos. Look it up. Then maybe 42 makes more sense. What doesnā€™t, look it up, study it, go over the videos. Then maybe ex43 makes more senseā€¦rinse, wash, repeat, repeat.
Each time I go over something I donā€™t understand it makes a little more sense each time. Like dictionaries, I thought I was going to quit on those, but over time they made sense. As I keep repeating these chapters I get more and more from it and I WILL get these (and that damn engine) as will you.
Keep at it.
I am most certain others will have more articulate and wiser response, with better advice.
Sorry if I read a bit rambly and possibly incoherent, Iā€™ve been up for 20 hrs with 3hrs sleep, Iā€™ll probably read this tomorrow night and wonder what the hell I was saying.

Also, came across this when looking for Chuchillā€™s words and died laughing.

but I didnā€™t want to seem condescending or belittling.

Iā€™ve got an idea:

You arenā€™t clear on how the Engine class works right? Now, thereā€™s a huge chance that this is because itā€™s confounded with all the other code so thatā€™s too much information.

What if you created a new python file with only the Engine in it. Itā€™s pretty small, so then your job is to get a game to work using the Engine class but not looking at my code very much. The key to this is to start small and only call functions in the Engine, get it to actually run with a single room class, and slowly get it working.

Next tactic is to copy my game, but do it from the outside without using any of my code and design. First, copy the game using what you know, with if-statements and functions. Then, copy the game but use classes and try to make it work.

When I say ā€œcopyā€ though I donā€™t mean go copy the code Iā€™ve written. Thatā€™s not working. What I mean is take my file and run it, study it, copying my text and what happens in each room like youā€™re a gamer and you donā€™t have the code. Then, do your own replica using the text and make it work the same.

The reason these two approaches work is they remove information thatā€™s confusing so you can focus only on one particular thing. In the first case, itā€™s just how the Engine works by isolating the Engine on its own and getting it to work. In the second case itā€™s creating a similar game using only your existing knowledge, which teaches you the structure of the game without confusing you with the Engine.

Last little tidbit, when you say you donā€™t understand the engine have you been running it with printing out every function call? Or, are you staring at the screen trying to read it without running it? If youā€™re doing the latter then thatā€™s why you canā€™t figure it out.

How about, try running it under pdb and tracing through it pdb ā€” The Python Debugger ā€” Python 3.9.7 documentation

You can tell pdb to stop at any function in the Engine, and to print out and watch variables, then you can step through and study each individual step to see whatā€™s going on. You can watch every variable change and each line of code run. If the raw command line style of pdb doesnā€™t work, then this might:

Basically, Iā€™m suggesting you do both remove information with my first two suggestions, then increase information with my last suggestion.

Try that, then come back and I have one more thing I can suggest.

in here:

class Map (object):
   def __init__(self,start_scene):
      self.start_scene = start_scene #it will give a_map.start_scene = ā€œcentral_corridorā€, won't it?
   def next_scene(self,scene_name): #what this function will do?
      val = Map.scenes.get(scene_name) # i guess it try to fetch the value from .get("central_corridor"), so val = CentralCorridor() (?)
      return val
   def opening_scene(self): #i also donā€™t get what this function will do
      return self.next_scene(self.start_scene)

a_map = Map(ā€œcentral_corridorā€)
a_game = Engine(a_map)
a_game.play()

Hereā€™s some reply comments, and then some questions for you to study:

class Map (object):
    def __init__(self,start_scene):
        #Q: it will give a_map.start_scene = ā€œcentral_corridorā€, won't it?
        #A: Yes, that's correct, here's how you can see that yourself:

        print(">>> Map.__init__: start_scene is", start_scene)
        self.start_scene = start_scene
        print("<<< Map.__init__ exit: self.start_scene is", self.start_scene)

    # Q: what this function will do?
    # A: Given a scene name it will look the scene up in the Map.scenes dict
    def next_scene(self, scene_name):
        #Q: i guess it try to fetch the value from .get("central_corridor"), so val = CentralCorridor() (?)
        #A: Yes, it uses .get on the Map.scenes dict to find the one that you've mapped to "central_corridor"
        #   but, that's just the first call.  Later calls change it as you enter new rooms.  Here's how you can
        #   see that:

        print(">>> Map.next_scene: scene_name is", scene_name)
        val = Map.scenes.get(scene_name) 
        print("<<< Map.next_scene: return val is", val)
        return val

  # Q: i also donā€™t get what this function will do
  # A: It takes the self.start_scene you set in Map.__init__ (see above) and then looks that
  #    up using Map.next_scene to find the first scene to show the player. Here's how you can
  #    see that for yourself.
  def opening_scene(self): 
      print(">>> Map.opening_scene: self.start_scene is", self.start_scene)
      val = self.next_scene(self.start_scene)
      print("<<< Map.opening_scene: returning val is (for first scene)", val)

a_map = Map(ā€œcentral_corridorā€)
a_game = Engine(a_map)
a_game.play()

My questions back to you:

  1. Iā€™ve said in the past that you canā€™t see what the value of something is by reading the code, and that you have to print everything. Did you do any printing like I have here (and was only showing me the relevant code), or did you not print anything and try to figure it out by reading it?
  2. If you didnā€™t have print() statements like I have here printing out every variable in every function, then can you explain why you missed this instruction from me? Maybe I need to do a whole course on just doing this, but Iā€™m pretty sure Iā€™ve said and demonstrated this quite a lot.
  3. Have you written out the steps that are happening here in a list on paper? That might help you understand since I think what you donā€™t get is that one function is calling another function or using the results of a previous call. Something like this:
  • a_map = Map(ā€œcentral_corridorā€) calls Map.init with ā€œcentral corridorā€.
  • Map.init sets self.start_scene
  • Engine calls a_map.start_scene
  • Engine calls a_map.next_scene

The print statements Iā€™ve shown you here basically do this. If you run this (after fixing it for your code) youā€™ll see a log of every function call and every variable passed to that function. If you then write these out on paper as steps the program is taking you might finally see whatā€™s happening.

Let me know your answers.

Edit: My editor uses 4 spaces for python indenting so you might have to fix it, but you should probably add these print statements manually to your code instead of pasting mine.

  1. I do every example you gaveā€¦ Sometimes I improvise on something simple, but when it getting more difficult, I still type it and try to understand what does that mean. I also printed out like what you did in the example. The problem I found last few days was I still have a trouble to understand where the code will go after executing one particular code especially in ex43 since there were too many class (I found that the knowledge gap between the previous example was too big). I found a guy try to draw a map how the code works and just realized it jumped back and forth between Engine and Map class, Iā€™ll try to figure it out today.
  2. Yes i tried to type it was helpful to build my basic understanding. But again, the code in exercise 43 still seems too much for me who ever just had done basic coding in 8 years ago. Yes you are right, I am still a bit confused if there is one function calling another function. I do understand the concept of calling a function with ā€˜def y(x):ā€™ but with a ā€˜class X(object):ā€™ is something new for me.

Okay I get it done finally. Now I could understand the flow and logic of the whole program but that was because you already typed it in the book so the reference and guidance is there. But if you didnā€™t put anything there, I couldnā€™t imagine how I can make the code by myself. Especially the code in class Map and Engine will require me to think ā€˜futuristicallyā€™ in order to make it work simultaneously

The key to building more complex things like this is realizing that nobody sits down and makes something complex right away. Itā€™s built up over time as you work and need to solve problems. So, to make something like this donā€™t try to make it at the start. Pick a specific problem and make a small simple solution to part of the problem, then organically add in complexity as you need it.

In this case, I started with just a simple thing that ran each scene in order. Thatā€™s easy since itā€™s just the scene classes and a list. Then I needed a way for a scene to say whatā€™s the next scene and that led me to making the Map in a first version. Then the Map needed to be run so that made the Engine. Then I kept working on that and slowly got what you have here.

Also, keep in mind this feeling of ā€œIā€™ll never make anything that complex!ā€ is a matter of perspective. Right now you donā€™t have a lot of experience of it seems complex. In a few years youā€™ll have the problem that all of your code is too complex (because intermediate programmers love showing off with insanely complex code).

Finally, remember that you shouldnā€™t be trying to write straight code. Even now when I code something Iā€™m not clear on I do this:

  1. Write out what I want it to do in plain English.
  2. Turn that plain English into comments.
  3. Write simple pseudo code under the comments.
  4. Turn the pseudo code into real code one bit at a time running it after each change.
  5. When itā€™s all working, delete the comments that arenā€™t documentation.

Try that on a few little problems.

1 Like