481 Stimmen

Wie verwende ich einen Punkt "." um auf Elemente eines Wörterbuchs zuzugreifen?

Wie mache ich Python-Wörterbuchmitglieder über einen Punkt "." zugänglich?

Zum Beispiel würde ich gerne statt mydict['val'] mydict.val schreiben.

Außerdem würde ich gerne auf verschachtelte Wörterbücher auf diese Weise zugreifen. Zum Beispiel

mydict.mydict2.val 

würde sich auf

mydict = { 'mydict2': { 'val': ... } }

32 Stimmen

Viele der Situationen, in denen Menschen verschachtelte Dicts verwenden, könnten genauso gut oder sogar besser durch Dicts mit Tupeln als Schlüssel gelöst werden, wobei d[a][b][c] durch d[a, b, c] ersetzt wird.

0 Stimmen

Können Sie bitte näher erläutern, wie d[a][b][c] durch d[a, b, c] ersetzt werden kann? Ich habe noch nicht verstanden, wie das gemacht werden kann.

9 Stimmen

Es ist kein Zauberei: foo={}; foo[1,2,3] = "one, two, three!"; foo.keys() => [(1,2,3)]

1voto

Emil Stenström Punkte 11959

Eine einfache Möglichkeit, Punktzugriff (aber kein Arrayzugriff) zu erhalten, besteht darin, ein einfaches Objekt in Python zu verwenden. Wie folgt:

Klasse YourObject:
    def __init__(self, *args, **kwargs):
        für k, v in kwargs.items():
            setattr(self, k, v)

...und verwenden Sie es so:

>>> obj = YourObject(key="value")
>>> print(obj.key)
"value"

... um es in ein Dict umzuwandeln:

>>> print(obj.__dict__)
{"key": "value"}

1voto

marnix Punkte 1210

Die Antwort von @derek73 ist sehr ordentlich, aber sie kann nicht eingelegt oder (tief)kopiert werden und gibt für fehlende Schlüssel None zurück. Der folgende Code behebt das.

Bearbeiten: Ich habe nicht gesehen, dass die oben genannte Antwort genau denselben Punkt anspricht (upgevotet). Ich lasse die Antwort hier als Referenz.

class dotdict(dict):
    __setattr__ = dict.__setitem__
    __delattr__ = dict.__delitem__

    def __getattr__(self, name):
        try:
            return self[name]
        except KeyError:
            raise AttributeError(name)

1voto

arod Punkte 12612

Ich musste nur auf ein Wörterbuch zugreifen, indem ich einen Punkt-Pfadstring verwendete, also habe ich das gemacht:

def get_value_from_path(dictionary, parts):
    """ extrahiert einen Wert aus einem Wörterbuch unter Verwendung eines Punktpfadstrings """

    if type(parts) is str:
        parts = parts.split('.')

    if len(parts) > 1:
        return get_value_from_path(dictionary[parts[0]], parts[1:])

    return dictionary[parts[0]]

a = {'a':{'b':'c'}}
print(get_value_from_path(a, 'a.b')) # c

1voto

James McGuigan Punkte 6675

Die Implementierung, die von kaggle_environments verwendet wird, ist eine Funktion namens structify.

class Struct(dict):
    def __init__(self, **entries):
        entries = {k: v for k, v in entries.items() if k != "items"}
        dict.__init__(self, entries)
        self.__dict__.update(entries)

    def __setattr__(self, attr, value):
        self.__dict__[attr] = value
        self[attr] = value

# Zusätzlicher Vorteil: Klonen von Listen und Dictionaries.
def structify(o):
    if isinstance(o, list):
        return [structify(o[i]) for i in range(len(o))]
    elif isinstance(o, dict):
        return Struct(**{k: structify(v) for k, v in o.items()})
    return o

Dies kann nützlich sein, um KI-Simulationsagenten in Spielen wie ConnectX zu testen.

from kaggle_environments import structify

obs  = structify({ 'remainingOverageTime': 60, 'step': 0, 'mark': 1, 'board': [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]})
conf = structify({ 'timeout': 2, 'actTimeout': 2, 'agentTimeout': 60, 'episodeSteps': 1000, 'runTimeout': 1200, 'columns': 7, 'rows': 6, 'inarow': 4, '__raw_path__': '/kaggle_simulations/agent/main.py' })

def agent(obs, conf):
  action = obs.step % conf.columns
  return action

0voto

М.Б. Punkte 1200

Ich habe eine Lösung erstellt, die (fast) jeden Zugriff auf Attribute von Listen/Dictionaries/Tupeln/Objekten sowohl mit Punkt als auch mit regulärem (erstem Ebenen-)Zugriff ermöglichen sollte:

def get(obj, key: str | int, default=None):
    """
    Versucht, Index, Schlüssel oder eine Eigenschaft
    für ein gegebenes Dictionary, Liste oder Objekt zu erhalten,
    gibt standardmäßig Fehler zurück

    Args:
        - obj (Gemischt): Dictionary, Liste, Objekt
        - key (str): beliebiger Schlüssel oder Punkt-Zugriff wie: foo.bar.0
    Returns:
        - Gemischt | None
    """

    key = str(key)
    keys = [key]
    if '.' in key:
        keys = key.split('.')

    val = obj
    for k in keys:
        if not k:
            continue

        try:
            if isinstance(val, list):
                val = val[k]
            elif isinstance(val, dict):
                val = val.get(k, default)
            else:
                val = getattr(val, k, default)
        except (IndexError, KeyError, AttributeError, TypeError, ValueError) as e:
            if 'list indices must be integers or slices, not str' in str(e):
                try:
                    k = int(k)
                    val = val[k]
                except (ValueError, KeyError, IndexError):
                    val = default
            else:
                return default

    return val

https://gist.github.com/milosb793/80610e15f5c547e29558e466c65cbe22

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X