Hallo Freunde,
da ich noch relativ neu auf Python-Gebiet bin habe ich folgende Frage.
Ich habe eine eigene Linkliste entworfen und ich stehe nun vor der Problematik, wie ich am geschicktesten die Iteratoren unterbringe. Da wäre zum einen die __iter__() Methode die ich in die Klasse integriere. Das funzt ganz gut nur mit der Einschränkung, dass ich nur GoF iterieren kann. Gibt es hier eine Möglichkeit das anders zu gestallten? z.B. rückwärts iterieren?
Als alternative habe ich ein seperates Modul mit einer vielzahl - so wie ich mir das auch ohnehin vorgestellt habe - an Funktionen.
forwärts/rückwärts iterieren
mit/ohne prefetch
usw.
Was ist jetzt nun am elegantesten?
Viele Grüße,
Chris
Generatoren & Iteratoren
- Defnull
- User
- Beiträge: 778
- Registriert: Donnerstag 18. Juni 2009, 22:09
- Wohnort: Göttingen
- Kontaktdaten:
Zu wenig Input.
Woher kommen die Links? SQL?
Wie hast du __iter__ implementiert?
Woher kommen die Links? SQL?
Wie hast du __iter__ implementiert?
Bottle: Micro Web Framework + Development Blog
hallo Defnull,
ich meine verkettete Listen...
n1 n2 n3
p <- p <- p
n -> n -> n
vg chris
welche links?? SQL ???Woher kommen die Links? SQL?
ich meine verkettete Listen...
n1 n2 n3
p <- p <- p
n -> n -> n
Wie hast du __iter__ implementiert
Code: Alles auswählen
def __iter__(self):
self.current = self.head
return self
def next(self):
if self.current == None:
raise StopIter....
else:
self.current = self.current.next
return self.current
be or not to be
- b.esser-wisser
- User
- Beiträge: 272
- Registriert: Freitag 20. Februar 2009, 14:21
- Wohnort: Bundeshauptstadt B.
Benutz' doch ein extra Iterator-objekt:
hth, Jörg
Code: Alles auswählen
class Iterator(object):
def __init__(self, node, forward=True):
self.current = node
self.forward=True
def next(self):
if self.forward:
#...
class LinkedList(...):
def __iter__(self):
return Iterator(self.head)
# rückwärts & extras brauchen zus. Methoden
#oder gehören in abgeleitete Klassen
Wir haben schon 10% vom 21. Jahrhundert hinter uns!
@ b.esser-wisser
ja so hab ich es ja vor. nur wollte ich die syntax beim aufruf von
schön einfach halten. einfach rückwärts iterieren geht hier nicht.
dachte da an
muss doch irgendwie möglich sein an die __iter__ methode ein arg zu übergeben, das dann den richtigen iterator ansteuert.
momentan habe ich es mit generatoren gelöst.
nur ists hier immer blöd aus dem modulnamensraum heraus die methode aufzurufen. sprich mit
und dann mit
anzustoßen.
Ich dachte das kann man irgendwie einfach mit:
machen[/code]
ja so hab ich es ja vor. nur wollte ich die syntax beim aufruf von
Code: Alles auswählen
for n in mylinkedlist:
pass # do anything
dachte da an
Code: Alles auswählen
for n in mylinkedlist[::-1]:
pass # do anything
momentan habe ich es mit generatoren gelöst.
Code: Alles auswählen
def list_for_each(list, item = None):
''' list_for_each() - iterate over a list '''
head = list.head
item = (item.next if item != None else list.head.next)
while item != head:
yield item
item = item.next
def list_for_each_prev(list, item = None):
''' '''
head = list.head
item = (item.prev if item != None else list.head.prev)
while item != head:
yield item
item = item.prev
Code: Alles auswählen
from mylinkedlist import iterators
Code: Alles auswählen
for n in iterators.list_for_each(meineZuDurchlaufendeListe):
pass # do anything
Ich dachte das kann man irgendwie einfach mit:
Code: Alles auswählen
for n in meineLinkedListe: pass
be or not to be
- b.esser-wisser
- User
- Beiträge: 272
- Registriert: Freitag 20. Februar 2009, 14:21
- Wohnort: Bundeshauptstadt B.
Nein, ich dachte da an eine Methode:Code: Alles auswählen
for n in iterators.list_for_each(meineZuDurchlaufendeListe): pass # do anything
Code: Alles auswählen
for n in meine_zu_durchlaufende_liste.backwards():
pass
hth, Jörg
ps.:
llist[::1] geht über __getitem__, __setitem__ und sog. slice-Objekte, ist aber wohl erstmal nichtso wichtig
Wir haben schon 10% vom 21. Jahrhundert hinter uns!
@maxwell: Gehört Deine `__iter__`-Methode zur `next()`-Methode? Dann ist sie ungewöhnlich, weil ein `iter()` angewendet auf einen Iterator eben jenen Iterator *unverändert* zurückgeben sollte, und nicht wieder von vorne anfangen sollte.
Ansonsten würde ich das wie folgt lösen:
Das `__reversed__()` von der `reversed()`-Funktion aufgerufen wird ist zwar AFAIK nicht dokumentiert, scheint aber bei CPython immer der Fall zu sein.
Ansonsten würde ich das wie folgt lösen:
Code: Alles auswählen
class LinkedList(object):
def __iter__(self):
item = self.head
while item is not None:
yield item
item = item.next
def __reversed__(self):
item = self.last
while item is not None:
yield item
item = item.previous
-
- User
- Beiträge: 996
- Registriert: Mittwoch 9. Januar 2008, 13:48
Warum willst du überhaupt einen Iterator für eine Liste implementieren? Die ist doch schon iterierbar. Und für Rückwärts-Iterieren gibts den `reverse`-Iterator.
Gruß
Gruß
@lunar: Jaaa, in der Doku für 2.6. Wer benutzt denn schon so etwas Neumodisches!? Bei 2.5 ist das noch nicht dokumentiert, funktioniert aber trotzdem. Zumindest bei CPython.
@all
just in time nach einer argen Google-Orgie bin ich auf
__reversed__() gestoßen. wollte gerade noch mal schauen ob noch jemand geantwortet hat und zack... klasse sache.
aber leider habe ich immer noch bauchschmerzen. das gefällt mir alles noch nicht so ganz.
__reversed__() nimmt keine args an.
ich möchte jedoch gerne auch einen startknoten angeben können.
bsp.
ich denke das geht dann nur über slices...
vielen dank euch alle!
vg chris
just in time nach einer argen Google-Orgie bin ich auf
__reversed__() gestoßen. wollte gerade noch mal schauen ob noch jemand geantwortet hat und zack... klasse sache.
aber leider habe ich immer noch bauchschmerzen. das gefällt mir alles noch nicht so ganz.
__reversed__() nimmt keine args an.
ich möchte jedoch gerne auch einen startknoten angeben können.
bsp.
Code: Alles auswählen
for i in myList(startKnoten): pass
vielen dank euch alle!
vg chris
be or not to be
Wenn myList ein Exemplar einer eigenen Klasse ist, dann gib der Klasse doch eine Methode die einen solchen Generator erzeugt:maxwell hat geschrieben:ch möchte jedoch gerne auch einen startknoten angeben können.
bsp.
Code: Alles auswählen
for i in myList(startKnoten): pass
Code: Alles auswählen
for i in myList.from_here(start_knoten)
Code: Alles auswählen
for i in from_here(myList, start_knoten)
Das Leben ist wie ein Tennisball.
@EyDu
so hab ichs momentan auch gemacht.
ich hätte es nur gerne beispielsweise über diesen
ausdruck geschafft:
so hab ichs momentan auch gemacht.
Code: Alles auswählen
def __iter__(self, i):
''' __iter__() - called if you iterate over list items with
"for" syntax '''
return self.forward()
def __reversed__(self):
''' '''
return self.backward()
def forward(self, item = None):
''' forward() - iterate over a list
@item: an entry from which we will start '''
head = self.head
item = (item.next if item != None else head.next)
while item != head:
yield item
item = item.next
def backward(self, item = None):
''' backward() - iterate over a list backwards '''
head = self.head
item = (item.prev if item != None else head.prev)
while item != head:
yield item
item = item.prev
ausdruck geschafft:
Code: Alles auswählen
for i in myList[5::]: pass
be or not to be
Dazu könntest du __getitem__ überschreiben. Das macht aber nur wirklich Sinn, wenn es echte Sequenzen sind, auf deren Elemente per Index zugegriffen werden kann. Alles andere wäre etwas verwirrend.
Das Leben ist wie ein Tennisball.