Ex43 Questions about the code

Hello all,

I have new questions about the code from ex.43:

A.

1    a_map = Map('central_corridor')
2    a_game = Engine(a_map)
  • In line 2, when the object a_game is created, what exactly from the object a_map is given as parameter? I have been watching the value of the instance attribute of self.scene_map and it takes no value. I expected the value of the instance attribute of self.start_scene from the a_map object to be transferred to self.scene_map, but it is not so(I watched the value in Debugging Mode).

  • And why does self.scene_map take no value throughout the whole game?

B.

1 class Engine(object):
2
3       def __init__(self, scene_map):
4              self.scene_map = scene_map
5
6       def play(self):
7              current_scene = self.scene_map.opening_scene()
8              last_scene = self.scene_map.next_scene('finished')
  • Can someone please explain line 7? I understand that the method opening_scene() returns in the first step of the game CentralCorridor, but with what scope is there also written self.scene_map? I would guess that it messages the instance attribute self.scene_map the result of the method opening_scene()(i.e., CentralCorridor), but this is not so, as once again, self.scene_map takes no value (as seen in Debugging Mode). Also, was it not enough to write self.opening_scene()?

  • I did see however that current_scene becomes a new object, in this case of the class CentralCorridor, but I did not understand why, given that self.scene_map is also written in the line and I did not understand what this part of the code does.

Explanations would be much appreciated.

Thank you!

Re:
A.
“In line 2, when the object a_game is created, what exactly from the object a_map is given as parameter?”

OK, after searches and readings, I think that in the code

a_game = Engine(a_map)

the object a_game does not inherit the methods and attributes of the a_map object, but it has access to them as if it inherited them, and a_game can also change the value of the attributes of the object a_map. Is this correct? Does anybody know how this is called in python?

Ok, so… You can give that self.scene_map any value you want when you initiate the engine. It would break the code, but you could give it a dictionary, a list, a method, a class, anything.
The real work is done in that play method. It uses that a_map class you initiated - Map(‘central corridor’).
That class object that you made my assigning a_map=Map(‘central corridor’), is what controls the shifting between scenes.
All play does is tell it (the Map object) to go/run/execute it’s methods:
Opening_scene and next_scene.
The work is being done in Map, and not engine.

Hello @nellietobey,

Thank you for your reply!

Yes, I agree that if self.scene_map would receive another value, the code would not work. I am curious how Python sees the parameter a_map in the code

a_game = Engine(a_map)

I know that a_map is an object previously defined, but in the code above a_game is an Engine class and has access to the a_map object’s methods and attributes (but does not inherit them) and a_map is also a parameter/argument given in Engine(a_map). But it is not an usual parameter, because self.scene_map takes no value throughout the game. What kind of value is it then, what is the type of this variable? A string? I am curious how Python sees this piece of code.

I am not sure if I made myself understood…

As to:

As far as I understood the code, the code in Map only returns the value of the given key from the dictionary. The code in Engine (more exactly in the while) is the one that does the shifting between scenes:

next_scene_name = current_scene.enter()

Now I’m curious how to explain. I’m going to go to the exercise and I’ll get back to you. It’s been a long time since I did that exercise

Ok, so a_map is an object. It is the whole class:

a_map = Map('central_corridor')

If you look in the Engine:

 def play(self):
7              current_scene = self.scene_map.opening_scene()
8              last_scene = self.scene_map.next_scene('finished')

self.scene_map is that ‘a_map’ you passed in, which is the Map class object.
The current_scene = is calling a method from the Map class.
so is the last_scene =.

The engine just tells Map object to go.
The a_map is an object, a class with all it’s methods passed into the Engine.
If you look in the separate classes for each room, they too send information back to the Map object, which is controlling the game by sending you to the next room according to the choices made in each current room.

Inheritance and attributes are completely different functions of a class.
There is no inheritance going on in Engine. The Map object is simply an attribute.
Information is being passed around through the methods in each function of the rooms and the map. Look for the return statements in room, draw a picture to see where and what information is being passed around, I think it will help visualize what is going on.
Particularly look at the ‘next_scene’ function/method in Map.


1 Like

OK.

So in the code:

a_game = Engine(a_map)

the object a_map becomes in the context of the above code an attribute. Whose object is this attribute? It for sure does not belong to a_game.

1 Like

yes it does… it just as a different name.

 def __init__(self, scene_map):
4              self.scene_map = scene_map

The a_map becomes the ‘scene_map’ When the Engine is initialized.
Engine is using it, under a different name. Change all the ‘scene_map’ references to ‘a_map’ when you look at it.

Wait, I think your text below made me realize.

So, because self.scene_map becomes a_map, then a_map is not an attribute, but a value of the attribute self.scene_map, which belongs to the a_game object. An because there is no inheritance, the only way to access the attributes of a_map is if you give as value to the attribute self.scene_map the value a_map, which is the label of the object a_map.

So, this answers then also question B. That if I want to access the method opening_scene() that belongs to a_map through the object a_game, then I must write self.scene_map.opening_scene(). I cannot just write a_map.opening_scene(), cause a_map is just a value…

Very complicated.

1 Like

Yup. And this is why naming a variable can be so very important.
I believe it is totally legitimate to just keep ‘a_map’ as the name instead of ‘scene_map’ in the Engine class. I’m not sure why he changed the name like that, maybe it’s a naming convention thing.

I printed all attributes of the object a_game, and a_map is not an attribute of the a_game, hence my confusion…:slight_smile:

1 Like

Now I’m curious, what did it list as the attributes?

He did not write a_map instead of scene_map because a_map is just a value given to the attribute scene_map. A_map is not an attribute. And you cannot call a method from a value, you have to use the attribute.

1 Like

Attributes of a_game are: {‘scene_map’: <main.Map object at 0x03B09C10>}
Attributes of a_map are: {‘start_scene’: ‘central_corridor’}

you see in the first line that there is no a_map attribute, but there is a Map object as the value, which is a_map(I assume)
Yeah, the answer was there all the time… I did not know how to read it

1 Like

you can give an init() attribute any name you want.

I could do:

class Spam(object):
    def__init__(self, something):
         self.something = something
    def spam(self):
         something.hiYa()

class Hello(object):
    def hiYa(self):
         print("Hello")

something = Hello()
sillyness = Spam(something)
sillyness.spam()

I didn’t test that, but the concept is correct.

What do you mean here:

I mean it’s a name. a place holder, a variable that holds a value. You can most certainly call a method from a variable. If that variable is a class. That is how class’s work. I can make a class with ten attributes, all other class’s if I want to, and I can name them anything I want. The name space, is held in the class’s dictionary which is a whole bigger conversation, That namespace can hold anything. From a class, to a method, to a string, bool, anything.
When I declared something as Hello() in that recent example, that variable now holds that class as it’s value.
When I pass that variable into Spam as an attribute, it gets stored in Spam’s dictionary as 'something variable. I can name that anything I want to, it is protected in the class’s dictionary.
But I imagine it really bad code to have variables with the same name and different values in one script, even if it is protected in a class dictionary.

1 Like

Thanks for the explanation.

Yes, it is a good explanation and a good reminder for me. Thanks a lot! It has been fun!

1 Like

One last thing: Check this out, this code will function the same as that previous example. Look at the difference. I’m sure you got it now, but I think it’s worth looking at it this way too:

  • I did go test the two codes this time through *
class Spam(object):
    def __init__(self):
         self.something = Hello()
    def spam(self):
         self.something.hiYa()

class Hello(object):
    def hiYa(self):
         print("Hello")


sillyness = Spam()
sillyness.spam()
1 Like

Thanks a lot! Awesome examples!

It did take some time to understand them and the difference, but I think I got it.
I did not know you could do that:

self.something = Hello()

But as you said, you can pass anything, any value/class.

1 Like