[Tutor] Re: The Game of Life

Kent Johnson kent37 at tds.net
Fri Jan 7 03:58:22 CET 2005


Brian van den Broek wrote:
> In an earlier version, instead of the run_world() method I now have, I
> put the following within my class definition and after (i.e. outside of)
> the method defs:
> .>    while self.current_generation > self.total_generations:
> .>        time.sleep(self.sleep_interval)
> .>        self.update_world()
> .>        self.print_world()
> 
> which caused this:
> 
> Traceback (most recent call last):
>    File "D:\Python Files\foogame_of_life.py", line 3, in -toplevel-
>      class life_world:
>    File "D:\Python Files\foogame_of_life.py", line 76, in life_world
>      while self.current_generation > self.total_generations:
> NameError: name 'self' is not defined
> 
> That surprised me -- I'd have guessed that within a class, self was
> everywhere defined, and not just within methods.

self is just another method parameter. OK not quite, but it is a method parameter and it is only 
bound within the scope of the method. There is nothing magic about the name, either; it is just a 
(strong) convention.

In fact, by using a different name for self and the magic of lexical scoping and closures, you can 
do something very much like Java inner classes - make a nested class that has access to all the 
attributes of the enclosing class.

This is off-topic and a bit twisted, but I'm not going to let that stop me:

''' Make a nested class that has access to the attributes of its parent class '''
class Outer:
     def __init__(outerSelf, x):
         outerSelf.x = x

     def makeNested(outerSelf, x):
         class Nested:
             def __init__(innerSelf, x):
                 innerSelf.x = x

             def showX(innerSelf):
                 print 'outer x is', outerSelf.x
                 print 'inner x is', innerSelf.x

         return Nested(x)

o = Outer(3)
n = o.makeNested(5)

n.showX()

o.x = 22
n.showX()

################
prints:

outer x is 3
inner x is 5
outer x is 22
inner x is 5

Kent

> 
> Clearly, I'm confused about something.
> 
> Anyway, thanks for reading. Best to all,
> 
> Brian vdB
> 
> 
> ------------------------------------------------------------------------
> 
> # pylife.py
> # Version 0.1
> # Brian van den Broek
> # vanden at gmail.com
> # 2005-01-06 Thursday 17:41
> # Copyright 2005
> 
> '''An OOP and ASCII based representation of Conway's Game of Life.
> Much of the code was inspired by a post of Danny Yoo's on 2005-01-03 04:11
> to the Python Tutor List. (You can find that post by searching the archives at
> <http://mail.python.org/pipermail/tutor/>.)
> 
> I make no claims to ellegance or efficency -- this is only the second OOP I
> have written.'''
> 
> import random, time
> 
> class life_world:
>     
>     def __init__(self, X, Y, sleep_interval = 0.5, total_generations = 20):
>         self.X = X
>         self.Y = Y        
>         self.world = self.seed_world()
>         self.sleep_interval = sleep_interval
>         self.total_generations = total_generations
>         self.current_generation = 0
>         self.print_world()
>         
>     def seed_world(self):
>         '''Constructs a new random world of size XxY.'''
> 
>         world = {}
>         for j in range(self.X):
>             for i in range(self.Y):
>                 world[i, j] = random.choice((True, False))
>         return world
> 
>     def print_world(self):
>         '''Prints out a string representation of a world.'''
> 
>         print '\n\nGeneration Number: %s\n' %self.current_generation
>         print '--'*(self.Y + 1) + '-'
>         for j in range(self.X):
>             print '|',
>             for i in range(self.Y):
>                 if self.world[i, j]:
>                     print 'X',
>                 else:
>                     print ' ',
>             print '|'
>         print '--'*(self.Y + 1) + '-'
>         
>     def count_neighbours(self, cell):
>         '''Returns the number of live neighbours to this one.
> 
>         'neghboUrs because I'm Canadian, eh.
>         '''
>         live_count = 0
>         i,j = cell
>         for i_delta in [-1, 0, 1]:
>             for j_delta in [-1, 0, 1]:
>                 if (i_delta, j_delta) == (0, 0):
>                     continue
>                 try:
>                     # To deal with the edges of the matrix, where the
>                     # deltas can take us out of bounds.
>                     if self.world[i+i_delta, j+j_delta]:
>                         live_count += 1
>                 except KeyError:
>                     pass
>         return live_count
> 
>     def cell_will_change(self, cell):
>         '''Returns True if a cell will change, False otherwise.'''
>         change = False
>         if self.world[cell] and not self.count_neighbours(cell) in (2,3):
>             change = True
>         if not self.world[cell] and self.count_neighbours(cell) == 3:
>             change = True
>         return change
> 
>     def get_changed_cells_list(self):
>         '''Returns a list of cells that will change in the next generation.'''
> 
>         changed_cells_list = []
>         for c in self.world:
>             if self.cell_will_change(c):
>                 changed_cells_list.append(c)
>         return changed_cells_list
> 
>     def update_world(self):
>         '''Produces the next generation world.'''
>         self.current_generation += 1
>         changed_cells_list = self.get_changed_cells_list()
>         for c in changed_cells_list:
>             self.world[c] = not self.world[c]
> 
>     def run_world(self):
>         while self.current_generation < self.total_generations:
>             time.sleep(self.sleep_interval)
>             self.update_world()
>             self.print_world()
> 
> if __name__ == '__main__':
>     world = life_world(7, 7)
>     world.run_world()
> 
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> Tutor maillist  -  Tutor at python.org
> http://mail.python.org/mailman/listinfo/tutor


More information about the Tutor mailing list