Exkurs 2: das Dictionary#

Schauen wir uns an dieser Stelle einen neuen Objekt-Typ an, der sich gut dazu eignet, einen Agenten mit mehreren Eigenschaften darzustellen: das Dictionary bzw. dict. Ein Dictionary ist ähnlich wie eine Liste ein Form von Datencontainer, in den wir alle möglichen Objekte ablegen können. Listen sind zwar praktisch, weil man dort relativ unkompliziert, relativ viele Dinge einfach “reinwerfen” kann. Will man aus der Liste allerdings ein ganz spezifisches Objekt wiederfinden, dann ist das nicht mehr so unkompliziert. Dann müsste man entweder den spezifischen Positionsindex wissen oder das Objekt mit verschiedenen Methoden suchen. Eine Liste eignet sich daher v.a. dafür, wenn man viele gleiche oder unspezifische Objekte einfach irgendwo “sammeln” muss, damit man dann z.B. innerhalb eines For-Loops diese Objekte nacheinander abarbeiten kann. Eine Liste ist also z.B. perfekt, um eine Population von Agenten abzuspeichern. Um die Agenten selbst zu repräsentieren, mit den je spezifischen Eigenschaften der Agenten, auf die man beim Handeln der Agenten ganz gezielt zugreifen muss, eignen sich Listen also eigentlich gar nicht so wirklich gut. Viel besser sind tatsächlich Dictionaries.

Ein Dictionary sind ein Datencontainer, in welchen man Objekte unter einem (sinnvollen) Namen ablegen kann. Diesen Namen nennt man auch Key. Mithilfe eines solchen Keys kann man dann, ganz gezielt die Objekte wiederfinden und darauf zugreifen. Das ist praktisch, wenn man Objekte etwas “geordneter” als in Listen verstauen möchte. Wie sehen solche Dictionaries aus? Während Listen mit zwei eckigen Klammern [] erzeugt werden, erzeugt man Dictionaries mit zwei geschweiften Klammern: {}. {} ist ein leeres Dictionary.

Möchte man ein Dictionary mit Inhalt erstellen, dann muss man den Inhalt immer in sogenannten Key-Value-Paaren aufschreiben, was allgemein so aussieht:

{KEY: VALUE}

Während der KEY ein Platzhalter für irgendeinen Namen ist, ist VALUE ein Platzhalter für irgendein Objekt, das dort unter dem gewählten Namen KEY abgelegt wird. KEY und VALUE sind immer durch einen Doppelpunkt getrennt bzw. verbunden. Möchte man mehrere Objekte in einem Dictionary ablegen, dann muss man die Key-Value-Paare durch Kommas trennen, was allgemein dann so aussieht:

{KEY1: VALUE1, KEY2: VALUE2, KEY3: VALUE3}

Schauen wir uns das mal konkret in Python an. Unten erstelle ich ein Dictionary und weise es der Variable agent zu. Im Dictionary agent habe ich das Objekt 10 unter dem Namen “opinion” abgelegt.

agent = {"opinion": 10}
agent
{'opinion': 10}

Möchte ich nun auf die "opinion" des agent zugreifen, muss ich dafür ähnlich wie bei Listen eine Form der Indexierung anwenden. Statt des Positionsindex muss ich nun aber einfach den Namen d.h. den Key, unter dem ich das Objekt im Dictionary abgelegt habe, in eckigen Klammern angeben:

agent["opinion"]
10

Allgemein formuliert greift man auf ein unter KEY in DICTIONARY abgelegtes Objekt immer so zu: DICTIONARY[KEY].

Unten erstelle ich ein Dictionary namens agent und füge diesmal drei Key-Value-Paare ein:

agent = {"opinion": 10, "name": "Hartmut", "age": 77}

Es hat sich übrigens ähnlich wie bei Listen auch eine solche Schreibweise eingebürgert:

agent = {
    "opinion": 10, 
    "name": "Hartmut", 
    "age": 77,
}
agent
{'opinion': 10, 'name': 'Hartmut', 'age': 77}

Nun kann ich ganz gezielt und ohne mir irgendeinen Positionsindex merken zu müssen, auf die Eigenschaften des agent zugreifen. Stattdessen muss ich natürlich wissen, unter welchem Key die Objekte jeweils zu finden sind.

agent["name"]
'Hartmut'
agent["opinion"]
10
agent["age"]
77

Unten sieht man ein typisches Szenario, das man fast am Anfang jeder Simulation sieht. Es wird eine zunächst leere Liste population erstellt, welche dann nach und nach innerhalb eines For-Loops mit Agenten befüllt wird. Die Agenten mit jeweils zwei Eigenschaften implementiere ich dabei als Dictionary.

import random

# Leere Populationsliste erstellen
population = []

# 5 mal
for i in range(5):
    
    # Agenten erstellen
    agent = {
        "id": i, 
        "opinion": random.randint(0,10),
    }
    
    # An Populationsliste anhängen
    population.append(agent)
population
[{'id': 0, 'opinion': 9},
 {'id': 1, 'opinion': 8},
 {'id': 2, 'opinion': 9},
 {'id': 3, 'opinion': 4},
 {'id': 4, 'opinion': 3}]

Dictionaries sind genau wie Listen veränderbare Objekte. Das ist praktisch, wie das folgende Beispiel zeigt: Angenommen wir möchten die “Meinungen” der Agenten verändern und alle Meinungswerte um 1 erhöhen. Nun können wir einfach innerhalb eines For-Loops alle Agenten durchgehen und den Agenten (bzw. die Meinung des Agenten) direkt über die Schleifenvariable verändern:

for agent in population:
    agent["opinion"] = agent["opinion"] + 1
population
[{'id': 0, 'opinion': 10},
 {'id': 1, 'opinion': 9},
 {'id': 2, 'opinion': 10},
 {'id': 3, 'opinion': 5},
 {'id': 4, 'opinion': 4}]

Mit Kurzschreibweise sähe das übrigens so aus:

for agent in population:
    agent["opinion"] += 1
population
[{'id': 0, 'opinion': 11},
 {'id': 1, 'opinion': 10},
 {'id': 2, 'opinion': 11},
 {'id': 3, 'opinion': 6},
 {'id': 4, 'opinion': 5}]

Ein Dictionary erweitern: update()#

Ein Dictionary verfügt über eine ganze Reihe von Methoden. An dieser Stelle möchte ich eine davon vorstellen, die man hin und wieder braucht. Mit der Methode update() kann man ein bereits bestehendes Dictionary um ein oder mehr Elemente bzw. Key-Value-Paare erweitern.

Man hängt die Methode update() wie jede Methode an das entsprechende Dictionary-Objekt an. Als Input erwartet die Methode update() ein weiteres Dictionary, das dann in das bereits bestehende Dictionary integriert wird. Die Methode update() ist letztlich genau das, was die Methode extend() für Listen ist.

Unten erstelle ich zunächst das Dictionary agent.

agent = {
    "opinion": 10, 
    "name": "Hartmut", 
    "age": 77,
}

Nun erweitere ich agent mithilfe von update() um ein weiteres Element namens "city":

agent.update({"city": "Mannheim"})
agent
{'opinion': 10, 'name': 'Hartmut', 'age': 77, 'city': 'Mannheim'}

Nun erweitere ich agent um zwei weitere Elemente:

agent.update({
    "work": False,
    "topic": "migration",
})
agent
{'opinion': 10,
 'name': 'Hartmut',
 'age': 77,
 'city': 'Mannheim',
 'work': False,
 'topic': 'migration'}