Dlaczego lista nie ma bezpiecznej metody "get", takiej jak słownik?

Dlaczego list nie ma bezpiecznej metody "get", takiej jak dictionary?

>>> 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
Author: dreftymac, 2011-02-26

12 answers

Ostatecznie prawdopodobnie nie ma bezpiecznej metody .get, Ponieważ dict jest zbiorem asocjacyjnym (wartości są powiązane z nazwami), gdzie nieefektywne jest sprawdzanie, czy klucz jest obecny (i zwracanie jego wartości) bez rzucania wyjątku, podczas gdy bardzo trywialne jest unikanie WYJĄTKÓW dostępujących do elementów listy (ponieważ metoda len jest bardzo szybka). Metoda .get pozwala na odpytywanie wartości powiązanej z nazwą, a nie bezpośredni dostęp do 37 pozycji w słowniku (co byłoby bardziej jak to, o co prosisz swoją listę).

Oczywiście możesz to łatwo zaimplementować samodzielnie:

def safe_list_get (l, idx, default):
  try:
    return l[idx]
  except IndexError:
    return default

Można nawet podłączyć monkeypatch do konstruktora __builtins__.list w __main__, ale byłaby to mniej powszechna zmiana, ponieważ większość kodu jej nie używa. Jeśli chcesz użyć tego z listami utworzonymi przez twój własny kod, możesz po prostu podklasować list i dodać metodę get.

 127
Author: Nick Bastin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-26 07:53:34

To działa, jeśli chcesz pierwszy element, jak my_list.get(0)

>>> my_list = [1,2,3]
>>> next(iter(my_list), 'fail')
1
>>> my_list = []
>>> next(iter(my_list), 'fail')
'fail'
Wiem, że to nie jest dokładnie to, o co prosiłeś, ale może pomóc innym.
 77
Author: Jake,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-11 04:56:54

Prawdopodobnie dlatego, że nie miało to większego sensu dla semantyki listy. Możesz jednak łatwo utworzyć własne, podklasując.

class safelist(list):
    def get(self, index, default=None):
        try:
            return self.__getitem__(index)
        except IndexError:
            return default

def _test():
    l = safelist(range(10))
    print l.get(20, "oops")

if __name__ == "__main__":
    _test()
 53
Author: Keith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-11 23:41:12

Zamiast używać .get, używanie takich list powinno być ok. Tylko różnica w użytkowaniu.

>>> l = [1]
>>> l[10] if 10 < len(l) else 'fail'
'fail'
 44
Author: YOU,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-20 11:31:44

Spróbuj tego:

>>> i = 3
>>> a = [1, 2, 3, 4]
>>> next(iter(a[i:]), 'fail')
4
>>> next(iter(a[i + 1:]), 'fail')
'fail'
 19
Author: Vsevolod Kulaga,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-10 17:50:10

Napisy do jose.Anioł.jimenez i Gus Bus .


Dla fanów "oneliner" ...


Jeśli chcesz pierwszy element listy lub jeśli chcesz wartość domyślną, jeśli lista jest pusta spróbuj:

liste = ['a', 'b', 'c']
value = (liste[0:1] or ('default',))[0]
print(value)

Zwraca a

I

liste = []
value = (liste[0:1] or ('default',))[0]
print(value)

Zwraca default


Przykłady innych elementów ...

liste = ['a', 'b', 'c']
print(liste[0:1])  # returns ['a']
print(liste[1:2])  # returns ['b']
print(liste[2:3])  # returns ['c']
print(liste[3:4])  # returns []

Z domyślnym fallback ...

liste = ['a', 'b', 'c']
print((liste[0:1] or ('default',))[0])  # returns a
print((liste[1:2] or ('default',))[0])  # returns b
print((liste[2:3] or ('default',))[0])  # returns c
print((liste[3:4] or ('default',))[0])  # returns default

Ewentualnie krótszy:

liste = ['a', 'b', 'c']
value, = liste[:1] or ('default',)
print(value)  # returns a

Wygląda na to, że potrzebujesz przecinka przed znak równości, znak równości i drugi nawias.


Bardziej ogólne:

liste = ['a', 'b', 'c']
f = lambda l, x, d: l[x:x+1] and l[x] or d
print(f(liste, 0, 'default'))  # returns a
print(f(liste, 1, 'default'))  # returns b
print(f(liste, 2, 'default'))  # returns c
print(f(liste, 3, 'default'))  # returns default

Sprawdzone z Python 3.6.0 (v3.6.0:41df79263a11, Dec 22 2016, 17:23:13)

 17
Author: qräbnö,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-10-04 16:02:25

Najlepszą rzeczą, jaką możesz zrobić, to przekonwertować listę na dict, a następnie uzyskać do niej dostęp za pomocą metody get:

>>> my_list = ['a', 'b', 'c', 'd', 'e']
>>> my_dict = dict(enumerate(my_list))
>>> print my_dict
{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e'}
>>> my_dict.get(2)
'c'
>>> my_dict.get(10, 'N/A')
 15
Author: fab,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-25 07:22:42

Więc zrobiłem trochę więcej badań nad tym i okazało się, że nie ma nic konkretnego do tego. Podnieciłem się, gdy znalazłem list.index (wartość), zwraca indeks określonego elementu, ale nie ma nic do uzyskania wartości w 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 kilka instrukcji 1 liner if, które mogą wykonać zadanie za Ciebie w zależności od scenariusza:

>>> x = [1, 2, 3]
>>> el = x[4] if len(x) > 4 else 'No'
>>> el
'No'

Możesz również użyć None zamiast 'Nie', co ma więcej sensu.:

>>> x = [1, 2, 3]
>>> i = 2
>>> el_i = x[i] if len(x) == i+1 else None

Również jeśli chcesz uzyskać pierwszy lub ostatni element na liście, działa to

end_el = x[-1] if x else None

Możesz również przekształcić je w funkcje, ale nadal podobało mi się rozwiązanie wyjątku IndexError. Poeksperymentowałem z pomniejszoną wersją rozwiązania safe_list_get i uczyniłem to nieco prostszym (bez domyślnej):

def list_get(l, i):
    try:
        return l[i]
    except IndexError:
        return None
Nie widziałem, co jest najszybsze.
 8
Author: radtek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-16 18:30:56

Słowniki służą do wyszukiwania. Warto zapytać, czy wpis istnieje, czy nie. Listy są zwykle iteracyjne. Nie jest powszechne pytanie, Czy L[10] istnieje, ale raczej, czy Długość L wynosi 11.

 4
Author: Apprentice Queue,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-26 07:34:15

Ten facet pracował dla mnie:

list_get = lambda l, x: l[x:x+1] and l[x] or 0

Lambdy są świetne dla jednej funkcji pomocniczej typu liner

 1
Author: Gus Bus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-29 03:18:18

Dla małych wartości indeksu można zaimplementować

my_list.get(index, default)

Jako

(my_list + [default] * (index + 1))[index]

Jeśli wiesz z góry, co to jest indeks, to można to uprościć, na przykład, jeśli wiedziałeś, że jest 1, to możesz zrobić

(my_list + [default, default])[index]

Ponieważ listy są zapakowane do przodu jedynym przypadkiem, o który musimy się martwić, jest ucieczka z końca listy. Takie podejście blokuje koniec listy z wystarczającą liczbą domyślnych wartości, aby zagwarantować, że indeks jest objęty.

 0
Author: Gordon Wrigley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-09-04 09:37:14

Twój usecase jest w zasadzie istotny tylko przy robieniu tablic i macierzy o stałej długości, tak, że wiesz, jak długo są one przed ręką. W takim przypadku zazwyczaj tworzysz je przed ręcznym wypełnieniem ich None lub 0, tak że w rzeczywistości dowolny indeks, którego użyjesz, już istnieje.

Można powiedzieć Tak: potrzebuję .get() na słownikach dość często. Po dziesięciu latach jako programista w pełnym wymiarze czasu nie sądzę, że kiedykolwiek potrzebowałem go na liście. :)

 -1
Author: Lennart Regebro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-26 08:30:33