[Tutor] Improving My Simple Game Code for Speed, Memory and Learning

Steven D'Aprano steve at pearwood.info
Sun Jan 4 11:07:35 CET 2015


On Sat, Jan 03, 2015 at 09:57:20PM -0500, Dave Angel wrote:
> On 01/03/2015 06:10 PM, WolfRage wrote:
> >On 01/03/2015 04:42 PM, Dave Angel wrote:
> >>self.transposed_grid = list( zip(*self.grid) )
> >This results in the same thing with or with out the list() wrapper. Using
> >Python 3.4.0 (default, Apr 11 2014, 13:05:11)
> >[GCC 4.8.2] on linux
> 
> In Python 3, zip() returns an iterator.  So you can traverse it once.  I 
> don't believe the second time is guaranteed to be the same.  A list is 
> what you want.

You cannot traverse iterators twice. Once they are exhausted, they stay 
exhausted. Technically you can write an iterator that can be re-used, 
but according to the iterator specification that is officially called 
"broken".

Specifically in the case of zip, if its arguments are sequences such as 
lists or tuples, then you can call zip(a, b) twice and the resulting 
iterator will always be in the same order. But if the arguments are sets 
or dicts, then Dave is correct, the language does not guarantee that the 
zip iterator will have the same order each time. But that's not because 
of zip(), that's because the order of sets and dicts is not guaranteed 
to be the same each time.

That is, given a set some_set, if you make two lists from it:

a = list(some_set)
b = list(some_set)  # The same set.

the language doesn't guarantee that a == b, as the order *could* be 
different each time. But in practice, I don't know any Python 
implementation *yet* where they actually are different, although I 
expect that there will be in the future.

The reason is that there are some Denial Of Service attacks against 
Python related to being able to predict the order of dictionaries. 
Python 3.3 changes the order from one interpreter session to the next, 
but that's not actually enough to prevent the DOS attack, so I expect 
that future versions may eventually fully randomize the output:


Python 2.7 has an arbitrary, but predictable, output, which is the same 
from one run to the next:

[steve at ando ~]$ python2.7 -c "print set(['ape', 'bat', 'cat', 'dog', 'fox'])"
set(['bat', 'cat', 'fox', 'dog', 'ape'])
[steve at ando ~]$ python2.7 -c "print set(['ape', 'bat', 'cat', 'dog', 'fox'])"
set(['bat', 'cat', 'fox', 'dog', 'ape'])

Python 3.3 changes the order from one run to the next:

[steve at ando ~]$ python3.3 -c "print({'ape', 'bat', 'cat', 'dog', 'fox'})"
{'cat', 'fox', 'dog', 'bat', 'ape'}
[steve at ando ~]$ python3.3 -c "print({'ape', 'bat', 'cat', 'dog', 'fox'})"
{'cat', 'ape', 'bat', 'fox', 'dog'}


-- 
Steve


More information about the Tutor mailing list