[Tutor] lists of lists: more Chutes & Ladders!

spir denis.spir at gmail.com
Tue Dec 31 10:27:20 CET 2013


On 12/31/2013 06:59 AM, Keith Winston wrote:
> I resolved a problem I was having with lists, but I don't understand how! I
> caught my code inadvertently resetting/zeroing two lists TWICE at the
> invocation of the game method, and it was leading to all the (gamechutes &
> gameladders) lists returned by that method being zeroed out except the
> final time the method is called. That is: the game method below is iterated
> iter times (this happens outside the method), and every time gamechutes and
> gameladders (which should be lists of all the chutes and ladders landed on
> during the game) were returned empty, except for the last time, in which
> case they were correct. I can see that doing the multiple zeroing is
> pointless, but I can't understand why it would have any effect on the
> returned values. Note that self.reset() is called in __init__, so the lists
> exist before this method is ever called, if I understand properly.
>
>      def game(self, iter):
>          """Single game"""
>
>          self.gamechutes[:] = []   #when I take out these two slice
> assignments,
>          self.gameladders[:] = []   # then gamechutes & gameladders work
> properly
>
>          self.gamechutes = []  # these were actually in a call to
> self.reset()
>          self.gameladders = []
>
>          #.... other stuff in reset()
>
>          while self.position < 100:
>              gamecandl = self.move()
>              if gamecandl[0] != 0:
>                  self.gamechutes.append(gamecandl[0])
>              if gamecandl[1] != 0:
>                  self.gameladders.append(gamecandl[1])
>          return [iter, self.movecount, self.numchutes, self.numladders,
> self.gamechutes,            self.gameladders]
>
> I'm happy to share the rest of the code if you want it, though I'm pretty
> sure the problem lies here. If it's not obvious, I'm setting myself up to
> analyse chute & ladder frequency: how often, in a sequence of games, one
> hits specific chutes & ladders, and related stats.
>
> As always, any comments on style or substance are appreciated.

Well you have found the reason for weird behaviour, but there is one point you 
may have missed, I mean not fully understood, else you would probably never have 
coded that way.

Imagine there is somewhere in your code, before the resetting of either, some 
reference to this list; then you empty this list using the first idiom, the 
emptying instruction with [:], like:

original = [1, 2, 3]
# ...
ref_to_list = original      # not a copy
# ...
original[:] = []            # empty the same list

# assert checks something is true; else we get an AssertionError:
assert(ref_to_list is original)
assert(ref_to_list == [])

Now, replace the emptying instruction with:

original = []               # assigns another list

Now, assertions are false (both). `ref_to_list` actually still refers to the... 
original list; The folllowing is true in this version:

assert(ref_to_list == [1,2,3])

But the symbol `original` itself is not bound to this orignal list anymore (it's 
now a liar! a misnomer). In this version, we do not *modify* the list element 
(to empty it, for the matter), but *replace* it by a new one (empty right from 
the start), bound to `original`.

And as you ask for style comments, I would (this is subject to personal views):
* use '_' for multi-word ids: game_chutes
* say what the 'game' method computes and returns, in comment/doc and in its *name*
   (many think a true function, that produces a result, should be named after 
its product
   -- I share this view -- eg 'square' compute the square of its input)
* 'iter' is a clear misnomer: I would have never guessed if you didn't say it in 
text:
    use eg n_iters or number_iters or such [*]
(

Denis

[*] In addition, "iter" is also the name of a builtin function, like "print". It 
is rarely a good idea to reuse such names, but maybe you did not know it. Here 
is what it does (if you don't know yet about iterator objects, this will give 
you a fore-taste, but don't bother with that topic before you actually need them):

spir at ospir:~$ python3
Python 3.3.1 (default, Sep 25 2013, 19:29:01)
[GCC 4.7.3] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> iter
<built-in function iter>
>>> l = [1,2,3]
>>> it = iter(l)
>>> it
<list_iterator object at 0x7f5a63b41c50>
>>> for i in it: print(i)
...
1
2
3



More information about the Tutor mailing list