Zurück


In dieser Einheit werden wir zwei wichtige Grundlagen für Python ausarbeiten: Strings und Dictionaries.



Strings

Die Programmiersprache Python ist sehr divers und flexibel, wenn es zur Manipulierung der Strings kommt, und diesen Schwerpunk bearbeiten wir jetzt.
String Manipulation dieser Art kommt öfter im Zusammenhang mit der Datenwissenschaft vor.

String Syntax


Du hast bereits viel über Strings in den vorherigen Einheiten gelernt, aber nur um es kurz zu wiederholen,
Strings befinden sich innerhalb von Einzel- oder Doppelanführungszeichen und beinhalten einen Text.
Doppel- oder Einzelanführungszeichen machen selten einen Unterschied.

x = 'Pluto ist ein Planet'
y = "Pluto ist ein Planet"
x == y

True

Es wird nur wichtig, wenn in dem String etwas mit einem Apostroph geschrieben werden muss.
Dann muss man bei Einzelanführungszeichen Doppelanführungszeichen nutzen und vice versa.

print("Pluto ist 'n Planet!")
print('Mein Hund heißt "Pluto"')
Pluto ist ein Planet!
Mein Hund heißt "Pluto"

Wenn wir zweimal dieselbe Art von Anführungszeichen verwenden, dann ist Python verwirrt.

'Pluto ist 'n Planet!'
File "/tmp/ipykernel_20/1561186517.py", line 1
'Pluto's a planet!'
^
SyntaxError: invalid syntax

Wir können diesen Fehler mit einem Backslash vor dem Anführungszeichen ausweichen.

'Pluto ist \'n Planet!'
"Pluto ist ein Planet!"

In dieser Tabelle wurden die wichtigsten Anwendungen für Backslash zusammengefasst.

Was du eintippst

Was du kriegst

beispiel

print(beispiel)

\'

'

'Wie geht\‘s?'

Wie geht‘s?

\"

"

"Das ist der \"Hammer\""

Das ist der "Hammer"

\\

\

"Schau mal, ein Berg: /\\"

Schau mal, ein Berg:/\

\n

 

"1\n2 3"

1
2 3



\n ist das Zeichen für Python, das es eine Zeile runter gehen soll.

hallo = "Hallo \nWelt"
print(hallo)
Hallo
Welt

Wie wir bereits in Docstrings gesehen haben, kann man mit Dreifachanführungszeichen
mit einem Enter in einer anderen Zeile anfangen

dreifachanführ_hallo = """Hallo
Welt"
print(dreifachanführ_hallo)
dreifachanführ_hallo == hallo
Hallo
Welt

True
print() fügt automatisch für jedes Mal, wenn es aufgerufen wird, eine Neue Zeile ein.
Das können wir aber mit der "end" Bedingung ändern.

print("Hallo")
print("Welt")
print("Hallo", end=' ')
print("Welt", end=' ')
Hallo
Welt
HalloWelt

Strings sind Sequenzen


Man kann sich Strings, wie eine Sequenz, aus Charakteren Vorstellen, so gut wie alles,
was wir mit listen bearbeitet haben, können wir mit Strings machen.

# Indexieren
planet = "Pluto"
planet[0]

"P"

# Slicing
Planet[-3:]

"uto"

# Wie lange ist dieser String?
len(planet)

5

# Wir können sogar Schleifen mit ihnen machen
[char+"!" for char in planet]
['P! ', 'l! ', 'u! ', 't! ', 'o! ']

Strings sind aber nicht veränderlich, also können wir sie nicht modifizieren.

planet[0] = "B"
# planet.append funktioniert auch nicht.
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/tmp/ipykernel_20/2683731249.py in <module>
----> 1 planet[0] = 'B'
2 # planet.append doesn't work either

TypeError: 'str' object does not support item assignment

String Methoden


Genauso, wie die list, hat das str Typ viele nützliche Methoden.

# Blockbuchstaben
aussage = "Pluto ist ein Planet!"
aussage.upper()

"PLUTO IST EIN PLANET!"


# Kleinbuchstaben
aussage.lower()

"pluto ist ein planet!"


# Nach dem ersten Index eines Substrings suchen
aussage.index("plan")

11


aussage.startswith(planet)

True

# Warte was? Wie? Achso, wir haben auf das Anführungszeichen vergessen.
aussage.endswith("planet")

False

Zwischen Strings und Listen gehen: .split() und .join()
str.split() verwandelt ein String in eine Liste mit kurzen Strings und
spaltet normalerweise bei Leerzeichen. Es ist sehr hilfreich, wenn du einen großen
String hast und diesen in eine Liste von Wörtern aufteilen möchtest.

woerter = aussage.split()
woerter
["Pluto", "ist", "ein", "Planet"]

Manchmal musst du etwas anderes zum Spalten verwenden, anstatt von Leerzeichen:

datumstr = "1956-01-31"
jahr, monat, tag = datumstr.split("-")

str.join() macht genau das Gegenteil und bindet eine Liste von Strings zusammen,
wodruch ein großer String erzeugt wird. Dafür braucht es einen String, welcher wie ein Bindemittel wirkt.

"/".join([monat, tag, jahr])
"01/31/1956"
# Wir könnten sogar Emojis als Bindemittel für unseren String verwenden.
"👏".join([wort.upper() for wort in woerter])

"PLUTO 👏 IST 👏 EIN 👏 PLANET!"

Strings mit .format() bauen
Python erlaubt uns Strings mit dem + Operanten zu verketten

planet + ", wir vermissen dich."

"Pluto, wir vermissen dich."

Wenn wir irgendwas, was kein String ist, mitverketten wollen, müssen wir str() einsetzen.
Sonst kommt eine Fehlermeldung.

Wenn wir Strings mit .format() bauen erlaubt es uns Strings mit einem + operanten zusammen zu flechten.

position = 9
planet + ", für mich wirst du immer der " + position + "te planet sein."
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/tmp/ipykernel_20/1802981568.py in <module>
1 position = 9
----> 2 planet + ", für mich wirst du immer der " + position + "te planet sein."

TypeError: can only concatenate str (not "int") to str

planet + ", für mich wirst du immer der " + str(position) + "te planet sein."
"Pluto, für mich wirst du immer der 9te Planet sein."

Langsam wird all das Tippen schwer zu lesen und nervig zu schreiben. str.format() rettet uns jetzt.

"{}, für mich wirst du immer der {}te Planet sein".format(planet, position)

"Pluto, für mich wirst du immer der 9te Planet sein."

Schon um einiges besser. Die Python Werte, die wir einsetzen wollen, packen wir in .format() rein und die Stelle,
wo sie sein sollen, wird mit dem Platzhalter {} besetzt.
Es ist so gut, dass wir nicht einmal str() machen müssten, damit der Integer zum String wird und das beste ist,
es kann noch mehr. Hier eine kleine Kostprobe:

pluto_masse = 1.303 * 10**22
erd_masse = 5.9722 * 10**24
population = 52910390


# 2 Dezimalstellen 3 Dezimalstellen, als Prozent formatiert mit Punkten trennen
"{} wiegt zirka {:.2} Kilogramm ({:.3%} von der Masse der Erde). Es ist der Lebensraum für {:.} Plutonier." .format(
planet, pluto_masse, pluto_masse / erd_masse, population,
)
"Pluto wiegt zirka 1.3e+22 Kilogramm (0.218% von der Masse der Erde). Es ist der Lebensraum für 52.910.390 Plutonier."

# Wir beziehen uns hier an format() mit Indexen, es fängt wiedermal mit 0 an.

s = """Pluto ist ein {0}.
Nein, es ist ein {1}.
{0}!
{1}!""".format("Planet", "Zwergplanet")
print(s)

Pluto ist ein Planet.
Nein, es ist ein Zwergplanet.
Planet!
Zwergplanet!

Man könnte wahrscheinlich ein ganzes Buch über str.format schreiben, also hören wir hier auf, bevor das noch eskaliert
und leiten dich weiter zum pyformat.info und the official docs für ein mögliches Selbststudium.

Dictionaries


Dictionaries sind eine eingebaute Python Datastruktur, um Schlüsselwörter zu Werten zu verknüpfen.

nummern = {"eins":1, "zwei":2, "drei":3}

Hier sind "eins", "zwei" und "drei" unsere Schlüssel und 1, 2 und 3 die korrespondierenden Werte,
auf diese kann man mit eckigen Klammern zugreifen, ähnlich wie das Indexieren bei Listen und Strings.

nummern["eins"]

1

Wir können auch die gleiche Syntax nutzen, um ein weiteres Schlüssel- und ein Wertepaar einzufügen.

nummern["elf"] = 11
nummern

{"eins":1, "zwei":2, "drei":3, "elf":11}

Oder wir könnten den assoziierten Wert für einen bereits existierenden Schlüssel ändern.

nummern["eins"] = "Pluto"
nummern

{"eins":"Pluto", "zwei":2, "drei":3, "elf":11}

Python hat Dictionary Comprehensions mit Syntax, es ist ähnlich wie die List Comprehensions, die wir in der vorherigen Einheit gesehen haben.

planeten = ["Merkur", "Venus", "Erde", "Mars", "Jupiter", "Saturn", "Uranus", "Neptun"]
planet_zu_initialen = {planet: planet[0] for planet in planeten}
planet_zu_initialen
{ "Merkur" : "M",
"Venus" : "V",
"Erde" : "E",
"Mars" : "M",
"Jupiter" : "J",
"Saturn" : "S",
"Uranus" : "U",
"Neptun" : "N"}

Der in Operant gibt uns Bescheid, ob etwas ein Schlüssel im Dictionary ist.

"Saturn" in planet_zu_initialen

True

"Beteigeuze" in planet_zu_initialen

False

Eine for Schleife auf einer Dictionary wird deren Schlüssel wiedergeben.

for k in nummern:
print("{} = {}".format(k, numbers[k]))
eins = Pluto
zwei = 2
drei = 3
elf = 11

Wir können auf eine Sammlung der Schlüssel bzw. Werte mit dict.keys() und dict.values() zugreifen.

# Nimm alle Initialen, sortiere sie Alphabetisch und trenne sie mit einem Leerzeichen String.
" ".join(sorted(planet_zu_initialen.values)))

"E J M M N S U V"

Wenn uns beides interessiert, dann verwenden wir das nützliche dict.items(), weil sich ein "Item" auf ein Schlüssel- und Wertepaar bezieht.

for planet, initialen in planet_zu_initialen.items():
print("{} fangt mit einem \"{}\" an".format(planet.rjust(10), initialen))
Merkur fängt mit einem "M" an
Venus fängt mit einem "V" an
Erde fängt mit einem "E" an
Mars fängt mit einem "M" an
Jupiter fängt mit einem "J" an
Saturn fängt mit einem "S" an
Uranus fängt mit einem "U" an
Neptun fängt mit einem "N" an

Um mehr über die Methoden der Dictionaries zu erfahren, würde ich entweder das gesamte help(dict) durchlesen oder die official online documentation durchlesen. help(dict)
Output (Warnung: Massiv) Help on class dict in module builtins:

class dict(object)
| dict() -> new empty dictionary
| dict(mapping) -> new dictionary initialized from a mapping object's
| (key, value) pairs
| dict(iterable) -> new dictionary initialized as if via:
| d = {}
| for k, v in iterable:
| d[k] = v
| dict(**kwargs) -> new dictionary initialized with the name=value pairs
| in the keyword argument list. For example: dict(one=1, two=2)
|
| Methods defined here:
|
| __contains__(self, key, /)
| True if the dictionary has the specified key, else False.
|
| __delitem__(self, key, /)
| Delete self[key].
|
| __eq__(self, value, /)
| Return self==value.
|
| __ge__(self, value, /)
| Return self>=value.
|
| __getattribute__(self, name, /)
| Return getattr(self, name).
|
| __getitem__(...)
| x.__getitem__(y) <==> x[y]
|
| __gt__(self, value, /)
| Return self>value.
|
| __init__(self, /, *args, **kwargs)
| Initialize self. See help(type(self)) for accurate signature.
|
| __iter__(self, /)
| Implement iter(self).
|
| __le__(self, value, /)
| Return self<=value.
|
| __len__(self, /)
| Return len(self).
|
| __lt__(self, value, /)
| Return self <value.
|
| __ne__(self, value, /)
| Return self!=value.
|
| __repr__(self, /)
| Return repr(self).
|
| __setitem__(self, key, value, /)
| Set self[key] to value.
|
| __sizeof__(...)
| D.__sizeof__() -> size of D in memory, in bytes
|
| clear(...)
| D.clear() -> None. Remove all items from D.
|
| copy(...)
| D.copy() -> a shallow copy of D
|
| get(self, key, default=None, /)
| Return the value for key if key is in the dictionary, else default.
|
| items(...)
| D.items() -> a set-like object providing a view on D's items
|
| keys(...)
| D.keys() -> a set-like object providing a view on D's keys
|
| pop(...)
| D.pop(k[,d]) -> v, remove specified key and return the corresponding value.
| If key is not found, d is returned if given, otherwise KeyError is raised
|
| popitem(...)
| D.popitem() -> (k, v), remove and return some (key, value) pair as a
| 2-tuple; but raise KeyError if D is empty.
|
| setdefault(self, key, default=None, /)
| Insert key with a value of default if key is not in the dictionary.
|
| Return the value for key if key is in the dictionary, else default.
|
| update(...)
| D.update([E, ]**F) -> None. Update D from dict/iterable E and F.
| If E is present and has a .keys() method, then does: for k in E: D[k] = E[k]
| If E is present and lacks a .keys() method, then does: for k, v in E: D[k] = v
| In either case, this is followed by: for k in F: D[k] = F[k]
|
| values(...)
| D.values() -> an object providing a view on D's values
|
| ----------------------------------------------------------------------
| Class methods defined here:
|
| fromkeys(iterable, value=None, /) from builtins.type
| Create a new dictionary with keys from iterable and values set to value.
|
| ----------------------------------------------------------------------
| Static methods defined here:
|
| __new__(*args, **kwargs) from builtins.type
| Create and return a new object. See help(type) for accurate signature.
|
| ----------------------------------------------------------------------
| Data and other attributes defined here:
|
| __hash__ = None