Ich habe folgenden Code:

board_dic = {
    0: '_',
    1: '_',
    2: '_',
    3: '_',
    4: '_',
    5: '_',
    6: '_',
    7: '_',
    8: '_',
}

print("|{0}|{1}|{2}|\n|{3}|{4}|{5}|\n|{6}|{7}|{8}|".format(**board_dic)

Die Ausgabe beim Ausführen ist:

line 28, in <module>
    print("|{0}|{1}|{2}|\n|{3}|{4}|{5}|\n|{6}|{7}|{8}|".format(**board_dic))
IndexError: Replacement index 0 out of range for positional args tuple

Ich kann nirgendwo eine Lösung dafür finden. Wenn ich die Schlüssel in board_dic durch Zeichenfolgen wie 'a', 'b', 'c' usw. ersetzen und die Platzhalter in der print-Anweisung durch {{X4 ersetzen würde }}, 'b', 'c' usw. Dann würde meine print-Anweisung ohne Probleme ausgeführt. Es scheint jedoch, dass das Problem speziell bei numerischen Schlüsselwörterbuchwerten liegt.

Warum ist das so und wie kann ich das beheben?

3
Arty 3 Sept. 2020 im 18:54

3 Antworten

Beste Antwort

Wenn Sie wissen, wonach Sie suchen müssen, wird hier :

Der Feldname selbst beginnt mit einem Argumentnamen, der entweder eine Zahl oder ein Schlüsselwort ist. Wenn es sich um eine Zahl handelt, bezieht sie sich auf ein Positionsargument , und wenn es sich um ein Schlüsselwort handelt, bezieht sie sich auf ein benanntes Schlüsselwortargument. Wenn die numerischen arg_names in einer Formatzeichenfolge nacheinander 0, 1, 2, ... sind, können sie alle weggelassen werden (nicht nur einige), und die Zahlen 0, 1, 2, ... werden automatisch in dieser Reihenfolge eingefügt. Da arg_name nicht durch Anführungszeichen getrennt ist, ist es nicht möglich, beliebige Wörterbuchschlüssel (z. B. die Zeichenfolgen '10' oder ': -]') innerhalb einer Formatzeichenfolge anzugeben.

In einfachen Worten bedeutet '{0} {1}'.format(...) "{0} durch das erste Positionsargument und {1} durch das zweite Positionsargument von format(...) ersetzen.

Positionsargumente sind solche, die ohne Angabe des Parameternamens im Funktionsaufruf übergeben werden. Zum Beispiel sind in format(1, 2, c=3) 1 und 2 Positionsargumente und c=3 ein Schlüsselwortargument.

Die Syntax **board_dic gibt jedoch Schlüsselwortargumente an! format(**board_dic) entspricht format(0='_', 1='_', 2='_', ...) 1 und es gibt keine Positionsargumente. Daher schlägt die Verwendung von {0}, {1}, {2} usw. fehl, um das erste, zweite, dritte usw. Positionsargument zu erhalten.

Um ein Wörterbuch mit Ganzzahlschlüsseln an format zu übergeben, können Sie Folgendes verwenden:

print("|{d[0]}|{d[1]}|{d[2]}|\n|...".format(d=board_dic))

1

2
mkrieger1 3 Sept. 2020 im 16:22

Bei Verwendung von Format-Strings stellen Platzhalter wie {1} das n-te Argument von "format ()" dar. Dies unterscheidet sich von benannten Schlüsselwortargumenten. Wenn Sie **board_dic verwenden, werden sie in Schlüsselwortargumente zerlegt. Dies ist der Grund, warum es nicht wie erwartet funktioniert.

Stattdessen müssen Sie Positionsargumente mit einem einzelnen * verwenden. Aber dann sind Sie mit einem anderen Problem konfrontiert: Die Reihenfolge der Wörterbücher wurde, soweit ich mich erinnere, nur Teil der Sprachspezifikation in Python 3.7. Es war bereits in früheren Versionen stabil, aber das war ein Implementierungsdetail und wurde in anderen Versionen (pypy, jython, ...) nicht garantiert.

Wir müssen es also sortieren, um 100% sicher zu sein, dass dies funktioniert.

Da die Schlüssel numerisch sind, können wir einfach nach board_dic.items() sortieren. Dies gibt uns einen stabilen Ersatz.

Wir müssen dann die effektiven Werte extrahieren. Wir können dies mit einem einfachen Listenverständnis tun.

Nach dieser Änderung sind wir - solange das Wörterbuch keine fehlenden Zahlen enthält - zu 100% sicher, dass die Ausgabe korrekt ist.

Wir können die resultierende Liste in .format() mit einer einzelnen "Positionsargument-Erweiterung" verwenden.

board_dic = {
    0: '_',
    1: '_',
    2: '_',
    3: '_',
    4: '_',
    5: '_',
    6: '_',
    7: '_',
    8: '_',
}

values = [value for _, value in sorted(board_dic.items())]

print("|{0}|{1}|{2}|\n|{3}|{4}|{5}|\n|{6}|{7}|{8}|".format(*values))
2
exhuma 3 Sept. 2020 im 16:15

Um die Diktatwerte mithilfe ihrer Schlüssel in Positionsargumente für die Methode str.format zu konvertieren, können Sie der get -Methode des Diktats ein range der Länge des Diktats zuordnen und die Ausgabe entpacken Reihenfolge als Argumente:

print("|{0}|{1}|{2}|\n|{3}|{4}|{5}|\n|{6}|{7}|{8}|".format(*map(board_dic.get, range(len(board_dic)))))
2
blhsing 3 Sept. 2020 im 16:12