[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