The Python Oracle

Unexpected list comprehension behaviour in Python

--------------------------------------------------
Rise to the top 3% as a developer or hire one of them at Toptal: https://topt.al/25cXVn
--------------------------------------------------

Music by Eric Matyas
https://www.soundimage.org
Track title: Over a Mysterious Island

--

Chapters
00:00 Unexpected List Comprehension Behaviour In Python
01:35 Accepted Answer Score 15
01:59 Answer 2 Score 4
02:37 Thank you

--

Full question
https://stackoverflow.com/questions/2256...

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#python #listcomprehension #languageimplementation

#avk47



ACCEPTED ANSWER

Score 15


The problem is that with return self.display you return a reference to this list (not a copy). So what you end up with is a list where each element is a reference to self.display. To illustrate, look at the following:

>>> a = [1,2]
>>> b = [a,a]
>>> b
[[1, 2], [1, 2]]
>>> a.append(3)
>>> b
[[1, 2, 3], [1, 2, 3]]

You probably want to use something like return self.display[:].




ANSWER 2

Score 4


Mind if i refactor this a bit?

def digit(n):
    for i in itertools.count():
        yield (i%n+1, not i%n)

But actually you don't need that one, if you implement the whole thing as a simple iterator:

def counter(digits, base):
    counter = [0] * digits

    def iterator():
        for total in itertools.count(1):
            for i in range(len(counter)):
                counter[i] = (counter[i] + 1) % base
                if counter[i]:
                    break
            print total, list(reversed(counter))
            yield list(reversed(counter))

    return iterator()

c = counter(2, 4)
print list(itertools.islice(c, 10))

If you want to get rid of the print (debugging, is it?), go with a while-loop.

This incindentally also solves your initial problem, because reversed returns a copy of the list.

Oh, and it's zero-based now ;)