Szukam eleganckiego sposobu na uzyskanie danych za pomocą dostępu do atrybutu w nagraniu z niektórymi zagnieżdżonymi dyktami i listami (tj. Składnią obiektu w stylu javascript).
Na przykład:
>>> d = {'a': 1, 'b': {'c': 2}, 'd': ["hi", {'foo': "bar"}]}
Powinny być dostępne w ten sposób:
>>> x = dict2obj(d)
>>> x.a
1
>>> x.b.c
2
>>> x.d[1].foo
bar
Myślę, że nie jest to możliwe bez rekurencji, ale jaki byłby fajny sposób na uzyskanie stylu obiektowego dla nagrań?
python
object
dictionary
Marc
źródło
źródło
from_
zamiast_from
zgodnie z PEP 8 .getattr(x, 'from')
zamiast zmiany nazwy atrybutu.d1.b.c
), myślę, że jasne jest, że powinieneś używać czegoś z biblioteki, np. Nametuple ze zbiorów , jak sugeruje ta odpowiedź … .Odpowiedzi:
Aktualizacja: w Pythonie 2.6 i nowszych rozważ, czy
namedtuple
struktura danych odpowiada Twoim potrzebom:Alternatywą (oryginalna treść odpowiedzi) jest:
Następnie możesz użyć:
źródło
Struct
s ze zagnieżdżonych słowników, ale ogólnie typ wartości może być dowolny. Klucz ogranicza się do dopasowania do miejsca na przedmiotyargparse.Namespace
(który ma również określone__eq__
,__ne__
,__contains__
).źródło
if isinstance(b, (list, tuple)):
obj
dziedziczy klasaargparse.Namespace
po dodatkowe funkcje, takie jak czytelna reprezentacja ciągu.Zaskakujące, że nikt nie wspomniał o Bunchu . Ta biblioteka służy wyłącznie do zapewnienia dostępu do obiektów typu dict w stylu atrybutów i robi dokładnie to, czego chce OP. Demonstracja:
Biblioteka Python 3 jest dostępna na stronie https://github.com/Infinidat/munch - Kredyt trafia do codyzu
źródło
następnie dodaj do tego rekursję i gotowe.
edytuj to jak to zaimplementuję:
źródło
top_instance = top()
i zwrócić to tam, gdzie wrócisztop
?x
ax.b
które zwracają brzydki<class '__main__.new'>
Nazywa się pomocnik kolekcji
namedtuple
, który może to dla Ciebie zrobić:źródło
Może być stosowany z dowolną strukturą sekwencji / nagrania / wartości o dowolnej głębokości.
źródło
def __repr__(self): return '{%s}' % str(', '.join("'%s': %s" % (k, repr(v)) for (k, v) in self.__dict__.iteritems()))
.items()
języka Python 3.x: po prostu zamiast.iteritems()
w wierszu 4. (Nazwa została zmieniona, ale zasadniczo jest taka sama )Biorąc to, co uważam za najlepsze aspekty poprzednich przykładów, oto co wymyśliłem:
źródło
def __init__(self, dct): for k, v in dct.iteritems(): setattr(self, k, isinstance(v, dict) and self.__class__(v) or v)
co również usuwa jawne wezwanie doStruct
isinstance(v, dict)
check będzie lepiej, jakisinstance(v, collections.Mapping)
więc może obsłużyć przyszłość dict-jak rzeczyJeśli pochodzi Twój dykt
json.loads()
, możesz go przekształcić w obiekt (zamiast dykta) w jednym wierszu:Zobacz także Jak przekonwertować dane JSON na obiekt Python .
źródło
.loads
jeśli masz ogromny obiekt JSONJeśli chcesz uzyskać dostęp do kluczy dyktafonu jako obiektu (lub dykta dla trudnych klawiszy), zrób to rekurencyjnie, a także możesz zaktualizować oryginalny dykta, możesz:
Przykładowe użycie:
źródło
źródło
Skończyło się na próbowaniu ZARÓWNO AttrDict i Bunchbibliotek i stwierdził, że są one zbyt wolne dla moich zastosowań. Po przyjrzeniu się temu przyjacielowi stwierdziliśmy, że główna metoda pisania tych bibliotek powoduje, że biblioteka agresywnie rekurencyjnie przeszukuje zagnieżdżony obiekt i tworzy kopie obiektu słownika w całym tekście. Mając to na uwadze, wprowadziliśmy dwie kluczowe zmiany. 1) Stworzyliśmy atrybuty leniwie załadowane 2) zamiast tworzyć kopie obiektu słownika, tworzymy kopie lekkiego obiektu proxy. To jest ostateczne wdrożenie. Wzrost wydajności korzystania z tego kodu jest niesamowity. Podczas korzystania z AttrDict lub Bunch te dwie biblioteki same pochłonęły odpowiednio 1/2 i 1/3 mojego czasu żądania (co !?). Ten kod skrócił ten czas prawie do zera (gdzieś w zakresie 0,5 ms). To oczywiście zależy od twoich potrzeb,
Zobacz oryginalną implementację tutaj : https://stackoverflow.com/users/704327/michael-merickel .
Inną rzeczą do odnotowania jest to, że ta implementacja jest dość prosta i nie implementuje wszystkich metod, których możesz potrzebować. Musisz zapisać je zgodnie z wymaganiami na obiektach DictProxy lub ListProxy.
źródło
x.__dict__.update(d)
powinno być w porządku.źródło
__dict__
: spróbuj,object().__dict__
a dostanieszAttributeError: 'object' object has no attribute '__dict__'
Możesz wykorzystać
json
moduł biblioteki standardowej za pomocą niestandardowego zaczepu obiektu :Przykładowe użycie:
I to jest nie ściśle tylko do odczytu , jak to jest z
namedtuple
, czyli można zmieniać wartości - nie struktura:źródło
json.JSONEncoder
iobject_hook
.To powinno zacząć:
To jeszcze nie działa w przypadku list. Będziesz musiał zawinąć listy w UserList i przeładować,
__getitem__
aby zawinąć dyktanda.źródło
if isinstance(d, list)
klauzuli zAnon
odpowiedzi.Wiem, że jest tu już wiele odpowiedzi i spóźniam się na imprezę, ale ta metoda rekursywnie i „na miejscu” przekształci słownik w obiektową strukturę ... Działa w wersji 3.xx
źródło
źródło
Pozwól, że wyjaśnię rozwiązanie, z którego prawie kiedyś korzystałem. Ale po pierwsze, powodem, dla którego tego nie zrobiłem, jest fakt, że następujący kod:
daje ten błąd:
Ponieważ „from” jest słowem kluczowym Python, istnieją pewne klucze słownika, na które nie można zezwolić.
Teraz moje rozwiązanie umożliwia dostęp do elementów słownika poprzez bezpośrednie używanie ich nazw. Ale pozwala także na użycie „semantyki słownika”. Oto kod z przykładowym użyciem:
źródło
Stare pytania i odpowiedzi, ale mam coś więcej do powiedzenia. Wydaje się, że nikt nie mówi o rekursywnym dykcie. To jest mój kod:
źródło
Chciałem przesłać moją wersję tego małego paradygmatu.
Zachowuje atrybuty typu importowanego do klasy. Moją jedyną troską byłoby zastąpienie metod parsowania ze słownika. Ale poza tym wydaje się solidny!
źródło
df.a
nawet nie działa.To też działa dobrze
źródło
Oto inny sposób implementacji oryginalnej sugestii SilentGhost:
źródło
Natknąłem się na przypadek, w którym musiałem rekurencyjnie przekonwertować listę dykt na listę obiektów, więc na podstawie fragmentu Roberta tutaj, co zadziałało dla mnie:
Zauważ, że każda krotka zostanie z oczywistych powodów przekonwertowana na ekwiwalent listy.
Mam nadzieję, że to pomaga komuś tak samo jak wszystkie twoje odpowiedzi, chłopaki.
źródło
Co powiesz na przypisanie
dict
do__dict__
pustego obiektu?Oczywiście nie powiedzie się to na przykładzie zagnieżdżonego słownika, chyba że rekursywnie przeprowadzisz go:
Twój przykładowy element listy prawdopodobnie miał być
Mapping
listą (klucz, wartość) w następujący sposób:źródło
Oto kolejna implementacja:
[Edytuj] Brakowało trochę na temat obsługi dykt na listach, a nie tylko innych dykt. Dodano poprawkę.
źródło
Stosowanie:
źródło
Co powiesz na to:
Można to następnie wykorzystać w następujący sposób:
źródło
Myślę, że dykt składa się z liczby, ciągu i dykt wystarcza przez większość czasu. Dlatego ignoruję sytuację, w której krotki, listy i inne typy nie pojawiają się w ostatecznym wymiarze dykta.
Biorąc pod uwagę dziedziczenie w połączeniu z rekurencją, wygodnie rozwiązuje problem z drukowaniem, a także zapewnia dwa sposoby wyszukiwania danych, jeden sposób edycji danych.
Zobacz poniższy przykład, który opisuje niektóre informacje o uczniach:
Wyniki:
źródło
Zazwyczaj chcesz odzwierciedlać hierarchię dyktowania w swoim obiekcie, ale nie wyświetlać list ani krotek, które zwykle znajdują się na najniższym poziomie. Oto jak to zrobiłem:
Więc robimy:
i dostać:
x.b.b1.x
1x.c
[„cześć”, „bar”]źródło
Mój słownik ma ten format:
Jak widać, zagnieżdżiłem słowniki i listę dykt . Wynika to z faktu, że addr_bk został zdekodowany z danych bufora protokołu, które przekonwertowano na dict Pythona za pomocą lwpb.codec. Istnieją pola opcjonalne (np. E-mail => gdzie klucz może być niedostępny) i pole powtarzane (np. Telefon => przekonwertowane na listę nagrań).
Wypróbowałem wszystkie wyżej zaproponowane rozwiązania. Niektóre nie radzą sobie dobrze z zagnieżdżonymi słownikami. Inni nie mogą łatwo wydrukować szczegółów obiektu.
Tylko rozwiązanie, dict2obj (dict) autorstwa Dawie Strauss, działa najlepiej.
Ulepszyłem go trochę, gdy nie można znaleźć klucza:
Następnie przetestowałem to z:
źródło
Opierając moją odpowiedź na „ python: Jak dynamicznie dodawać właściwość do klasy? ”:
Wywołujesz
makedata
słownik, który chcesz przekonwertować, a może wtrydata
zależności od tego, czego oczekujesz jako dane wejściowe, i wyrzuca obiekt danych.Uwagi:
trydata
jeśli potrzebujesz więcej funkcji.x.a = {}
lub podobnie.źródło