Frage

Ich glaube, ich werde von einer Kombination aus verschachtelten Scoping -Regeln und Listenfindungen gebissen. Jeremy Hyltons Blog -Beitrag ist suggestiv über die Ursachen, aber ich verstehe die Implementierung von CPython nicht wirklich, um herauszufinden, wie ich mich umgehen kann.

Hier ist ein (überkompriziertes?) Beispiel. Wenn die Leute eine einfachere haben, die es demonstriert, würde ich es gerne hören. Das Problem: Die List -Verständnisse unter Verwendung von Next () sind mit dem Ergebnis aus der letzten Iteration gefüllt.

bearbeiten: Das Problem:

Was genau ist damit los und wie kann ich das beheben? Muss ich einen Standard für die Schleife verwenden? Klar in der Funktion wird die richtige Häufigkeit ausgeführt, aber die Liste der Liste Finale Wert anstelle des Ergebniss jeder Schleife.

Einige Hypothesen:

  • Generatoren?
  • Faule Füllung von Listenverständnissen?

Code

import itertools
def digit(n):
    digit_list = [ (x,False) for x in xrange(1,n+1)]
    digit_list[0] = (1,True)
    return itertools.cycle ( digit_list)
>>> D = digit(5)
>>> [D.next() for x in range(5)]
## This list comprehension works as expected
[(1, True), (2, False), (3, False), (4, False), (5, False)]
class counter(object):
    def __init__(self):
        self.counter = [ digit(4) for ii in range(2) ] 
        self.totalcount=0
        self.display = [0,] * 2
    def next(self):
        self.totalcount += 1
        self.display[-1] = self.counter[-1].next()[0]
        print self.totalcount, self.display
        return self.display

    def next2(self,*args):
        self._cycle(1)
        self.totalcount += 1
        print self.totalcount, self.display
        return self.display

    def _cycle(self,digit):
        d,first = self.counter[digit].next()
        #print digit, d, first
        #print self._display
        self.display[digit] = d
        if first and digit > 0:
            self._cycle(digit-1)


C = counter()
[C.next() for x in range(5)]
[C.next2() for x in range(5)]

AUSGANG

In [44]: [C.next() for x in range(6)]
1 [0, 1]
2 [0, 2]
3 [0, 3]
4 [0, 4]
5 [0, 1]
6 [0, 2]
Out[44]: [[0, 2], [0, 2], [0, 2], [0, 2], [0, 2], [0, 2]]

In [45]: [C.next2() for x in range(6)]
7 [0, 3]
8 [0, 4]
9 [1, 1]
10 [1, 2]
11 [1, 3]
12 [1, 4]
Out[45]: [[1, 4], [1, 4], [1, 4], [1, 4], [1, 4], [1, 4]]

# this should be:  [[0,3],[0,4]....[1,4]] or similar
War es hilfreich?

Lösung

Das Problem ist das mit return self.display Sie geben eine zurück Hinweis auf diese Liste (keine Kopie). Was Sie also haben, ist eine Liste, in der jedes Element ein Verweis auf sich selbst ist. Display. Schauen Sie sich die folgende an:

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

Sie möchten wahrscheinlich so etwas verwenden return self.display[:].

Andere Tipps

Wenn ich das ein bisschen wieder aufrefiziere?

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

Aber tatsächlich brauchen Sie das nicht, wenn Sie das Ganze als einfache Iterator implementieren:

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))

Wenn Sie den Druck loswerden möchten (Debugging, oder?), Gehen Sie mit einer Weile Schleife.

Dies löst auch Ihr anfängliches Problem, weil reversed Gibt eine Kopie der Liste zurück.

Oh, und es basiert jetzt auf Null;)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top