Arrays, Listen, usw.

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.
Antworten
Nordpol
User
Beiträge: 19
Registriert: Sonntag 19. September 2010, 18:21

Hallo Forum,

in den letzten Jahren habe ich ausschließlich php programmiert und obwohl hier schon seit x Jahren angemeldet, bin ich Einsteiger in Python.

Ich schau mir gerade mal Arrays an und habe eine Frage:

Ich kenne das aus php, dass ich ienem Array einfach Key und Value zuweisen kann, also

Code: Alles auswählen

$arr_test[0][0] = 12;
Aber sowas mag Python nicht. Jedenfalls ernte ich für

Code: Alles auswählen

lst[0][0] = 1
ein "KeyError: 0"

Wie befülle ich denn in Python ein mehrdimensionales Array, dessen Keys nicht numerisch sein sollen? Oder muß dann ein Directionery her?
Weitere Frage: Haben mehrdimensionale Array und Directionerys zu einem möglichen "nicht numerischen" Schlüssel wie bei php zusätzliche einen numerischen Key?

N.
BlackJack

@Nordpol: Als erstes müsstest Du die Begrifflichkeiten sauber trennen. Python hat Arrays im `array`-Modul in der Standardbibliothek die sehr selten verwendet werden. Meistens meint man deshalb Numpy-Arrays aus dem `numpy`-Package wenn man von Arrays spricht. Als eingebauten Sequenzdatentyp hat Python *Listen* (`list`). Und für Abbildungen von Schlüsseln zu Werten gibt es Wörterbücher (`dict`).

Wenn man einer Liste etwas an einem Index zuweisen möchte, dann muss dieser Index bereits existieren. Das ist aber auch eher selten das man so etwas in Python machen möchte. Listen werden in der Regel dynamisch aufgebaut, in dem die Elemente einfach nach und nach an eine Liste angehängt werden.

Listen-Indizes müssen ganze Zahlen sein (oder `slice()`\s).

Für Abbildungen von Schlüsseln zu Werten kann man als Schlüssel dagegen alles nehmen was „hashable“ ist und wo gleicher Hash auch `True` beim Vergleich mit ``==`` ergibt.

Wenn Du bei ``lst[0][0] = 1`` einen `KeyError` bekommst, dann ist `lst` ein sehr irreführender Name, denn dann ist das ein Wörterbuch und keine Liste. Und zwar ein Wörterbuch das unter dem Schlüssel 0 noch keinen Wert hinterlegt hat, also kann man den auch nicht abfragen um dort dann wiederum etwas unter dem Index oder Schlüssel 0 zuzuweisen.

Elemente von Wörterbüchern fangen nicht einfach an zu existieren wenn man darauf lesend zugreift. Das wäre auch ziemlich magisch und es würde sich die Frage stellen was für einen Typ so ein Element haben sollte. Wieder ein Wörterbuch? Eine Liste? Eine Menge? Oder vielleicht auch etwas gänzlich anderes. Da dort alles mögliche Sinn machen kann, gibt es dieses Verhalten nicht.

Es gibt aber `collections.defaultdict`, das ist ein Wörterbuchtyp bei dem man beim erstellen etwas aufrufbares übergeben kann, das beim Zugriff auf nichtvorhandene Schlüsseln einen neuen Wert zu dem Schlüssel erzeugt.

Wörterbücher haben keine Ordnung bei den Schlüssel/Wert-Paaren und dementsprechend sind denen auch keine numerischen Schlüssel zugeordnet.

Man sollte sich eventuell auch noch mal klar machen das weder Listen noch Wöterbücher mehrdimensional sind. Im Gegensatz zu Numpy-Arrays beispielsweise. Man kann diese Typen aber beliebig verschachteln.
nezzcarth
User
Beiträge: 1634
Registriert: Samstag 16. April 2011, 12:47

Nordpol hat geschrieben: Ich kenne das aus php, dass ich ienem Array einfach Key und Value zuweisen kann, also
Es kann sinnvoll sein, dass du, wenn du Python lernen möchtest, zumindest vorübergehend erst einmal alles vergisst, was du über PHP weißt. In Python gibt es als (als Standarddatenyp) keine Arrays (zumal das, was PHP als Array bezeichnet nach meinem Verständnis auch keine klassischen Arrays sind). Aber es gibt in Python Listen und Dictionaries. Dictionaries sind unsortierte Paare von Schlüsseln und Werten. Listen sind sortierte Ansammlungen von Werten. Man kann etwas an sie anhängen, oder etwas entfernen, und man kann einzelne Elemente über ihren Listenindex ansprechen. Die Werte können -- bei Dictionaries und bei Listen -- beliebige Typen haben, Integer, Strings, oder eben auch andere Listen oder Dictionaries. Entsprechend würde dann mehrdimensionale Arrays in Python mit verschachtelten Listen abbilden.

Also z.B.:

Code: Alles auswählen

elements = [[1,2,3], [4,5,6]]
Dein erstes Beispiel funktioniert so in Python nicht, weil Python für Listen nicht einfach "automatisch" nur durch Zuweisung so eine Struktur erzeugt. Zuweisungen funktionieren nur, wenn bereits etwas da ist. Was Python versucht ist, das erste Element der Liste zu nehmen (was es nicht gibt), und dessen wiederum erstem Element (das es ebenfalls nicht gibt), einen Wert zuzuweisen. Wenn du eine Liste erzeugen möchtest, musst du das entweder wie gezeigt "per Hand" machen, oder -- wenn es sich anbietet -- automatisch z.B. per ListComprehension.

EDIT:
BlackJack war schneller; aber da ich die Antwort schon getippt hatte.. :/
Melewo
User
Beiträge: 320
Registriert: Mittwoch 3. Mai 2017, 16:30

Wie BlackJack schrieb, es gibt Unterschiede, nicht zu wenige, ein direktes Vergleichen hinkt oft und genauso oft muss ich auch noch überlegen, ob ich etwas richtig schreibe. Entspricht das eher dem, wonach Du suchst?

Code: Alles auswählen

test = {}

test[1] = 31
test[2] = 32

print("# Ausgabe: {}".format(test))
# Ausgabe: {1: 31, 2: 32}

print("# Ausgabe: {}".format(test[1]))
# Ausgabe: 31

print("# Ausgabe: {}".format(test[2]))
# Ausgabe: 32
Nordpol
User
Beiträge: 19
Registriert: Sonntag 19. September 2010, 18:21

Vielen Dank für Eure Antworten!
Ist tatsächlich ein wenig Umstellung, wenn man von php gewohnt ist, dass php arrays quasi automatisch erstellt, auch wenn zuvor nichts vorhanden war. Die Kombination Eurer Erklärungen (Blackjack + nezcarth) fand ich ganz klasse und einleuchtend!

@BlackJack: Lohnt es, sich das Numpy Package genauer anzuschauen?

@Melewo: So in der Art hatte ichs auch gelöst:

Code: Alles auswählen

test = {}
test[0] = 10
test[1] = 12

print(test)
print("Ausgabe: "+str(test[0]))
print("Ausgabe: "+str(test[1]))
N.
Zuletzt geändert von Anonymous am Samstag 22. Juli 2017, 20:52, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

@Nordpol: Ob sich Numpy lohnt kommt darauf an was Du machen möchtest.

Das Programm kann man kürzer schreiben:

Code: Alles auswählen

test = {0: 10, 1: 12}
print(test)
for key in [0, 1]:
    print('Ausgabe:', test[key])
Insbesondere Zeichenketten und Werte mit `str()` und ``+`` zusammenstückeln ist eher BASIC als Python. Entweder verwendet man dafür `format()` wie Melewo in seinem Beispiel, oder bei `print()` den Umstand das man mehr als ein Argument angeben kann die `print()` in Zeichenketten umwandelt und mit einem Leerzeichen getrennt ausgibt. Das Trennzeichen kann man mit einem Schlüsselwort-Argument auch ändern.
Nordpol
User
Beiträge: 19
Registriert: Sonntag 19. September 2010, 18:21

Hi Blackjack,
Das Programm kann man kürzer schreiben:
Mir gings aber darum, die Elemente einzeln zu setzen.
Insbesondere Zeichenketten und Werte mit `str()` und ``+`` zusammenstückeln ist eher BASIC als Python.
Oder Javascript.
oder bei `print()` den Umstand das man mehr als ein Argument angeben kann die `print()` in Zeichenketten umwandelt und mit einem Leerzeichen getrennt ausgibt. Das Trennzeichen kann man mit einem Schlüsselwort-Argument auch ändern.
Danke für den Tip! Gefällt mir auch viel besser.
2 Fragen hierzu:
1. Was, wenn ich aus String und Variablen etwas zussammensetzen möchte, das keine Leerzeichen enthalten darf?
2. Wie macht man das: "Das Trennzeichen mit einem Schlüsselwort-Argument ändern"

N.
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

Nordpol hat geschrieben:2 Fragen hierzu:
1. Was, wenn ich aus String und Variablen etwas zussammensetzen möchte, das keine Leerzeichen enthalten darf?
2. Wie macht man das: "Das Trennzeichen mit einem Schlüsselwort-Argument ändern"
Zu 1: Du erzeugst einen neuen String mittels der Format-Methode.
Zu 2: Das bezog sich auf die print-Funktion aus Python 3 (bzw. den Backport nach Python 2). Diese Funktion akzeptiert die beiden Keyword-Parameter 'sep' und 'end'.
Benutzeravatar
DeaD_EyE
User
Beiträge: 1021
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Eins vorweg, strings sind im Python imutable, also nicht veränderbar.
Folgendes geht nicht:

Code: Alles auswählen

s = 'Hwllo World'
s[1] = 'e' # TypeError: 'str' object does not support item assignment
Da findest du alle Antworten zur built-in print funtion: https://docs.python.org/3/library/functions.html#print
Mit sep kannst du den Seperator festlegen, der standardmäßig ein Leerzeichen ist.

Andererseits gibt viele viele Möglichkeiten Strings zu interpretieren/formatieren.

Code: Alles auswählen

vname = 'Andre'
fname = 'Müller'

# kann man machen, in vielen Fällen ist es entgegen der Aussage vieler schneller, notfalls nachmessen
full_name = vname + ' ' + fname

# sieht hässlich aus, oftmals nimmt man diese Methode um aus liste, tuple bzw. Sequenzen einen String zu erstellen
full_name = ' '.join([vname, fname])

#string formatting
full_name = '%s %s' % (vname, fname) # String-Formatierung in C-Style, ungern gesehen. Ist alt

# Format Methode, wird bevorzugt eingesetzt. Die Indexierung kann man aus Kompatibilitätsgründen verwenden. 
full_name = '{0} {1}'.format(vname, fname)
full_name = '{} {}'.format(vname, fname)
# das erste Feld ist 30 Zeichen lang und der eingesetzte Text ist linksbündig
full_name = '{:<30}{}'.format(vname, fname)

# jetzt nochmal mit einem dict und der format_map methode, ziemlich cool
person = {'vname': 'Andre', 'fname': 'Müller'}
full_name =  '{vname} {fname}'.format_map(person)

# seit Python 3.6 der format string, der lokale Variablen einsetzt und sogar Methoden zulässt
full_name = f'{vname} {fname}'
# hier wird die Methode upper beide Strings angewandt. Namen von Sklaven hat man früher groß geschieben.
full_name = f'{vname.upper()} {fname.upper()}'

# string.Template, nutzt kaum jemand
import string
tpl = string.Template('$vname $fname')
full_name = tpl.safe_substitute(vname=vname, fname=fname)


Das müssten so alle Möglichkeiten gewesen sein. Zur format Methode unbedingt das hier lesen: https://docs.python.org/3/library/strin ... matstrings
Das gilt auch für format-strings in Python 3.6.

Seit Python 3.x sind alle strings Unicode. Die interne Repräsentation hängt von der Python-Version ab.
Dann gibt es noch bytes, die explizit die binäre Repräsentation des Speichers darstellen.
Hat man z.B. eine Datei im binären Modus geöffnet, müssen das zu schreibende Objekt auch explizit bytes sein.
Eine implizite Konvertierung von str zu bytes gibt es seit Python 3 zum Glück nicht mehr.

str > bytes: encode > utf-8 Standardmäßig
bytes > str: decode < utf-8 Standardmäßig

Bytestrings werden mit im Programmcode mit einem b Präfix gekennzeichnet.
b'Andre M\xfcller' # codiert mit latin1
b'Andre M\xc3\xbcller' # codiert mit utf-8

Wie schon ersichtlich, werden Zeichen, die nicht durch ASCII dargestellt werden können, als \xHEX dargestellt.
Es lassen sich Zeichen so auch im Programmcode explizit eingeben. Gültig ist in bytestrings \x00 - \xFF.
In Strings lässt sich das auch verwenden. Für 2 byte unicode \u3ccc und für 4 byte unicode \U
Dazu am besten die Dokumentation über Unicode lesen: https://docs.python.org/3/howto/unicode.html
Manchmal kann das etwas verwirrend sein.

Übrigens kannst du auch im Programmcode Variablennamen in Unicode angeben um andere zu ärgern.

Öffnet man Dateien, so werden diese Standardmäßig im Text-Mode geöffnet und das encoding ist utf-8.
Öffnet man Dateien im Raw-Mode, so müssen auch explizit bytes geschrieben werden. Darüber wirst du sicherlich noch öfters stolpern.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
BlackJack

Zu dem was DeaD_EyE schrieb: UTF-8 ist in Python 3 *nicht* die Standardkodierung, ausser bei Python-Quelltexten. Wenn man also Textdateien öffnet und möchte das UTF-8 als Kodierung verwendet werden soll, dann *muss* man das explizit angeben, sonst kann da auch etwas anderes genommen werden.
Nordpol
User
Beiträge: 19
Registriert: Sonntag 19. September 2010, 18:21

@DeaD_EyE: Danke, das ist eine super Hilfe, die druck ich mir mal gleich aus.
BlackJack hat geschrieben:Zu dem was DeaD_EyE schrieb: UTF-8 ist in Python 3 *nicht* die Standardkodierung, ausser bei Python-Quelltexten. Wenn man also Textdateien öffnet und möchte das UTF-8 als Kodierung verwendet werden soll, dann *muss* man das explizit angeben, sonst kann da auch etwas anderes genommen werden.
Aha?
Wonach entscheidet Python, welche Codierung es nimmt?

N.
BlackJack

@Nordpol: Das ist selbstverständlich bei der open()-Funktion dokumentiert wie die Kodierung ermittelt wird. Letztendlich will man die immer explizit angeben und es spricht einiges dafür immer UTF-8 zu nehmen wenn man es selbst in der Hand hat.
Nordpol
User
Beiträge: 19
Registriert: Sonntag 19. September 2010, 18:21

BlackJack hat geschrieben: open()-Funktion
Danke für den Link auf die Doku, kann ich gut brauchen.

N.
Antworten