Jak wszyscy wiemy, istnieje zrozumienie listy
[i for i in [1, 2, 3, 4]]
i istnieje zrozumienie słownika
{i:j for i, j in {1: 'a', 2: 'b'}.items()}
ale
(i for i in (1, 2, 3))
skończy w generatorze, a nie w tuple
zrozumieniu. Dlaczego?
Domyślam się, że a tuple
jest niezmienne, ale nie wydaje się, że to jest odpowiedź.
{i:j for i,j in {1:'a', 2:'b'}}
powinien być{i:j for i,j in {1:'a', 2:'b'}.items()}
Odpowiedzi:
Możesz użyć wyrażenia generatora:
ale nawiasy zostały już pobrane dla… wyrażeń generatora.
źródło
list(i for i in (1,2,3))
. Naprawdę myślę, że to po prostu dlatego, że nie ma dla niego czystej składni (lub przynajmniej nikt o tym nie pomyślał)list(i for i in (1, 2, 3))
jest wyrażeniem generatora, które wypisuje listę,set(i for i in (1, 2, 3))
wypisuje zestaw. Czy to oznacza, że składnia zrozumienia nie jest potrzebna? Może nie, ale jest to okropnie przydatne. W rzadkich przypadkach potrzebna jest krotka. Wyrażenie generatora wystarczy, jest jasne i nie wymaga wynalezienia innego nawiasu klamrowego lub nawiasu.[thing for thing in things]
konstruuje listę znacznie szybciej niżlist(thing for thing in things)
. Zrozumienie krotki nie byłoby bezużyteczne;tuple(thing for thing in things)
ma problemy z opóźnieniami ituple([thing for thing in things])
może mieć problemy z pamięcią.A list or set or dict comprehension is just syntactic sugar to use a generator expression
? Powoduje zamieszanie przez ludzi postrzegających je jako równoważne środki do celu. Nie jest to technicznie syntaktyczny cukier, ponieważ procesy są w rzeczywistości różne, nawet jeśli produkt końcowy jest taki sam.Raymond Hettinger (jeden z programistów rdzenia Pythona) powiedział o krotkach w ostatnim tweecie :
To (dla mnie) popiera ideę, że jeśli elementy w sekwencji są wystarczająco powiązane, aby mogły zostać wygenerowane przez, cóż, generator, to powinna to być lista. Chociaż krotka jest iterowalna i wydaje się po prostu niezmienną listą, jest tak naprawdę odpowiednikiem struktury C w Pythonie:
staje się w Pythonie
źródło
operator.itemgetter
w takim przypadku.tuple(obj[item] for item in items)
bezpośrednim użyciem . W moim przypadku umieściłem to w liście, aby utworzyć listę krotek. Jeśli muszę to powtarzać w całym kodzie, itemgetter wygląda świetnie. Być może tak czy inaczej itemgetter byłby bardziej idiomatyczny?Od wersji Python 3.5 możesz także użyć
*
składni rozpakowywania splat do rozpakowania wyrażenia generatora:źródło
tuple(list(x for x in range(10)))
( ścieżki kodu są identyczne , przy czym oba budują alist
, z tą jedyną różnicą, że ostatnim krokiem jest utworzenie wartoścituple
zlist
i wyrzucenie,list
kiedytuple
wyjście jest wymagane). Oznacza, że tak naprawdę nie unikasz tymczasowości.*(x for x in range(10))
nie działa. I dostaćSyntaxError: can't use starred expression here
. Jednaktuple(x for x in range(10))
działa.Jak
macm
wspomniano w innym plakacie , najszybszym sposobem na stworzenie krotki z generatora jesttuple([generator])
.Porównanie wydajności
Zrozumienie listy:
Próbuj ze zrozumienia listy:
Krotka z generatora:
Krotka z rozpakowywania:
Moja wersja Pythona :
Dlatego zawsze powinieneś utworzyć krotkę na podstawie listy, chyba że wydajność nie stanowi problemu.
źródło
tuple
z listcomp wymaga maksymalnego użycia pamięci w oparciu o łączny rozmiar pliku końcowegotuple
ilist
.tuple
genexpr, choć wolniejszy, oznacza, że płacisz tylko za końcowytuple
, a nie tymczasowylist
(sam genexpr zajmujący mniej więcej ustaloną pamięć). Zwykle nie ma to znaczenia, ale może być ważne, gdy rozmiary są ogromne.Zrozumienie polega na zapętlaniu lub iterowaniu elementów i przypisywaniu ich do kontenera, a Tuple nie może odbierać zadań.
Po utworzeniu krotki nie można jej dodawać, rozszerzać ani przypisywać. Jedynym sposobem zmodyfikowania krotki jest to, że jeden z jej obiektów może być przypisany (jest to kontener niebędący krotką). Ponieważ krotek zawiera tylko odniesienie do tego rodzaju obiektu.
Ponadto krotka ma własnego konstruktora,
tuple()
który można nadać dowolnemu iteratorowi. Co oznacza, że aby utworzyć krotkę, możesz:źródło
lst = [x for x in ...]; x.append()
?Domyślam się, że zabrakło im nawiasów i nie sądziłem, że przydałoby się dodać „brzydką” składnię…
źródło
{*()}
choć brzydki, działa jak pusty zestaw literału!set()
{*[]}
jest to zdecydowanie gorsze od innych opcji; pusty ciąg i pustytuple
, ponieważ są niezmienne, są singletonami, więc nie potrzeba tymczasowego skonstruowania pustegoset
. W przeciwieństwie do tego, pustelist
nie jest singletonem, więc musisz go zbudować, użyć go do zbudowaniaset
, a następnie zniszczyć, tracąc jakąkolwiek trywialną przewagę wydajności, jaką zapewnia jednooki operator małpy.Krotki nie mogą być skutecznie dołączane jak lista.
Tak więc zrozumienie krotki będzie wymagało użycia listy wewnętrznie, a następnie konwersji do krotki.
To byłoby to samo, co teraz robisz: krotka ([zrozumienie])
źródło
Nawiasy nie tworzą krotki. aka jeden = (dwa) nie jest krotką. Jedynym rozwiązaniem jest jeden = (dwa) lub jeden = krotka (dwa). Tak więc rozwiązaniem jest:
źródło
Uważam, że to po prostu ze względu na przejrzystość, nie chcemy zaśmiecać języka zbyt wieloma różnymi symbolami. Również
tuple
zrozumienie nigdy nie jest konieczne , zamiast tego można użyć listy z nieznacznymi różnicami prędkości, w przeciwieństwie do rozumienia dykta, w przeciwieństwie do rozumienia listy.źródło
Możemy wygenerować krotki na podstawie listy. Poniższy dodaje kolejno dwie liczby do krotki i podaje listę od cyfr 0-9.
źródło