Plattformunabhängigkeit und getch(curses)

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
lunar

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.
Anfänger haben für vieles kein Verständnis ... z.B. warum "('foo')" die Zeichenkette 'foo' erzeugt und kein einelementiges Tupel.
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

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.
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.
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()
EDIT: 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{}
lunar

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.
EDIT: 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{}
Dazu sage ich jetzt mal nichts :roll:
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

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.
Und deswegen gibt man ihnen die, bis auf einem Doppelpunkt in der Mitte, die gleiche Syntax? Genau das ist doch das Problem!

Code: Alles auswählen

>>> {1,2,3}  # set
>>> {1,2}    # set
>>> {1}      # set
>>> {}       # dict !?!?
Ein Präfix macht den Unterschied meiner Meinung nach halt deutlicher sichtbar, da man nun mal von links nach rechts ließt und so den Unterschied direkt erkennt und nicht mitten in der Zeile in seinen Gedanken "zurückspringen" muss.

Code: Alles auswählen

>>> s{1,2,3}  # set
>>> s{1,2}    # set
>>> s{1}      # set
>>> s{}       # set
Du hast natürlich damit recht, dass das nicht ganz sauber ist. Aber das ist ja keine der Lösungen (set() find ich noch am besten). Ich wollte nur ausdrücken, dass ich diese Neuerung für eine der weniger gelungenen in Python 3 halte.

MFG HerrHagen
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Du kannst schlecht Inkonsistenz kritisieren und eine Lösung präsentieren die noch inkonsistenter ist.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

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.
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.
Warum also nicht mit noch mehr alten Zöpfen brechen und {} als leere Menge und {:} als leeres dict einführen?
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

HerrHagen hat geschrieben:Mehr Klammern gibt die Tastatur nun mal nicht her.
Es gibt spitze Klammern (größer/kleiner). :)

(ohne jetzt dafür plädieren zu wollen, diese für den besagten Fall einzusetzen)
bords0
User
Beiträge: 234
Registriert: Mittwoch 4. Juli 2007, 20:40

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.
Benutzeravatar
darktrym
User
Beiträge: 784
Registriert: Freitag 24. April 2009, 09:26

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.
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Wenn du wirklich was performantes haben willst kommst du mit einem Interpreter nicht weit, ein Compiler ist da um einiges interessanter.
Benutzeravatar
darktrym
User
Beiträge: 784
Registriert: Freitag 24. April 2009, 09:26

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 :twisted:
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
BlackJack

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.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

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
Benutzeravatar
darktrym
User
Beiträge: 784
Registriert: Freitag 24. April 2009, 09:26

@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!?
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

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
Benutzeravatar
darktrym
User
Beiträge: 784
Registriert: Freitag 24. April 2009, 09:26

Hallo sma,
ich habe dein Code mit meinen gekreuzt um zu testen wie schnell deine Variante ist. Leider kommt er nur bis "91 Bottles of beer\nTake one down and pass it around"

Gibts eine python interne Beschränkung für deinen Code? Oder habe ich einen Fehler gemacht?

Nochmals "unseren" Code:

Code: Alles auswählen

import sys
import platform

def compile_brainfuck(src):
    program = ["def bf():", " import sys", " cells, ptr = [0] * 1000, 0"]
    indent = 1
    def emit(line): program.append(" " * indent + line)
    for s in src:
        if s == ">": emit("ptr += 1")
        elif s == "<": emit("ptr -= 1")
        elif s == "+": emit("cells[ptr] += 1")
        elif s == "-": emit("cells[ptr] -= 1")
        elif s == ".": emit("sys.stdout.write(chr(cells[ptr]))")
        elif s == ",": emit("cells[ptr] = ord(sys.stdin.read(1))")
        elif s == "[": emit("while cells[ptr]:"); indent += 1
        elif s == "]": emit("pass"); indent -= 1
    indent -= 1; emit("bf()")
    return "\n".join(program)
   

try:
	filehandler = open(sys.argv[1],"r")
except IndexError:
	print("wrong syntax: no source file")
	exit(-1)
	
code = ""
brainfucksymbols = ('+','-','>','<','.',',','[',']')
while True:
	line = filehandler.readline()
	if line == "":
		break
	for char in line:
		if char in brainfucksymbols:
			code+=char

exec (compile_brainfuck(code)) 
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
Antworten