[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