Vielleicht hast du gerade einen KDE-Entwickler enttarntLeonidas hat geschrieben:Was soll das soll das ``k`` vor den Namen?
Kellerspeicher und umgekehrte Polnische Notation
hi,
@Leonidas:
Das `k` vor den Namen steht für "Keller-"
Ich wäre dir verbunden wenn du den Hinweis auf
die Namespaces nochmal in diesem Zusammenhang
erläutern könntest, kapier ich nämlich nicht
Wenn man den Kellerspeicher benutzt benutzt man
doch nur "alphabet":
MfG Jonas
@Leonidas:
Das `k` vor den Namen steht für "Keller-"
Ich wäre dir verbunden wenn du den Hinweis auf
die Namespaces nochmal in diesem Zusammenhang
erläutern könntest, kapier ich nämlich nicht
Wenn man den Kellerspeicher benutzt benutzt man
doch nur "alphabet":
Code: Alles auswählen
IMkeller = Kellerspeicher(alphabet=[1,2,3,4])
@jonas Die Aufgabenstellung löst dass wohl nicht so ganz und die Underscores bei push und pop gehören da nicht hin. Wenn überhaupt verwendet man zwei vor dem Namen aber hier will man ja von außen darauf zugreifen.
Zu den namespaces kellerspeicher.kalphabet vs. kellerspeicher.alphabet was erscheint dir sinnvoller?
Sinnvoller ist es hier von list zu erben und append(, pop) zu überschreiben.
Zu den namespaces kellerspeicher.kalphabet vs. kellerspeicher.alphabet was erscheint dir sinnvoller?
Sinnvoller ist es hier von list zu erben und append(, pop) zu überschreiben.
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Ja, aber welchen Sinn haben die ``k``? Es ist schon klar, dass ``alphabet`` zu ``Kellerspeicher`` gehört, es ist ja ein Attribut der Klasse.jonas hat geschrieben:Das `k` vor den Namen steht für "Keller-"
Ich wäre dir verbunden wenn du den Hinweis auf
die Namespaces nochmal in diesem Zusammenhang
erläutern könntest, kapier ich nämlich nicht
Du stimmst mir sicher zu, dass
Code: Alles auswählen
kellerspeicher = Kellerspeicher(['a'])
print kellerspeicher.kalphabet
Außerdem hast du da ein Mutables Objekt in der Signatur, das solltest du lassen, denn damit kannst du dir erstaunlich abstruse Fehler einfangen. So wird die Liste nur einmal erstellt und behält ihre Inhalte (statt immer auf [] gesetzt zu werden) - sowas willst du mit hoher Sicherheit nicht haben.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Hi,
@Leonidas:
Das komfortabler ist als
damit hast du Recht!
Aber das mit mutable object versteh ich noch nicht so ganz...
Meinst du meine Forensignatur?
MfG Jonas
@Leonidas:
Das
Code: Alles auswählen
print kellerspeicher.alphabet
Code: Alles auswählen
print kellerspeicher.kalphabet
Aber das mit mutable object versteh ich noch nicht so ganz...
Meinst du meine Forensignatur?
MfG Jonas
Code: Alles auswählen
In [87]: def foo(bar=[]):
....: return bar
....:
In [88]: a = foo()
In [89]: a.append('spam')
In [90]: foo()
Out[90]: ['spam']
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Nein, ich meine die Funktionssignatur von ``__init__``.jonas hat geschrieben:Aber das mit mutable object versteh ich noch nicht so ganz...
Meinst du meine Forensignatur?
Beispiel wo sowas zu Problemen führt:
Code: Alles auswählen
>>> class K(object):
... def __init__(self, args=[]):
... args.append(7)
... self.args = args
...
>>> k1 = K([1, 2, 3])
>>> k2 = K()
>>> k1.args
[1, 2, 3, 7]
>>> k2.args
[7]
>>> k3 = K()
>>> k3.args
[7, 7]
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
@jonas: Die doppelten Unterstriche vor und nach dem Namen verwendet man, wenn man eine der "magischen" Methoden implementiert, die eine besondere Bedeutung in der Sprache haben. Zum Beispiel um ein Objekt iterierbar zu machen, Operatoren zu überladen, oder Indexzugriff zu ermöglichen.
Nachtrag: Mit dem Kelleralphabet ist der Kellerspeicher für die Aufgabe nicht brauchbar, oder soll man da wirklich alle Zahlen übergeben, mit denen man rechnen können soll!?
Das Du Fehler mit ``print`` ausgibst, statt Ausnahmen auszulösen und sogar vorhandene Ausnahmen auf diese Weise "verschluckst", ist auch äusserst ungünstig.
Wenn das Programm etwas mit dem Kellerspeicher anstellt, was nicht in Ordnung ist, dann möchte man wohl kaum, dass das Programm sagt, hey hier ist was dummes passiert, und dann einfach weiter macht, als wenn nichts gewesen wäre.
Nachtrag: Mit dem Kelleralphabet ist der Kellerspeicher für die Aufgabe nicht brauchbar, oder soll man da wirklich alle Zahlen übergeben, mit denen man rechnen können soll!?
Das Du Fehler mit ``print`` ausgibst, statt Ausnahmen auszulösen und sogar vorhandene Ausnahmen auf diese Weise "verschluckst", ist auch äusserst ungünstig.
Wenn das Programm etwas mit dem Kellerspeicher anstellt, was nicht in Ordnung ist, dann möchte man wohl kaum, dass das Programm sagt, hey hier ist was dummes passiert, und dann einfach weiter macht, als wenn nichts gewesen wäre.
Hi,
@Leonidas:
Danke für den für mich persönlich hilfreichen Beitrag.
So etwas, wie in deinem Beispiel zu sehen, wäre natürlich
denkbar schlecht.
@Blackjack:
Danke für die hilfreiche Aufklärung über die "magischen" Methoden.
Mit
hast du natürlich Recht, auch das wäre denkbar ungünstig.
MfG Jonas
@Leonidas:
Danke für den für mich persönlich hilfreichen Beitrag.
So etwas, wie in deinem Beispiel zu sehen, wäre natürlich
denkbar schlecht.
@Blackjack:
Danke für die hilfreiche Aufklärung über die "magischen" Methoden.
Mit
Code: Alles auswählen
def irgendeinefunktion ():
try:
## tuEtwas...
except :
print """Hallo es gab irgendeinen Error aber
machen Sie sich mal keine Sorgen..."""
MfG Jonas
Ein einzelner Underscrore steht für die Dinge, die nicht "öffentlich" sein sollen, also von außen nicht benutzt werden sollen. Das ist aber nur eine Konvention, es wird also nichts erzwungen. Beispielsweise ist ein solcher Einsatz denkbar wenn du eine Klasse erstellst, die eine API implementiert (add_thing, remove_thing, do_somethign_important ...), und dann eine spezialisiertere Klasse erstellst, die von dieser abgeleitet ist. Willst du dort für Ordnung sorgen und etwas in eine eigene Methode auslagern, (zb "_build_important_structure"), kannst / solltest du den Underscore benutzen.
Doppelte Underscores werden einerseits für die "magischen Methoden" verwendet, andererseits kann man damit Dinge vor einem direkten Zugriff "schützen", der von außerhalb erfolgt (auch wenn sie nicht wirklich geschützt sind, man kommt noch über Umwege dran). "Offiziell" wird das aber nur dazu benutzt, um dem Mangel an Schreibweisen in Bezug auf einen bestimmten Namen zu vermeiden.
Praktisch braucht man das nie, außer für magische Methoden.
Doppelte Underscores werden einerseits für die "magischen Methoden" verwendet, andererseits kann man damit Dinge vor einem direkten Zugriff "schützen", der von außerhalb erfolgt (auch wenn sie nicht wirklich geschützt sind, man kommt noch über Umwege dran). "Offiziell" wird das aber nur dazu benutzt, um dem Mangel an Schreibweisen in Bezug auf einen bestimmten Namen zu vermeiden.
Praktisch braucht man das nie, außer für magische Methoden.
Hi.
@str1442:
MfG Jonas
@str1442:
Ist so eine spezialisierte Klasse z.B. Frog <=> Tkinter ?str1442 hat geschrieben:[...]Beispielsweise ist ein solcher Einsatz denkbar wenn du eine Klasse erstellst, die eine API implementiert (add_thing, remove_thing, do_somethign_important ...), und dann eine spezialisiertere Klasse erstellst, die von dieser abgeleitet ist.[...]
MfG Jonas
Frog kenne ich nicht.
Aber zb sowas:
Anwendung zb bei Objekten, die alle das gleiche Interface brauchen, aber nicht wissen
sollen, mit wem sie konkret agieren. Da ist "_do_sth_for_add" auch etwas, was diesem Objekt nicht bekannt ist. So kann man damit ganz banal verschiedene Parser für Dateitypen von einem "AbstractParser" ableiten, hoffe du verstehst das Prinzip.
Aber zb sowas:
Code: Alles auswählen
class AbstractCls(object):
def add(self):
pass
def request(self):
pass
class Cls(AbstractCls):
def add(self):
# Wichtiger Code
def _do_sth_for_add(self):
# Mach irgendwas und nutze Instanzvariablen dazu.
sollen, mit wem sie konkret agieren. Da ist "_do_sth_for_add" auch etwas, was diesem Objekt nicht bekannt ist. So kann man damit ganz banal verschiedene Parser für Dateitypen von einem "AbstractParser" ableiten, hoffe du verstehst das Prinzip.
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Naja, Abstrakte Klassen sind ja auch eher wenig gebräuchlich in Python (übrigens würden die dann eher NotImplementedError werfen, statt still und leise mit pass zurückzukehren). Das ist in Java (Interfaces) und Scala (Traits) etwas anders, dort definiert so eine Abstrakte Klasse eine API und die konkreten Klassen implementieren das. Ermöglicht also nichts was nicht in Python auch so schon möglich ist, soll aber wohl etwas mehr Konsistenz sicherstellen (auch wenn ich davon selbst eigentlich nicht besonders überzeugt bin).
Python 3 bietet noch ein etwas anderes Konzept, sogenannte Abstract Base Classes (ABC), aber das werd ich jetzt auch nicht groß diskutieren, bei Interesse einfach in die Dokumentation gucken.
Python 3 bietet noch ein etwas anderes Konzept, sogenannte Abstract Base Classes (ABC), aber das werd ich jetzt auch nicht groß diskutieren, bei Interesse einfach in die Dokumentation gucken.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
@jonas
Diese Abstrakten Klassen waren nur ein Beispiel. Die Methoden mit Unterstrichen stellen einfach Dinge da, die man nicht verwenden sollte. Meistens sind das Dinge, die die Klasse intern braucht. Abstrakte Klassen finde ich sind da ein gutes Beispiel, da es bei dem Beispiel egal ist, ob du noch 5 andere Unterklassen von "AbstractCls" hast, da alle die grundlegenden Operation von "AbstractCls" benutzen. Und genau diese sind nur anderen Objekten, die damit umgehen sollen, bekannt. Insofern macht es keinen Sinn, "_do_sth_with_add" ohne Unterstrich zu schreiben, da die Methode sowieso keinem anderem Objekt bekannt ist und somit auch nicht dafür gedacht ist, von diesen verwendet zu werden. Der Unterstrich signalisiert also "Achtung, verwende mich nicht, wenn du nicht weißt, was du machst!". In dem "AbstractCls" Beispiel könnte zb jemand diese Methode verwenden, weil er denkt, jede Klasse hätte sie und sie gehört zur "Api", obwohl sie ja nur zur "Cls" gehört. ---> "NameError: ....".
Generell sind Unterstriche zum Zweck, den DasIch auch schon erläutert hat, gedacht. Das ist nur ein Anwendungsfall.
@Leonidas:
Die einzelnen Methoden müssen ja nicht einfach durchgehen. In Java ist das afaik ja zwingend, das man eine interface Methode nicht weiter spezifieren kann. Aber wenn 5 verschiedene Parser beispielsweise sowieso immer ~3 Methoden haben, die komplett gleich sind, unterscheidet sich das nicht vom normalen Einsatzzweck von Vererbung.
Statt dem NotImplementedError gibts auch das NotImplemented Singleton. Wäre wohl besser, das zurückzugeben. Zumindest meine ich, das sollte man auch machen (hab da irgendwas, was mit Dive into Python in Verbindung steht, im Hinterkopf).
Diese Abstrakten Klassen waren nur ein Beispiel. Die Methoden mit Unterstrichen stellen einfach Dinge da, die man nicht verwenden sollte. Meistens sind das Dinge, die die Klasse intern braucht. Abstrakte Klassen finde ich sind da ein gutes Beispiel, da es bei dem Beispiel egal ist, ob du noch 5 andere Unterklassen von "AbstractCls" hast, da alle die grundlegenden Operation von "AbstractCls" benutzen. Und genau diese sind nur anderen Objekten, die damit umgehen sollen, bekannt. Insofern macht es keinen Sinn, "_do_sth_with_add" ohne Unterstrich zu schreiben, da die Methode sowieso keinem anderem Objekt bekannt ist und somit auch nicht dafür gedacht ist, von diesen verwendet zu werden. Der Unterstrich signalisiert also "Achtung, verwende mich nicht, wenn du nicht weißt, was du machst!". In dem "AbstractCls" Beispiel könnte zb jemand diese Methode verwenden, weil er denkt, jede Klasse hätte sie und sie gehört zur "Api", obwohl sie ja nur zur "Cls" gehört. ---> "NameError: ....".
Generell sind Unterstriche zum Zweck, den DasIch auch schon erläutert hat, gedacht. Das ist nur ein Anwendungsfall.
@Leonidas:
Die einzelnen Methoden müssen ja nicht einfach durchgehen. In Java ist das afaik ja zwingend, das man eine interface Methode nicht weiter spezifieren kann. Aber wenn 5 verschiedene Parser beispielsweise sowieso immer ~3 Methoden haben, die komplett gleich sind, unterscheidet sich das nicht vom normalen Einsatzzweck von Vererbung.
Statt dem NotImplementedError gibts auch das NotImplemented Singleton. Wäre wohl besser, das zurückzugeben. Zumindest meine ich, das sollte man auch machen (hab da irgendwas, was mit Dive into Python in Verbindung steht, im Hinterkopf).
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Ja, natürlich, aber funktionen die implementiert werden sollten, sollten Ausnahmen werfen. Sonst kann man sie auch einfach nicht implementieren und sich wundern warum dann an seltsamen Stellen ``None`` auftaucht. Ich finde es ähnlich wie du auch wenig sinnvoll wenn man in Interfaces nicht auch teile der Implementation haben kann. In Scalas Traits ist das anders, dort kann man in den Traits schon eine Implementation haben aber wenn man abstrakte Methoden des Traits nicht implementiert, wird es nicht kompilieren. Sowas kann man eben mit normalen Klassen und NotImplementedError auch haben; allerdings zur Laufzeit.str1442 hat geschrieben:Die einzelnen Methoden müssen ja nicht einfach durchgehen. In Java ist das afaik ja zwingend, das man eine interface Methode nicht weiter spezifieren kann. Aber wenn 5 verschiedene Parser beispielsweise sowieso immer ~3 Methoden haben, die komplett gleich sind, unterscheidet sich das nicht vom normalen Einsatzzweck von Vererbung.
Wieso? Statt ``None`` wird man dann ``NotImplemented`` im Programm umherfliegen haben und man darf dann den Debugger anwerfen um festzustellen welche Funktion nicht implementiert wurde. Da finde ich Ausnahmen wesentlich besser, weil eben der letzte Frame im Traceback der Funktion entspricht, die man überschreiben muss.str1442 hat geschrieben:Statt dem NotImplementedError gibts auch das NotImplemented Singleton. Wäre wohl besser, das zurückzugeben.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Wie gesagt, ich meine nur irgendwo mal was diesbezüglich gelesen zu haben. Ansonsten ist eine Ausnahme wohl besser geeignet, ja. Welchen Zweck hat aber NotImplemented, wenn man es sowieso nie zurückgeben sollte? Gibt ja dann eigentlich keinen Einsatzzweck mehr dafür.Wieso? Statt ``None`` wird man dann ``NotImplemented`` im Programm umherfliegen haben und man darf dann den Debugger anwerfen um festzustellen welche Funktion nicht implementiert wurde. Da finde ich Ausnahmen wesentlich besser, weil eben der letzte Frame im Traceback der Funktion entspricht, die man überschreiben muss.