Plattformunabhängigkeit und getch(curses)
"Das war schon immer so" kann man nicht kritisieren? Insbesondere bei einer Version die explizit mit Rückwärtskompatibilität bricht!? Leere `dict`\s mit ``{:}`` wäre IMHO durchaus möglich gewesen um den weg für ``{}`` als leeres `set` freizumachen.
Ach bitte, du weißt, was ich meine. "{}" als leeres Wörterbuch ist schon lange Bestandteil der Python-Syntax. Jeder Python-Programmierer kennt das, jeder erwartet das.BlackJack hat geschrieben:"Das war schon immer so" kann man nicht kritisieren? Insbesondere bei einer Version die explizit mit Rückwärtskompatibilität bricht!?
Konsistenz aber ist kein Selbstzweck, sondern dient immer den Verständnis. Code wird aber nicht unbedingt verständlicher, wenn man lang vertraute Formen im Sinne der Konsistenz mit einer neuen Bedeutung belegt. Ein solcher Schritt schafft allenfalls Verwirrung, und es benötigt dann wieder einige Zeit, bis sich jeder daran gewöhnt hat.
"A Foolish Consistency is the Hobgoblin of Little Minds".
Die Alternative wäre gewesen alles so zu lassen wie es ist - oder etwas in der Art wie man es auch schon von Strings kennt:
MFG HerrHagen
EDIT: Oh, BlackJack war schneller - und hatte offensichtlich die gleiche Idee
Code: Alles auswählen
empty_set = s{}
empty_dic = {}
Genau darin liegt das Problem. {} ist ein leeres dict, obwohl es der Logik nach nun eher ein set sein müsste. Konsistent hätte das leere dict so: {:} und das leere set so {} ausgesehen. "Das war schon immer so" ist ganz sicher kein Argument, schließlich ging es ja in Python 3 darum solche Inkonsistenzen auszuräumen. Gerade bei dict/et comprehensions finde ich die neue Syntax ein wenig unübersichtlich.Die Umsetzung ist allenfalls etwas inkonsistent, da "{}" keine leere Menge, sondern ein leeres Wörterbuch erzeugt, aber das war bei Python schon immer so, und ist daher eigentlich kein Kritikpunkt.
MFG HerrHagen
EDIT: Oh, BlackJack war schneller - und hatte offensichtlich die gleiche Idee
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Jeder Python 2.x Programmierer, ja. Aber man kann kaum erwarten dass das ewig so bleiben würde. Schließlich nehme ich an, dass auch Neulinge auf Python 3.0 einsteigen und die haben für sowas kein Verständnis. Ebenso wie alle anderen in ein paar Jahren, wenn 2.x an Bedeutung verliert.lunar hat geschrieben:Ach bitte, du weißt, was ich meine. "{}" als leeres Wörterbuch ist schon lange Bestandteil der Python-Syntax. Jeder Python-Programmierer kennt das, jeder erwartet das.BlackJack hat geschrieben:"Das war schon immer so" kann man nicht kritisieren? Insbesondere bei einer Version die explizit mit Rückwärtskompatibilität bricht!?
Damit lässt sich nicht alles rechtferigen. Sonst müssten wir ja sagen dass die Twisted-Libs gut designt sindlunar hat geschrieben:"A Foolish Consistency is the Hobgoblin of Little Minds".
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Also keine Literalform für Mengen? Das wäre aber auch inkonsistent, den jede andere elementare Container-Klasse (Tupel, List, Wörterbuch) hat eine Literalform Außerdem ziemlich unkomfortabel, aber darum gehts ja offenbar gerade nicht.HerrHagen hat geschrieben:Die Alternative wäre gewesen alles so zu lassen
Das wäre sogar noch inkonsistenter als der Verzicht. Zum einen hat kein anderes Containerliteral Typpräfixe, zum anderen ändern diese bei skalaren Literalen zwar Typ, nicht aber Verhalten von Objekten. Ob ich nun Zahlen mit oktal- oder hexademzimal-Präfix versehe, oder Zeichenkette mit "u" oder "r", es ändert sich nichts an deren Verhalten: Es bleibt immer eine Zahl, und immer eine Zeichenkette.wie es ist - oder etwas in der Art wie man es auch schon von Strings kennt:Code: Alles auswählen
empty_set = s{} empty_dic = {}
Das aus einem leeren Wörterbuch aber durch den magischen Buchstaben "s" eine Menge wird, also ein sich völlig anders verhaltendes Objekt, passt da nicht recht ins Schema.
Mit der Konsistenz ist eben so eine Sache
Siehe meine Antwort auf BlackJacks Posting ...Genau darin liegt das Problem. {} ist ein leeres dict, obwohl es der Logik nach nun eher ein set sein müsste. Konsistent hätte das leere dict so: {:} und das leere set so {} ausgesehen.
Was wäre denn die konsistente(!) und übersichtliche Alternative? Typpräfixe sind inkonsistent, außerdem wird der Code dadurch nur bedingt übersichtlicher: Wenn du einen Doppelpunkt nicht siehst, dann wirst du auch das Präfix nicht sehen. Der Verzicht ist ebenfalls inkonsistent, außerdem auch unkomfortabel. Und andere Klammern gibt es auch nicht wirklich ...Gerade bei dict/et comprehensions finde ich die neue Syntax ein wenig unübersichtlich.
Und ich hatte ihm sogar schon geantwortet ...EDIT: Oh, BlackJack war schneller - und hatte offensichtlich die gleiche Idee
Anfänger haben für vieles kein Verständnis ... z.B. warum "('foo')" die Zeichenkette 'foo' erzeugt und kein einelementiges Tupel.Leonidas hat geschrieben:Jeder Python 2.x Programmierer, ja. Aber man kann kaum erwarten dass das ewig so bleiben würde. Schließlich nehme ich an, dass auch Neulinge auf Python 3.0 einsteigen und die haben für sowas kein Verständnis. Ebenso wie alle anderen in ein paar Jahren, wenn 2.x an Bedeutung verliert.
Wieso? Bei Bytes/Unicode ist das doch recht ähnlich. Zudem wäre man so zukunftssicher gewesen. Beispielsweise werden ja nun recht häufig namedtuple eingesetzt. Was passiert wenn man die gerne in die Syntax integriert hätte? Oder irgendein anderer colllection Typ? Mehr Klammern gibt die Tastatur nun mal nicht her. Mit einem Präfix wäre das ganze recht einfach.Das aus einem leeren Wörterbuch aber durch den magischen Buchstaben "s" eine Menge wird, also ein sich völlig anders verhaltendes Objekt, passt da nicht recht ins Schema.
Man hätte das set ja auch mit eckigen Klammern und Präfix machen können. Es ähnelt ja eher einer Liste als einem Dictionary. Dann ist die Diskrepanz zwischen kleiner Änderung in Syntax - große Auswirkungen auf Verhalten nicht ganz so groß. Ein frozenset wäre dann entsprechend mit runden Klammern, äquivalent zum Verhältnis Tuple/Liste.
Code: Alles auswählen
empty_set = s[]
empty_frozenset = s()
Code: Alles auswählen
empty_set = s{}
empty_frozenset = f{}
str und byte stellen geordnete Sequenzen dar und implementieren das Listen-Protokoll. Zwischen beiden Typen besteht darüber hinaus ein logischer Zusammenhang, da sie ineinander überführt werden können.
set() und dict() dagegen sind zwei völlig unterschiedliche Typen, die in keinem unmittelbaren Zusammenhang stehen und völlig verschiedene Protokolle implementieren. Das ist also mitnichten vergleichbar.
Auch sind Mengen keine Listen und ähneln ihnen auch nicht. MengenSie sind ungeordnet, und unterstützen daher weder Slicing noch Sortierung noch Einfügen. Die einzige Operation, die auf Listen und Mengen gleichermaßen funktioniert, ist die Iteration.
set() und dict() dagegen sind zwei völlig unterschiedliche Typen, die in keinem unmittelbaren Zusammenhang stehen und völlig verschiedene Protokolle implementieren. Das ist also mitnichten vergleichbar.
Auch sind Mengen keine Listen und ähneln ihnen auch nicht. MengenSie sind ungeordnet, und unterstützen daher weder Slicing noch Sortierung noch Einfügen. Die einzige Operation, die auf Listen und Mengen gleichermaßen funktioniert, ist die Iteration.
Dazu sage ich jetzt mal nichtsEDIT: OK, das ist natürlich Quatsch, weil dann nicht mehr zwischen Funktionsaufruf/ Set unterschieden werden könnte. Dann halt doch so:Code: Alles auswählen
empty_set = s{} empty_frozenset = f{}
Und deswegen gibt man ihnen die, bis auf einem Doppelpunkt in der Mitte, die gleiche Syntax? Genau das ist doch das Problem!set() und dict() dagegen sind zwei völlig unterschiedliche Typen, die in keinem unmittelbaren Zusammenhang stehen und völlig verschiedene Protokolle implementieren. Das ist also mitnichten vergleichbar.
Code: Alles auswählen
>>> {1,2,3} # set
>>> {1,2} # set
>>> {1} # set
>>> {} # dict !?!?
Code: Alles auswählen
>>> s{1,2,3} # set
>>> s{1,2} # set
>>> s{1} # set
>>> s{} # set
MFG HerrHagen
Ja, das wäre eine gute Lösung gewesen. Wer sich an Python 2.x gewöhnt hat, gewöhnt sich irgendwann um. Immerhin gibt es auch anderes umzugewöhnen, sei es nun die Division mittels "/" oder range() oder input() oder oder ... , die plötzlich etwas anderes machen.HerrHagen hat geschrieben: {} ist ein leeres dict, obwohl es der Logik nach nun eher ein set sein müsste. Konsistent hätte das leere dict so: {:} und das leere set so {} ausgesehen.
Warum also nicht mit noch mehr alten Zöpfen brechen und {} als leere Menge und {:} als leeres dict einführen?
Es gibt spitze Klammern (größer/kleiner).HerrHagen hat geschrieben:Mehr Klammern gibt die Tastatur nun mal nicht her.
(ohne jetzt dafür plädieren zu wollen, diese für den besagten Fall einzusetzen)
BrainF**K-Interpreter können ja auch ziemlich kurz sein: https://www.spoj.pl/ranks/BRAINF_K/
An Perl (nur 132 Zeichen!) kommt man mit Python aber wohl nicht heran.
An Perl (nur 132 Zeichen!) kommt man mit Python aber wohl nicht heran.
Ich möchte mich noch bei allen recht herzlich bedanken, die dazu beigetragen haben meinen Thread vollzu"spam"men".
Gibts eigentlich Benchmarks mit dem man testen kann, wie schnell der Interpreter ist? Am bestens mit Vergleichwerten. Das 99 Bottle Programm ist recht I/O(wobei mehr O) intensiv. Ich hätte da noch ein paar Ideen in der Hinterhand. Diese bringen aber keine aussagekräftigen Werte, wenn das Programm in 3s(auf einen x41) schon beendet wird.
Und zu den Wettbewerbungen rundum die legendäre Programmiersprache Brainf***, wichtiger sind für mich die Lesbarkeit, Performanz, Speicherverbrauch, Plattformunabhängigkeit am wenigsten interessieren mich die Größe des Quellcodes oder irgendwelche Hacks mit i386 Opcodes.
Gibts eigentlich Benchmarks mit dem man testen kann, wie schnell der Interpreter ist? Am bestens mit Vergleichwerten. Das 99 Bottle Programm ist recht I/O(wobei mehr O) intensiv. Ich hätte da noch ein paar Ideen in der Hinterhand. Diese bringen aber keine aussagekräftigen Werte, wenn das Programm in 3s(auf einen x41) schon beendet wird.
Und zu den Wettbewerbungen rundum die legendäre Programmiersprache Brainf***, wichtiger sind für mich die Lesbarkeit, Performanz, Speicherverbrauch, Plattformunabhängigkeit am wenigsten interessieren mich die Größe des Quellcodes oder irgendwelche Hacks mit i386 Opcodes.
Das Problem wäre dann aber das alles nur unter best. Vorraussetzungen funktioniert. Die gängiste Methode wäre dann den Code umwandeln in Assembler und ihn lokal übersetzen lassen & ausführen.
Ich dachte da mehr an einen Präprozessor oder JIT Optimierung. Ein kleines Beispiel:
BF: +++++ 5mal lesen & auswerten
OBF: 5+ 2mal lesen & auswerten
-----
Ergebnis: sauschnell
Ich dachte da mehr an einen Präprozessor oder JIT Optimierung. Ein kleines Beispiel:
BF: +++++ 5mal lesen & auswerten
OBF: 5+ 2mal lesen & auswerten
-----
Ergebnis: sauschnell
Also ich würde mir da wohl die Arbeit sparen, denn BF lässt sich *sehr* einfach nach C übersetzen, und ein optimierender C-Compiler sollte aus 5× inkrementieren nacheinander *eine* Addition machen.
Stichwort Compiler: In einem anderen Thread hatte ich mal einen BF-Compiler geschrieben, der dann nochmals von mitsuhiko in Eleganz und Kürze übertroffen wurde.
Stefan
Stefan
@BlackJack: Sicher kann das der gcc optimieren, viel mehr aber nicht. Am Muster, Ausführen irgendwelcher Anweisungen kommt er nicht dran vorbei, da er(Compiler) niemals weiß was das Programm letztendlich für eine Aufgabe hat, halten sich die Optimierungen in Grenzen. z.B. Zählschleifen um eine Zelle auf einen bestimmten Wert zu setzen, könnte man zu einfach "Wert setzen" optimieren. Erkennt ein Compiler so etwas?
@sma: Ich dachte, das getch und std.read nicht das gleiche Verhalten haben. Siehe Posting 2 und 3. Frage. Kannst du mir sagen wie ich dein Code starte bzw. einbinde? Auch bekomme ich einen Syntaxfehler in deiner letzten Zeile!?
@sma: Ich dachte, das getch und std.read nicht das gleiche Verhalten haben. Siehe Posting 2 und 3. Frage. Kannst du mir sagen wie ich dein Code starte bzw. einbinde? Auch bekomme ich einen Syntaxfehler in deiner letzten Zeile!?
Rufe `run_brainfuck("....Programm...")` auf. Wenn du einen Syntaxfehler bekommst, hast du wahrscheinlich Python 3. Mache Klammern um das `exec`, da es kein Statement mehr ist sondern eine Funktion geworden ist.
Das sys.stdin.read(1) Zeichen nicht unmittelbar liest, ist mir bekannt, war aber für das Beispiel egal. Es gibt halt keinen plattformunabhängigen Weg, ein einzelnes Zeichen einzulesen, da Python für Windows keine curses-Emulation mitbringt.
Stefan
Das sys.stdin.read(1) Zeichen nicht unmittelbar liest, ist mir bekannt, war aber für das Beispiel egal. Es gibt halt keinen plattformunabhängigen Weg, ein einzelnes Zeichen einzulesen, da Python für Windows keine curses-Emulation mitbringt.
Stefan