Help: Python while loop inside Class
I'm just learning Python as my first program开发者_高级运维ming language, and going through the this online book. My problem relates to the exercise found on that page. I'm stuck understanding how the play method works inside the class. How is it accessing all the other methods? How is getattr functioning inside this loop? Appreciate the help!
Here is the method for those that would prefer not to leave the page:
def play(self):
next = self.start
while True:
print "\n--------"
room = getattr(self, next)
next = room()
I'll try to explain how it works.
First, this is run:
a_game = Game("central_corridor")
This calls Game.__init__("central_corridor")
.
In the __init__ method, self.start
takes the value "central_corridor".
Then we go back to the main body. By now, we have a variable called a_game
. This variable is in fact an instance of the class Game
, and it has some properties, like a_game.start
, a_game.quips
, a_game.death()
, etc.
Next, this is run:
a_game.play()
That calls the play()
method in a_game
. Not in Game
, but in a_game
. Thus, when the method is running, it has access, through the word self
(which is treated like a regular argument), to all properties of a_game
.
This is run next
next = self.start
self.start
was defined in __init__()
, and is equal to "central_corridor". So now, next
is "central_corridor".
We enter the while True:
loop, print some hypens, and call getattr()
.
getattr()
takes at least two arguments. The first one is an intsance of an object, in this case self
, and the second one is the name of an attribute of that instance. In this case "central_corridor"
.
So getattr looks for an attribute of self that is called "central_corridor", and it finds it, and returns it. Now, room
is equal to self.central_corridor
.
Next, next = room()
is run. As room is currently equal to self.central_corridor
, this:
next = self.central_corridor()
is actually run.
self.central_corridor()
can return one of "death", "laser_weapon_armory" or "central_corridor". Let's say it returns "laser_weapon_armory". Now next
is "laser_weapon_armory". We go back to the beginning of the loop. We print some hyphens again, get an attribute of self named "laser_weapon_armory", which happens to be self.laser_weapon_armory
, and run it.
self.laser_weapon_armory
can return "the_bridge" or "death". This time let's say it returns "death". Now next
is "death". We go back to the beginning of the loop, print some hypens, get self.death
, and run it.
All self.death
does is print a random string from self.quips, and then exit(1)
. The exit
function, which is from the sys
module, does just that. It terminates the program.
And that's pretty much it. I hope this helped.
Good luck learning Python the hard way!
Take a look here:
http://effbot.org/zone/python-getattr.htm
Basically getattr(self, next)
asks the self
object to return the attribute named by next
. For example if next
is "abc" then it's like calling self.abc
.
Though I am uncertain as to why, it is clear that getattr() is executing whatever value is posessed in 'next'. Initially it is 'start' which is '"central_corridor". However, after that function completes and returns a value, the interaction between room() and getattr(self, next) is picking up that value and executing the corresponding function as 'next'.
EDIT:
getattr() is getting the value of the attribute, rather than the attribute itself. The value of the attribute is.... drum roll whatever the attribute returns. Which requires the attribute to fully execute in order for the value to be obtained. Then, the attribute 'next' is changed to become the return of the now-executed attribute... 'next' is then run in order to get it's value by getattr() ! Repeat until 'death' or whatever, which breaks the cycle.
I get it now.
It's actually very simple. :)
Think about it this way. next
is assigned the reference (address) of self.next
. So when we getaddr(self, next)
, since next is the reference of self.next
, it really is just asking for the memory address of self.next
which is of course an attribute of self
, so it works.
I know it looks a little odd though.
A simple example for you:
>>> a = 'r'
>>> print '0x%x' % id(a)
0x7fbe99e204b8
>>> b = a
>>> print '0x%x' % id(b)
0x7fbe99e204b8
>>> class T(object): pass
...
>>> foo = T()
>>> print '0x%x' % id(foo)
0x15c6bd0
>>> bar = foo
>>> print '0x%x' % id(bar)
0x15c6bd0
>>> bar = T()
>>> print '0x%x' % id(bar)
0x15c6b90
So basically assigning a variable to another variable just references the same object, without changing anything.
getattr is a built-in function from python. The play method is a method that belongs to the class Game.
While True means that the loop keeps going forever till you interrupt it.
What else don't you understand?
EDIT: Ig you create a new game : g = Game()
then you can call the play method : g.play()
, this is what play(self) means, you can also call it this way :Game.play(g)
, but that is not common.
EDIT2: read more about getattr function here
精彩评论