Dlaczego lista nie ma bezpiecznej metody „get”, takiej jak słownik?
>>> d = {'a':'b'}
>>> d['a']
'b'
>>> d['c']
KeyError: 'c'
>>> d.get('c', 'fail')
'fail'
>>> l = [1]
>>> l[10]
IndexError: list index out of range
Dlaczego lista nie ma bezpiecznej metody „get”, takiej jak słownik?
>>> d = {'a':'b'}
>>> d['a']
'b'
>>> d['c']
KeyError: 'c'
>>> d.get('c', 'fail')
'fail'
>>> l = [1]
>>> l[10]
IndexError: list index out of range
l[10:11]
tego poprosisz o plasterek: zamiastl[10]
, na przykład. () Podlista będzie miała pożądany element, jeśli istnieje).get
. Byłby to odpowiednikl[i] if i < len(l) else default
, ale bardziej czytelny, bardziej zwięzły i pozwalający nai
wyrażenie bez konieczności ponownego obliczaniaNone
jeśli nie istniał. Byłoby miło powiedziećx = expensive().get(0, None)
, że nie musiałbym umieszczać bezużytecznego zwrotu drogiego w zmiennej tymczasowej.Odpowiedzi:
Ostatecznie prawdopodobnie nie ma bezpiecznej
.get
metody, ponieważ adict
jest kolekcją asocjacyjną (wartości są powiązane z nazwami), w której nieefektywne jest sprawdzenie, czy klucz jest obecny (i zwrócenie jego wartości) bez zgłaszania wyjątku, podczas gdy jest on bardzo trywialny aby uniknąć wyjątków dostępu do elementów listy (ponieważlen
metoda jest bardzo szybka). Ta.get
metoda umożliwia zapytanie o wartość związaną z nazwą, a nie bezpośredni dostęp do 37 pozycji w słowniku (co byłoby bardziej podobne do tego, o co pytasz z listy).Oczywiście możesz to łatwo zaimplementować samodzielnie:
Możesz nawet dopasować go do
__builtins__.list
konstruktora w__main__
, ale byłaby to mniej powszechna zmiana, ponieważ większość kodu go nie używa. Jeśli chcesz tego użyć z listami utworzonymi przez Twój własny kod, możesz po prostu podklasęlist
i dodaćget
metodę.źródło
list
.get
rozwiązuje problem, którego nie ma na listach - skuteczny sposób na uniknięcie wyjątków podczas pobierania danych, które mogą nie istnieć. Bardzo trywialne i bardzo skuteczne jest sprawdzenie, czym jest prawidłowy indeks listy, ale nie ma szczególnie dobrego sposobu na zrobienie tego dla kluczowych wartości w słowniku.O(1)
. Z grubsza nie będzie to tak szybkie jak sprawdzanielen
, ale ze złożonego punktu widzenia są one wszystkieO(1)
. Prawidłowa odpowiedź to typowe zastosowanie / semantyka ...dict
jest to tylko najlepszy przypadek O (1), nie wszystkie przypadki..get()
albo masz problemy w innym miejscu w kodzie (lub środowisku). Istotą takiej metody jest czytelność kodu. Technika „waniliowa” wymaga czterech wierszy kodu w każdym miejscu, w którym należy to zrobić. Ta.get()
technika wymaga tylko jednego i może być łatwo połączona za pomocą kolejnych wywołań metod (npmy_list.get(2, '').uppercase()
.).Działa to, jeśli chcesz pierwszego elementu, takiego jak
my_list.get(0)
Wiem, że nie jest to dokładnie to, o co prosiłeś, ale może pomóc innym.
źródło
next(iter(my_list[index:index+1]), 'fail')
Pozwala na każdym indeksie, a nie tylko mniej lub 0. FP ale zapewne bardziej pythonowy, a prawie na pewno bardziej czytelny:my_list[index] if index < len(my_list) else 'fail'
.Prawdopodobnie dlatego, że nie miało to większego sensu dla semantyki listy. Możesz jednak łatwo utworzyć własne, podklasując.
źródło
get
metody. Liczy się czytelność. A czytelność cierpi z każdą dodatkową niepotrzebną klasą. Po prostu zastosujtry / except
podejście bez tworzenia podklas.Zamiast używać .get, używanie w ten sposób powinno być odpowiednie dla list. Różnica w użyciu.
źródło
.get
metodę (z wyjątkiem tego, że nie jestem pewien, w jaki sposób wyjaśniłbyś, co oznaczał indeks w tym przypadku lub dlaczego miałby się nie powieść).lst[i] if -len(lst) <= i < len(l) else 'fail'
Spróbuj tego:
źródło
Kredyty dla jose.angel.jimenez
Dla fanów „oneliner”…
Jeśli chcesz pierwszy element listy lub jeśli chcesz wartość domyślną, jeśli lista jest pusta, spróbuj:
zwroty
a
i
zwroty
default
Przykłady innych elementów…
Z domyślną rezerwą…
Testowane z
Python 3.6.0 (v3.6.0:41df79263a11, Dec 22 2016, 17:23:13)
źródło
value, = liste[:1] or ('default',)
. Wygląda na to, że potrzebujesz nawiasów.Najlepszą rzeczą, jaką możesz zrobić, to przekształcić listę w dykt, a następnie uzyskać do niej dostęp za pomocą metody get:
źródło
zip range len
można po prostu użyćdict(enumerate(my_list))
Zrobiłem więc więcej badań na ten temat i okazało się, że nie ma w tym nic konkretnego. Byłem podekscytowany, gdy znalazłem list.index (wartość), zwraca indeks określonego elementu, ale nie ma nic do uzyskania wartości przy określonym indeksie. Więc jeśli nie chcesz używać rozwiązania safe_list_get, które moim zdaniem jest całkiem dobre. Oto 1 linijka, jeśli instrukcje, które mogą wykonać zadanie dla Ciebie w zależności od scenariusza:
Możesz także użyć None zamiast „No”, co ma większy sens:
Również jeśli chcesz dostać pierwszy lub ostatni element na liście, to działa
Możesz również przekształcić je w funkcje, ale nadal podobało mi się rozwiązanie wyjątku IndexError. Eksperymentowałem z fałszywą wersją
safe_list_get
rozwiązania i uczyniłem go nieco prostszym (brak domyślnego):Nie przeprowadziłem testów porównawczych, aby zobaczyć, co jest najszybsze.
źródło
list
poprzez jego podklasowanie. W ten sposób konstruktor może pobraćlist
dowolną listę, która zachowuje się jak lista, a nowa instancja zachowuje się jaklist
. Zobacz odpowiedź Keitha poniżej, która powinna być zaakceptowana przez IMHO.dict.get()
zwracania wartości domyślnej z odwołania do indeksu listy zamiast konieczności przechwytywaniaIndexError
? Więc tak naprawdę chodzi o funkcję języka / biblioteki (a nie OOP kontra kontekst FP) Ponadto prawdopodobnie należy zakwalifikować użycie słowa „python” jako być może WWGD (ponieważ jego pogarda dla FP Python jest dobrze znana) i niekoniecznie po prostu satysfakcjonująca PEP8 / 20.el = x[4] if len(x) == 4 else 'No'
- masz na myślilen(x) > 4
?x[4]
jest poza zakresem jeślilen(x) == 4
.Słowniki służą do wyszukiwania. Warto zapytać, czy wpis istnieje, czy nie. Listy są zwykle iterowane. Często zdarza się pytanie, czy L [10] istnieje, ale czy długość L wynosi 11.
źródło
Twój przypadek użycia jest w zasadzie istotny tylko przy wykonywaniu tablic i matryc o stałej długości, abyś wiedział, jak długo mają one przed sobą. W takim przypadku zazwyczaj tworzysz je również przed ręcznym wypełnieniem ich None lub 0, aby w rzeczywistości każdy indeks, którego użyjesz, już istniał.
Można powiedzieć tak: dość często potrzebuję .get () w słownikach. Po dziesięciu latach pełnoetatowego programisty nie sądzę, żebym kiedykolwiek potrzebował go na liście. :)
źródło
'lalala' in url.split('/')[2:]
. Problem w tym rozwiązaniu polega na tym, że patrzysz tylko na drugi element. Co jeśli adres URL to „/ monkeybonkey / lalala”? Otrzymasz komunikat,True
mimo że adres URL jest nieprawidłowy.