[Tutor] Criticism / Suggestions

Kent Johnson kent37 at tds.net
Thu Mar 3 12:50:23 CET 2005


Bill Kranec wrote:
> Hi Kent,
>> - The above code depends on roundlist which is not even defined 
>> anywhere in the module (just shown in the comment). This suggests 
>> again that the init code from the comment should be part of 
>> Tournament, and roundlist should be an attribute of Tournament. For a 
>> class to depend on some external variable is bad design and will break 
>> if the client code is in a different module from the class code 
>> (roundlist will be in a different namespace than Tournament).
> 
> 
> I have always been uneasy about this, but I wanted to be able to define 
> multiple tournament objects off of the same roundlist, to avoid 
> generating the list every time a new object is created.  I think what I 
> really want to do is have a separate Round class, from which Tournament 
> inherits the list of rounds.  I have started to implement something like 
> this in my most recent version, but haven't finished it yet.  ( I need 
> to understand class inheritance better. )

Composition is a better solution than inheritance. You can have a separate Round class and pass an 
instance of Round to the constructor for Tournament. Tournament can save the instance and refer to 
it as needed.

> 
>> - Tournament.next() doesn't return a value, it prints it directly. It 
>> should return self.key or str( self.key )
> 
> 
> Does the next() call in an iterator object need to return a value, and 
> if so, why? ( My reasoning was that next() only needs to increment the 
> iterator. )

To be an iterator it needs to return a value. This is the value that will be assigned to the loop 
variable.

For example, this class looks like an iterator but it doesn't return any value from next():
class not_an_iterator:
   def __init__(self):
     self.i = 0
   def __iter__(self):
     return self
   def next(self):
     if self.i < 5:
       print 'In next - i =', self.i
       self.i += 1
     else:
       raise StopIteration

If I use the class in a loop, the loop variable doesn't receive any value:

for i in not_an_iterator():
   print 'In loop - i =', i

prints:
In next - i = 0
In loop - i = None
In next - i = 1
In loop - i = None
In next - i = 2
In loop - i = None
In next - i = 3
In loop - i = None
In next - i = 4
In loop - i = None

For the loop variable to get the values from next(), I have to return it:

class is_an_iterator:
   def __init__(self):
     self.i = 0
   def __iter__(self):
     return self
   def next(self):
     if self.i < 5:
       print 'In next - i =', self.i
       old_i = self.i
       self.i += 1
       return old_i
     else:
       raise StopIteration


for i in is_an_iterator():
   print 'In loop - i =', i

prints:
In next - i = 0
In loop - i = 0
In next - i = 1
In loop - i = 1
In next - i = 2
In loop - i = 2
In next - i = 3
In loop - i = 3
In next - i = 4
In loop - i = 4

Incidentally, generator functions make it much easier to do this because they maintain state between 
calls automatically. I could write is_an_iterator as a generator like this:

def is_a_generator():
   i = 0
   while i < 5:
     yield i
     i += 1

for i in is_a_generator():
   print 'In loop - i =', i

Kent




More information about the Tutor mailing list