Implementierung eines Stacks

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Antworten
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Vielleicht kann es ja jemand brauchen. Hab es so nebenher gemacht, während ich eine Programmdokumentation geschrieben hab.

Code: Alles auswählen

class Stack(object):
	def __init__(self):
		self.list = []

	def push(self, item):
		self.list.append(item)

	def pop(self):
		return self.list.pop()

	def top(self):
		return self.list[-1]

	def isEmpty(self):
		return not bool(len(self.list))
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

Eine Liste ist nicht unbedingt optimal für einen Stack. Besser wäre mit einer deque, die Gründe warum stehen auch dort.

Gruss
Benutzeravatar
BlackVivi
User
Beiträge: 762
Registriert: Samstag 9. Dezember 2006, 14:29
Kontaktdaten:

Die Methode isEmpty hält sich nicht an PEP8 (müsste is_empty heißen...)

Außerdem is sie ein bissel zu kompliziert.

Code: Alles auswählen

def is_empty(self):
    return not bool(self.list)
Das reicht schon. (Man könnte sogar bool() weglassen, aber... find's dann nich mehr ganz so eindeutig.)
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Hallo!

Wenn eine Liste als Stack genügt, dann könnte man von einer Liste ableiten.

Code: Alles auswählen

class Stack(list):

    def push(self, item):
        self.append(item)
    
    def top(self):
        return self.pop(0)
Im Falle der Liste als Basis, würde ich "is_empty" komplett weglassen. Das prüft man sowiso von außen.

Code: Alles auswählen

stack = Stack()
if stack:
    ...

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Soll ja der Spezifikation des ADTs Stack gerecht werden.
Deshalb halte ich mich auch nicht an die PEP8.
Und deshalb kann ich auch keine Liste ableiten, weil dann die anderen Operationen auch möglich sind.

Aber Danke für die optimierte isEmpty-Methode!

Edit: Wie gesagt, ist eh nur Spielerei für den Anhang der Doku. Im echten Programm benutze ich direkt eine Liste. Braucht also nicht so viel Wind um die ganze Sache machen ;)

Edit2: Und da meine maximale Stack-Größe bisher auf 20 begrenzt ist, spielt das mit der Komplexität (Gründe für deque) eigentlich auch keine Rolle...
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Ok, hab mir nochmal mein Programm angeschaut. Für den Einsatz von "deque" musste ich außer dem import genau eine Zeile ändern.
statt stack = [] steht jetzt stack = deque().
Da die Methoden gleich heißen, hab ich jetzt doch die deque genommen.
Jetzt muss ich nur in der Doku wieder einiges ändern *grml*

Naja hier noch der neue Stack-Code mit deque und Super-Komplexität^^

Code: Alles auswählen

#!/usr/bin/env python
from collections import deque

class Stack(object):
	def __init__(self):
		self.list = deque()
	def push(self, item):
		self.list.append(item)
	def pop(self):
		return self.list.pop()
	def top(self):
		return self.list[-1]
	def isEmpty(self):
		return not bool(self.list)
Edit: Und nein, ich werde auch nicht von der deque ableiten ;)
So lass ich es jetzt...
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

ice2k3 hat geschrieben:Edit: Und nein, ich werde auch nicht von der deque ableiten ;)
Warum nicht? Und warum nicht PEP8-konform?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

ice2k3 hat geschrieben:Soll ja der Spezifikation des ADTs Stack gerecht werden.
Deshalb halte ich mich auch nicht an die PEP8.
Und deshalb kann ich auch keine Liste ableiten, weil dann die anderen Operationen auch möglich sind.
Die Spezifikation bezieht sich eben auf meine Info-Vorlesung.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Und wo würde das vererben stören?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Weil zur Spezifikation z.B. nicht stack.popleft() gehört, sondern nur die 4 implementierten Methoden. Wenn ich das mit Generalisierung löse, werden alle Methoden mitvererbt, die ich gar nicht haben will.
Was ist daran nicht zu verstehen?!
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

ice2k3 hat geschrieben:Was ist daran nicht zu verstehen?!
Jetzt wo du es erklärt hast ist es verständlich. Davor nicht. Muss aber generell eine ziemlich miese Spezifikation sein, denn die Klasse hat ja auch so noch reihenweise Attribute die nicht zur Spezifikation gehören.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Spricht etwas gegen:

Code: Alles auswählen

In [44]: class Foo(object):
   ....:     def bar(self):
   ....:         pass
   ....:
   ....:

In [45]: f = Foo()

In [46]: f.bar()

In [47]: f.test()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)

/home/nelson/<ipython console> in <module>()

AttributeError: 'Foo' object has no attribute 'test'

In [48]: class Foo(object):
   ....:     def test(self):
   ....:         raise AttributeError()
   ....:
   ....:

In [49]: f = Foo()

In [50]: f.test()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)

/home/nelson/<ipython console> in <module>()

/home/nelson/<ipython console> in test(self)

AttributeError:
Ist zwar nicht wirklich sensationell, aber man könnte doch so die geerbten Methoden quasi verstecken? Aber vermutlich kommt man über die Elternklasse dann immer noch an die Methoden fällt mir grad ein ...

Wobei ich das Problem auch nicht so sehe: Solange die Methoden vorhanden sind, die man haben möchte / muss, stört es doch eigentlich nicht, wenn es auch noch "mehr" gibt?!? Das geht so ein wenig in die Richtung Java-Konzepte-Diskussion, die wir neulich im Offtopic hatten.
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Und wo ist das Problem, wenn ich die deque nicht als Basisklasse nehme?!
Außer dass ich die pop-Methode neu definieren muss. Und das ist ja wohl nicht der Rede wert.
Ja, die Diskussion wird langsam seltsam...

[ironie]Ohja, und ich hab natürlich zwei Instanzen im Speicher statt einem, DAS ist natürlich ein ausschlaggebendes Argument.[/ironie]
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

ice2k3 hat geschrieben:Und wo ist das Problem, wenn ich die deque nicht als Basisklasse nehme?!
Keines, es wäre halt eleganter. Scheint dir aber recht egal zu sein.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

ice2k3 hat geschrieben:Und wo ist das Problem, wenn ich die deque nicht als Basisklasse nehme?!
Es ist unelegant → schlechter Code.
Benutzeravatar
BlackVivi
User
Beiträge: 762
Registriert: Samstag 9. Dezember 2006, 14:29
Kontaktdaten:

ice2k3 hat geschrieben:[ironie]Ohja, und ich hab natürlich zwei Instanzen im Speicher statt einem, DAS ist natürlich ein ausschlaggebendes Argument.[/ironie]
Ist bei Vererbung nicht anders :P Nur eben nicht Explizit, quasi.

Und wie die beiden schon vorher gesagt haben:

Code: Alles auswählen

In [1]: import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
[...]
Außerdem soll man ja nicht mit verschlossenen Augen durch die Welt gehen. In Ordnung, es gibt eine Stackspezifikation - aber sie sagt nix darüber, dass man nicht mehr Methoden haben darf. Die werden halt dann nicht benutzt.. Außerdem sollte man nicht gegen die Sprache arbeiten, egal was irgendwelche Spezifikationen sagen. Stupide einem Unterrichtsstoff folgen ist _nie_ richtig. Wenn es deinen Dozenten/Professor nicht gefällt, dann steh drüber. Denn nur so erreicht man was im Leben...
BlackJack

Also ich finde es ehrlich gesagt eleganter *nicht* von `list` oder `dequeue` zu erben. Und ich würde auch bei `list` bleiben, solange nicht messbare Probleme damit entstehen.

Die vielen zusätzlichen Methoden, die nicht zu einem Stack gehören, gehören halt nicht zu einem Stack. Für einen Aussenstehenden, der nur ein Exemplar davon in die Hand bekommt, ist nicht ersichtlich welche der Methoden nun zur offiziellen API gehören, und welche nicht.

Das ist IMHO so ähnlich wie *-Importe bei Modulen. Solche die das tun, haben plötzlich einen Haufen mehr Inhalt und man kann in einer interaktiven Shell nicht mehr so einfach sehen was eigentlich in dem Modul definiert wird, und was nur zufällig dort ist und ignoriert werden muss.
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Endlich mal jemand, der auf meiner Seite ist...
Habe schon gedacht, ich stehe alleine da.

Auch wenn der Vorteil der deque wahrscheinlich nicht messbar ist, werde ich trotzdem diese Klasse einsetzen. Wenn ich in meiner Doku alias Praxisarbeit schreibe, dass ich diese aufgrund der Komplexität ausgewählt habe und noch ein Landau-Symbol dazu schreibe, macht das sicher einen guten Eindruck bei den Bewertern ;)
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

BlackJack hat geschrieben:Die vielen zusätzlichen Methoden, die nicht zu einem Stack gehören, gehören halt nicht zu einem Stack. Für einen Aussenstehenden, der nur ein Exemplar davon in die Hand bekommt, ist nicht ersichtlich welche der Methoden nun zur offiziellen API gehören, und welche nicht.
Was da zur offiziellen API gehört ist ja durch die Spezifikation durchaus dokumentiert. ``__class__`` gehört so gesehen ja auch nicht zur Spezifikation. Außerdem finde ich dass da eine "Stack IST_EINE Dequeue" Relation existiert.

Das würde ich nicht mit ``*-Importen`` vergleichen (denn man überschreibt ja durch das Vererben nichts unabsichtlicherweise) sondern eher mit der Diskussion letztens um das ``_``.

Letztendlich ist es mir aber ziemlich egal. :arrow:
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten