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

Hallo,
ich bin relativer Neuling in Sachen Python. Nachdem ich einige Tutorials/Bücher gelesen habe, möchte ich mein Wissen anwenden. Mein Zielsetzung ist/war ein Brainfuck Interpreter zu schreiben und die Leistung/Implementierung in anderen Programmiersprachen(C) und OSes(Windows/NetBSD) zu vergleichen.
Damit das Programm auch auf anderen BS läuft, benötige ich curses. Nun gibts (n)curses aus irgendwelchen Gründen nicht für Windows(für C gibt es eine Bibliothek). Im Prinzip benötige ich nur die getch Funktion zum Einlesen eines Zeichens. Ich benutze die 3.01 Version von Python.

Gibt es eine andere Möglichkeit eine getch Funktion zu realisieren?
Benutzeravatar
b.esser-wisser
User
Beiträge: 272
Registriert: Freitag 20. Februar 2009, 14:21
Wohnort: Bundeshauptstadt B.

Hat Python 3 kein "sys.stdin.read(1)"?
Wcurses scheint noch nicht auf python 3 portiert zu sein (das hattest du bestimmt schon herausgefunden :D )
hth, Jörg
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

Unter Windows gibt es das Modul msvcrt. Darin ist getch enthalten.

@b.esser-wisser: sys.stdin.read(1) ist nicht das gleiche wie getch, da man die Eingabe abschließen muss! Mann kann also auch nacheinander 10 Zeichen eingeben. Solange kein Enter gedrückt wurde, gibt die Funktion nichts zurück (dann entsprechend nur das 1. Zeichen der Eingabe).
Benutzeravatar
darktrym
User
Beiträge: 784
Registriert: Freitag 24. April 2009, 09:26

Gibt es eine Möglichkeit den Code so zu schreiben, das er unter Windows andere Befehle interpretiert als unter unixähnlichen Systemen?
Wenn ich z.B. das Modul curses einbinde unter Windows, bekomme ich eine Fehlermeldung unter BSD wird sicherlich der Windows Kram Schwierigkeiten bereiten! Und zwei Versionen zu pflegen, will ich auch nicht.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

darktrym hat geschrieben:Gibt es eine Möglichkeit den Code so zu schreiben, das er unter Windows andere Befehle interpretiert als unter unixähnlichen Systemen?
Sicher. Schau dir z.B. mal das platform-Modul an.
Benutzeravatar
b.esser-wisser
User
Beiträge: 272
Registriert: Freitag 20. Februar 2009, 14:21
Wohnort: Bundeshauptstadt B.

HerrHagen hat geschrieben:@b.esser-wisser: sys.stdin.read(1) ist nicht das gleiche wie getch, da man die Eingabe abschließen muss! Mann kann also auch nacheinander 10 Zeichen eingeben. Solange kein Enter gedrückt wurde, gibt die Funktion nichts zurück (dann entsprechend nur das 1. Zeichen der Eingabe).
Hast natürlich recht, getch() scheint der einzige Weg um den (Zeilen-)Puffer des 'Terminals' zu sein ('os.fdopen(0,"r",1)' funktioniert auch nicht).

@darktrym:
Du kannst z.B. auch "ImportError" abfangen und was anderes importieren.

sry, Jörg
Benutzeravatar
darktrym
User
Beiträge: 784
Registriert: Freitag 24. April 2009, 09:26

Code: Alles auswählen

try:
	import curses
except ImportError:
	print("no curses")
Ich verstehe nicht, wieso das nicht funktioniert.

Edit: Fehlalarm, Verzeihung.
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Falls jmd. interessiert, warum das stdin.read() nicht so ohne weiteres funktioniert, hier gabs schonmal einen Thread dazu.
Benutzeravatar
darktrym
User
Beiträge: 784
Registriert: Freitag 24. April 2009, 09:26

Der Code für den Windows Teil funktioniert(getestet) soweit. Es wäre nett, wenn ihr mir noch ein paar Ratschläge geben könntet, welche Sachen man mit Python Bordmitteln eleganter lösen kann. Ich komme von den Java/C Denkmuster nicht ganz los.

Code: Alles auswählen

#Copyright (c) 2009, DarkTrym aka D.Oe.
#
#Permission to use, copy, modify, and/or distribute this software for any purpose with or
#without fee is hereby granted, provided that the above copyright notice and this permission
#notice appear in all copies.
#
#THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
#REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
#AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 
#INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 
#LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 
#OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 
#PERFORMANCE OF THIS SOFTWARE.

#!/usr/bin/env python

#brainfuck interpreter
#version 0.1
import sys
import platform

#open file, if it exists
try:
	file=open(sys.argv[1],"r")
except IndexError:
	print("wrong syntax: no source file")
	exit(-1)
	
#checking  keypressing libs
try:
	import curses
	stdscr = curses.initscr()
except ImportError:
	import msvcrt
	
isWindows=False
if platform.system()=="Windows":
	isWindows=True
	
#list in which the bainfuck code is stored
code=[]

#read the input file
#filter the symbols,check syntax and store it
balance=0
while True:
	line = file.read()
	if line == "":
		break
	for char in line:
		if char == '+' or char == '-' \
		or char == '>' or char == '<' \
		or char == '.' or char == ',': 
			code.append(char)
		elif char == '[': 
			balance+=1
			code.append(char)
		elif char == ']':
			balance-=1
			if balance < 0:
				print("more brackets are closed than opened")
				exit(-2)
			code.append(char)
			
if balance != 0:
	print("too much opened brackets")
	exit(-3)
		
codesize=len(code)
#create interpreter memory 256*256 bytes with zeros
memory=[]
for i in range(256**2):
	memory.append(0)

#store bracket level
stack=[]
#create jump table 
jmptable={}
for i in range(codesize) :
	if code[i]=='[':
		stack.append(i)
	elif code[i]==']':
		source=stack.pop()
		jmptable.setdefault(int(source), int(i))
		jmptable.setdefault(int(i), int(source))

#memory pointer
memmarker=0
#codepointer
codemarker=0

#interpret brainfuck code
while codemarker != codesize:
	if code[codemarker] == '+':
		if memory[memmarker] < 255:
			memory[memmarker]+=1
	elif code[codemarker] == '-':
		if memory[memmarker] > 0:
			memory[memmarker]-=1
	elif code[codemarker] == '>':
		if memmarker < 256**2-1:
			memmarker+=1
	elif code[codemarker] == '<':
		if memmarker > 0:
			memmarker-=1
	elif code[codemarker] == '[':
		if memory[memmarker]==0:
			codemarker=jmptable[codemarker]
	elif code[codemarker] == ']':
		if memory[memmarker]!=0:
			codemarker=jmptable[codemarker]
	elif code[codemarker] == '.':
		if isWindows:
			sys.stdout.write(chr(memory[memmarker]))
		else:	#for all systems, that use curses
			stdscr.addch(chr(memory[memmarker]))
	elif code[codemarker] == ',':
		if isWindows:
			memory[memmarker]=msvcrt.getch()
		else: #for all systems, that use curses
			memory[memmarker]=stdscr.getch()
			
	codemarker+=1
	
if not isWindows:		
	stdscr.endwin()

Code: Alles auswählen


Ein kleines Testprogramm als Benchmark. 

[quote]99 Bottles of Beer in Urban Mueller's BrainF*** (The actual
name is impolite)

by Ben Olmstead

ANSI C interpreter available on the internet; due to
constraints in comments the address below needs to have the
stuff in parenthesis replaced with the appropriate symbol:

http://www(dot)cats(dash)eye(dot)com/cet/soft/lang/bf/

Believe it or not this language is indeed Turing complete!
Combines the speed of BASIC with the ease of INTERCAL and
the readability of an IOCCC entry!

>+++++++++[<+++++++++++>-]<[>[-]>[-]<<[>+>+<<-]>>[<<+>>-]>>>
[-]<<<+++++++++<[>>>+<<[>+>[-]<<-]>[<+>-]>[<<++++++++++>>>+<
-]<<-<-]+++++++++>[<->-]>>+>[<[-]<<+>>>-]>[-]+<<[>+>-<<-]<<<
[>>+>+<<<-]>>>[<<<+>>>-]>[<+>-]<<-[>[-]<[-]]>>+<[>[-]<-]<+++
+++++[<++++++<++++++>>-]>>>[>+>+<<-]>>[<<+>>-]<[<<<<<.>>>>>-
]<<<<<<.>>[-]>[-]++++[<++++++++>-]<.>++++[<++++++++>-]<++.>+
++++[<+++++++++>-]<.><+++++..--------.-------.>>[>>+>+<<<-]>
>>[<<<+>>>-]<[<<<<++++++++++++++.>>>>-]<<<<[-]>++++[<+++++++
+>-]<.>+++++++++[<+++++++++>-]<--.---------.>+++++++[<------
---->-]<.>++++++[<+++++++++++>-]<.+++..+++++++++++++.>++++++
++[<---------->-]<--.>+++++++++[<+++++++++>-]<--.-.>++++++++
[<---------->-]<++.>++++++++[<++++++++++>-]<++++.-----------
-.---.>+++++++[<---------->-]<+.>++++++++[<+++++++++++>-]<-.
>++[<----------->-]<.+++++++++++..>+++++++++[<---------->-]<
-----.---.>>>[>+>+<<-]>>[<<+>>-]<[<<<<<.>>>>>-]<<<<<<.>>>+++
+[<++++++>-]<--.>++++[<++++++++>-]<++.>+++++[<+++++++++>-]<.
><+++++..--------.-------.>>[>>+>+<<<-]>>>[<<<+>>>-]<[<<<<++
++++++++++++.>>>>-]<<<<[-]>++++[<++++++++>-]<.>+++++++++[<++
+++++++>-]<--.---------.>+++++++[<---------->-]<.>++++++[<++
+++++++++>-]<.+++..+++++++++++++.>++++++++++[<---------->-]<
-.---.>+++++++[<++++++++++>-]<++++.+++++++++++++.++++++++++.
------.>+++++++[<---------->-]<+.>++++++++[<++++++++++>-]<-.
-.---------.>+++++++[<---------->-]<+.>+++++++[<++++++++++>-
]<--.+++++++++++.++++++++.---------.>++++++++[<---------->-]
<++.>+++++[<+++++++++++++>-]<.+++++++++++++.----------.>++++
+++[<---------->-]<++.>++++++++[<++++++++++>-]<.>+++[<----->
-]<.>+++[<++++++>-]<..>+++++++++[<--------->-]<--.>+++++++[<
++++++++++>-]<+++.+++++++++++.>++++++++[<----------->-]<++++
.>+++++[<+++++++++++++>-]<.>+++[<++++++>-]<-.---.++++++.----
---.----------.>++++++++[<----------->-]<+.---.[-]<<<->[-]>[
-]<<[>+>+<<-]>>[<<+>>-]>>>[-]<<<+++++++++<[>>>+<<[>+>[-]<<-]
>[<+>-]>[<<++++++++++>>>+<-]<<-<-]+++++++++>[<->-]>>+>[<[-]<
<+>>>-]>[-]+<<[>+>-<<-]<<<[>>+>+<<<-]>>>[<<<+>>>-]<>>[<+>-]<
<-[>[-]<[-]]>>+<[>[-]<-]<++++++++[<++++++<++++++>>-]>>>[>+>+
<<-]>>[<<+>>-]<[<<<<<.>>>>>-]<<<<<<.>>[-]>[-]++++[<++++++++>
-]<.>++++[<++++++++>-]<++.>+++++[<+++++++++>-]<.><+++++..---
-----.-------.>>[>>+>+<<<-]>>>[<<<+>>>-]<[<<<<++++++++++++++
.>>>>-]<<<<[-]>++++[<++++++++>-]<.>+++++++++[<+++++++++>-]<-
-.---------.>+++++++[<---------->-]<.>++++++[<+++++++++++>-]
<.+++..+++++++++++++.>++++++++[<---------->-]<--.>+++++++++[
<+++++++++>-]<--.-.>++++++++[<---------->-]<++.>++++++++[<++
++++++++>-]<++++.------------.---.>+++++++[<---------->-]<+.
>++++++++[<+++++++++++>-]<-.>++[<----------->-]<.+++++++++++
..>+++++++++[<---------->-]<-----.---.+++.---.[-]<<<]
@[/quote]
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Zunächst einmal solltest du dir PEP8 ansehen (siehe im Wiki des Forums, da gibt es eine Übersetzung).

Statt einen isWindows "Control flag" zu setzen, solltest du einfach ein Einheitliches Interface anbieten. Du benutzt doch sowieso nur getch. Also kannst du auch sowas schreiben:

Code: Alles auswählen

try:
    import curses as _curses
    stdscr = _cursed.initscr()
except ImportError:
    import msvcrt as stdscr

...

stdscr.getch() # Funktioniert auf jedem System wo eine der beiden Libraries vorhanden ist
Dann hast du schonmal an der Stelle kein "Control Coupling" mehr.

Du solltest Dateien nicht "file" nennen, das ist die Builtin Klasse für Dateien (du bekommst ein Exemplar der Klasse mit open()). Du kannst in Python jede Funktion mit einem eigenen Namen überschreiben, es ist aber oft nicht anzuraten. Kann zu witzigen Fehlern führen.

file.read() liest die Datei komplett in den Speicher. Die Schleife wird an der Stelle also doch sowieso nur einmal durchlaufen, danach liefert read "" zurück, was dann zu einem break führt. Stattdessen kannst du einfach über jede Zeile der Datei mit "for line in file:" iterieren. Da du die Datei komplett einliest, ist line als Name auch falsch.

Die ganzen BrainF Symbole kannst du doch in einen Tupel packen und dann mit "char in symbols" arbeiten. Kannst du die if balance < 0 Abfrage an der Stelle des Codes entfernen und zu der Abfrage nach "balance != 0" packen? Dann kannst du

Code: Alles auswählen

brackets_balance = {"[": 1, "]": -1}
if char in symbols:
    ... # kein code.append hier
elif char in brackets_balance: # Sucht nach einem Key in brackets_balance
    balance += brackets_balance[char]
else:
    raise BrainFuckSyntaxError(...) # Subklasse von SyntaxError oder von Exception
code.append(char)
Die brackets_balance kannst du wahlweise nochmal einzeln als Tupel für "brackets" schreiben oder so belassen, aber die ganzen Symbole (auch brackets) sollten globale Konstanten sein.
Benutzeravatar
darktrym
User
Beiträge: 784
Registriert: Freitag 24. April 2009, 09:26

Dank dir. Ich habe noch ein paar Stellen verbessert, wie empfohlen.

Die jetztige Version sieht dann so aus.
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

Tolle Sache, so ein Brainfuck-Interpreter. :-)

Hier noch ein paar kleine Hinweise:
Statt:

Code: Alles auswählen

memory=[]
for i in range(256**2):
        memory.append(0)
kannst du auch einfach folgendes schreiben:

Code: Alles auswählen

memory=[0]*(256**2)
Wenn du schon für die Eingabe ein einheitliches Inteface hast, warum dann nicht auch für die Ausgabe (Funktionen sind normale Objekte)?

Code: Alles auswählen

putchar = sys.stdout.write if isWindows else stdscr.addch
Wenn du überprüfen willst ob ein Zeichen in einer Reihe von Zeichen drin ist, brauchst du kein set/liste/... erstellen. Mit einem String ist das ebenso möglich. So wirds ein wenig übersichlicher:

Code: Alles auswählen

# brainfucksymbols={'+','-','>','<','.',',','[',']'}
brainfucksymbols="+-><.,[]"
...
if char in brainfucksymbols:
    ...
Wenn man über eine Liste iteriert und sowohl die Werte als auch den Index braucht, schreibt man gerne:

Code: Alles auswählen

for i, char in enumerate(code) :
        if char == '[':
                stack.append(i)
        elif char == ']':
                ...
Du verwendest tabs statt den standartmäßigen 4 Leerzeichen. Das solltest du unbedingt ändern um nicht Konflikte bei gepasteten Code, etc. zu geraten. Die Python-Leute sind ja generell ziemlich erpicht auf Codeformatierungen. Deswegen sei dir auch von mir nochmal PEP8 ans herz gelegt.

MFG HerrHagen
lunar

HerrHagen hat geschrieben:Wenn du überprüfen willst ob ein Zeichen in einer Reihe von Zeichen drin ist, brauchst du kein set/liste/... erstellen. Mit einem String ist das ebenso möglich. So wirds ein wenig übersichlicher:

Code: Alles auswählen

# brainfucksymbols={'+','-','>','<','.',',','[',']'}
brainfucksymbols="+-><.,[]"
...
if char in brainfucksymbols:
    ...
Auf Zeichenketten hat der "in"-Operator lineare, auf Mengen dagegen lediglich konstante Laufzeit. Bei kleinen Zeichenmenge fällt das natürlich nicht ins Gewicht, im Allgemeinen aber sollte man Zeichenketten aber nicht als Mengen missbrauchen. Die Übersicht kann man trotzdem wahren, wenn man das will:

Code: Alles auswählen

brainfucksymbols=set('+-><.,[]')
Ich persönlich halte die Mengennotation von Python 3 für ausreichend übersichtlich.

Außerdem würde ich die if-elif-else-Kaskade des Interpreters durch ein Wörterbuch mit Callback-Funktionen ersetzen.

Leerzeichen nach dem Kommentarzeichen würden die Lesbarkeit der Kommentare erhöhen. Und es heißt "too many opened brackets" ...
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

@lunar: Da haste natürlich recht. Den Aspekt hat ich irgendwie vergessen. :oops:
Ich finde die neue set Syntax irgwendwie nicht so gelungen. Die geschweiften Klammern erinnern mich doch irgendwie zu sehr an dict's. Naja, vielleicht ist das aber nur ne Gewöhnungssache und man setzt sie aufgrund der integrierteren Syntax häufiger ein. Der Geschwindigkeitsvorteil ist auf jeden Fall da:

Code: Alles auswählen

In [20]: txt = "qwertzuiopasdfghjklyxcvbnm"
In [21]: %timeit "m" in txt
1000000 loops, best of 3: 241 ns per loop
In [22]: txt = set("qwertzuiopasdfghjklyxcvbnm")
In [23]: %timeit "m" in txt
1000000 loops, best of 3: 187 ns per loop
lunar

HerrHagen hat geschrieben:Ich finde die neue set Syntax irgwendwie nicht so gelungen.
Und was wäre die Alternative gewesen? Geschweifte Klammern sind eben die mathematische Notation für Mengen, und Wörterbücher sind letztlich auch nur Mengen von Schlüssel-Wert-Paaren. 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.
BlackJack

"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.
lunar

BlackJack hat geschrieben:"Das war schon immer so" kann man nicht kritisieren? Insbesondere bei einer Version die explizit mit Rückwärtskompatibilität bricht!?
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.

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".
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

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:

Code: Alles auswählen

empty_set = s{}
empty_dic = {}
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.
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.

MFG HerrHagen

EDIT: Oh, BlackJack war schneller - und hatte offensichtlich die gleiche Idee :wink:
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

lunar hat geschrieben:
BlackJack hat geschrieben:"Das war schon immer so" kann man nicht kritisieren? Insbesondere bei einer Version die explizit mit Rückwärtskompatibilität bricht!?
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.
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:"A Foolish Consistency is the Hobgoblin of Little Minds".
Damit lässt sich nicht alles rechtferigen. Sonst müssten wir ja sagen dass die Twisted-Libs gut designt sind ;)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
lunar

HerrHagen hat geschrieben:Die Alternative wäre gewesen alles so zu lassen
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.
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 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.

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 ;)
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.
Siehe meine Antwort auf BlackJacks Posting ...
Gerade bei dict/et comprehensions finde ich die neue Syntax ein wenig unübersichtlich.
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 ...
EDIT: Oh, BlackJack war schneller - und hatte offensichtlich die gleiche Idee :wink:
Und ich hatte ihm sogar schon geantwortet ...
Antworten