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)]

0voto

Hedde van der Heide Punkte 20395

Keine direkte Antwort auf die Frage des OP, aber inspiriert von und vielleicht nützlich für einige.. Ich habe eine objektbasierte Lösung mit dem internen __dict__ erstellt (In keiner Weise optimierter Code)

payload = {
    "name": "John",
    "location": {
        "lat": 53.12312312,
        "long": 43.21345112
    },
    "numbers": [
        {
            "role": "home",
            "number": "070-12345678"
        },
        {
            "role": "office",
            "number": "070-12345679"
        }
    ]
}

class Map(object):
    """
    Punktzugriff auf Objektmitglieder, Zugriff auf Rohwerte
    mit einem Unterstrich z.B.

    class Foo(Map):
        def foo(self):
            return self.get('foo') + 'bar'

    obj = Foo(**{'foo': 'foo'})

    obj.foo => 'foobar'
    obj._foo => 'foo'

    """

    def __init__(self, *args, **kwargs):
        for arg in args:
            if isinstance(arg, dict):
                for k, v in arg.items():
                    self.__dict__[k] = v
                    self.__dict__['_' + k] = v

        if kwargs:
            for k, v in kwargs.items():
                self.__dict__[k] = v
                self.__dict__['_' + k] = v

    def __getattribute__(self, attr):
        if hasattr(self, 'get_' + attr):
            return object.__getattribute__(self, 'get_' + attr)()
        else:
            return object.__getattribute__(self, attr)

    def get(self, key):
        try:
            return self.__dict__.get('get_' + key)()
        except (AttributeError, TypeError):
            return self.__dict__.get(key)

    def __repr__(self):
        return u"<{name} object>".format(
            name=self.__class__.__name__
        )

class Number(Map):
    def get_role(self):
        return self.get('role')

    def get_number(self):
        return self.get('number')

class Location(Map):
    def get_latitude(self):
        return self.get('lat') + 1

    def get_longitude(self):
        return self.get('long') + 1

class Item(Map):
    def get_name(self):
        return self.get('name') + " Doe"

    def get_location(self):
        return Location(**self.get('location'))

    def get_numbers(self):
        return [Number(**n) for n in self.get('numbers')]

# Tests

obj = Item({'foo': 'bar'}, **payload)

assert type(obj) == Item
assert obj._name == "John"
assert obj.name == "John Doe"
assert type(obj.location) == Location
assert obj.location._lat == 53.12312312
assert obj.location._long == 43.21345112
assert obj.location.latitude == 54.12312312
assert obj.location.longitude == 44.21345112

for n in obj.numbers:
    assert type(n) == Number
    if n.role == 'home':
        assert n.number == "070-12345678"
    if n.role == 'office':
        assert n.number == "070-12345679"

-3voto

Yonks Somarl Punkte 11

Eine Lösung irgendwie delikat

class DotDict(dict):

    __setattr__ = dict.__setitem__
    __delattr__ = dict.__delitem__

    def __getattr__(self, key):

        def typer(candidate):
            if isinstance(candidate, dict):
                return DotDict(candidate)

            if isinstance(candidate, str):  # iterable but no need to iter
                return candidate

            try:  # other iterable are processed as list
                return [typer(item) for item in candidate]
            except TypeError:
                return candidate

            return candidate

        return typer(dict.get(self, key))

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