0

A similar question was asked here . However, the responses didn't really help me grasp how some parts of the program worked. The program is as follows:

from sys import exit
from random import randint

class Game(object):

    def __init__(self, start):
        self.pie = [ 'pie test']

        self.start = start

    def play(self):
        next_room_name = self.start
        while True:
            print "\n--------"
            room = getattr(self, next_room_name)
            next_room_name = room()

    def rooom(self):
        print "Test worked. good job"
        return "piez"

    def piez(self):
        print "pie room"
        exit(1)


a_game = Game("rooom")
a_game.play()

The first question is how is the following working?

def play(self):
        next_room_name = self.start

        while True:
            print "\n--------"
            room = getattr(self, next_room_name)
            next_room_name = room()

I know that somehow the following is generating the room name so the program can go to where it needs to. I'm just not seeing how it is happening.

My second question is:

self.start = start

I sort of understand self.pie is doing. But I'm not sure what self.start = start is suppose to accomplish. Thanks again for your assistance.

Community
  • 1
  • 1
kiddsupreme
  • 115
  • 1
  • 3
  • 13

2 Answers2

1

Let's say that you have some class like this:

class DummyClass(object):

    awesome = True

    def not_awesome(self):
        self.awesome=False

Using getattr on this is exactly equivalent to using the dot syntax, e.g.

dumb = DummyClass()
print getattr(dummy, "awesome") # True
print dummy.awesome # True

You can use this with methods too:

dumb = DummyClass()
no_more_awesome = getattr(dummy, "not_awesome") # returns the not_awesome method of dummy
print dummy.awesome # True
no_more_awesome()
print dummy.awesome # False

So, in the code snippet you posted, the getattr(self, next_room_name) gets the method with name next_room_name and returns the function (bound to self) to be called. You use a variable instead of dot syntax here because you don't know the name in advance. Consider the following two snippets to get this (a bit confusing with overlaps...sorry):

dummy = DummyClass()
awesome = "not_awesome"
print dummy.awesome # True
print getattr(dummy, awesome) # string with something like <bound method ... >
Jeff Tratner
  • 16,270
  • 4
  • 47
  • 67
0

First of all: object initialization. When Game("rooom") is called, the string "rooom" is bound to the parameter start of __init__. The statement this.start = start simply stores the string "rooom" in the internal object dictionary, accessible through this.start.

Then play() method is called: the usage of getattr in this context defines a pattern called Pluggable Selector. In other words, rather than explicitly stating which method to call, the name of the method is stored is a variable (next_room_name in this case).

The first method to be called is rooom because the local variable next_room_name (local to the scope of the method play) is initialized to self.start before the while loop.

The return value of the method call is used to update the next_room_name variable, therefore after rooom executes, the value becomes "piez". Hence, the next method to be called is going to be piez.

Finally, when piez executes, a call to exit(1) is made, therefore the interpreter is terminated, with no further execution of code. The reason why no more code executes, in this case, is that sys.exit raises a SystemExit exception (see documentation), which is not caught anywhere.

Stefano Masini
  • 452
  • 3
  • 11