Chcę stworzyć serię list o różnej długości. Każda lista będzie zawierać ten sam element e
, powtarzane n
razy (gdzie n
= długość listy).
Jak utworzyć listy bez korzystania ze zrozumienia listy [e for number in xrange(n)]
dla każdej listy?
Chcę stworzyć serię list o różnej długości. Każda lista będzie zawierać ten sam element e
, powtarzane n
razy (gdzie n
= długość listy).
Jak utworzyć listy bez korzystania ze zrozumienia listy [e for number in xrange(n)]
dla każdej listy?
Odpowiedzi:
Możesz także napisać:
[e] * n
Należy zauważyć, że jeśli e jest na przykład pustą listą, otrzymujesz listę z n odniesieniami do tej samej listy, a nie n niezależnymi pustymi listami.
Test wydajności
Na pierwszy rzut oka wydaje się, że powtórzenie jest najszybszym sposobem na utworzenie listy zawierającej n identycznych elementów:
>>> timeit.timeit('itertools.repeat(0, 10)', 'import itertools', number = 1000000)
0.37095273281943264
>>> timeit.timeit('[0] * 10', 'import itertools', number = 1000000)
0.5577236771712819
Ale czekaj - to nie jest uczciwy test ...
>>> itertools.repeat(0, 10)
repeat(0, 10) # Not a list!!!
Ta funkcja itertools.repeat
nie tworzy listy, po prostu tworzy obiekt, którego można użyć do utworzenia listy, jeśli chcesz! Spróbujmy jeszcze raz, ale przechodząc do listy:
>>> timeit.timeit('list(itertools.repeat(0, 10))', 'import itertools', number = 1000000)
1.7508119747063233
Więc jeśli chcesz listę, użyj [e] * n
. Jeśli chcesz generować elementy leniwie, użyj repeat
.
[[]] * n
może ona dać nieoczekiwane wyniki. Aby utworzyć unikalne puste listy podrzędne , skorzystaj ze zrozumienia:[[] for i in range(0,n)]
Utwórz listę powtarzanych pojedynczych elementów n razy w Pythonie
W przypadku niezmiennych przedmiotów, takich jak None, bools, ints, floats, strings, tuples lub frozensets, możesz to zrobić w następujący sposób:
[e] * 4
Zauważ, że najlepiej tego używać tylko z niezmiennymi elementami (ciągami, krotkami, frozensetami) na liście, ponieważ wszystkie wskazują na ten sam element w tym samym miejscu w pamięci. Używam tego często, gdy muszę zbudować tabelę ze schematem wszystkich łańcuchów, aby nie musiałem nadawać bardzo redundantnego mapowania jeden do jednego.
schema = ['string'] * len(columns)
Używam Pythona od dłuższego czasu i nigdy nie widziałem przypadku użycia, w którym zrobiłbym powyższe z modyfikowalną instancją. Zamiast tego, aby uzyskać, powiedzmy, zmienną pustą listę, ustawić lub dyktować, powinieneś zrobić coś takiego:
list_of_lists = [[] for _ in columns]
Podkreślenie to po prostu zmienna nazwa zmiennej w tym kontekście.
Jeśli masz tylko numer, byłoby to:
list_of_lists = [[] for _ in range(4)]
Nie _
jest to tak naprawdę wyjątkowe, ale sprawdzanie stylu środowiska kodowania prawdopodobnie narzeka, jeśli nie zamierzasz używać zmiennej i używać żadnej innej nazwy.
Strzeż się robienia tego ze zmiennymi obiektami , kiedy zmienisz jeden z nich, wszystkie się zmieniają, ponieważ wszystkie są tym samym obiektem:
foo = [[]] * 4
foo[0].append('x')
foo teraz zwraca:
[['x'], ['x'], ['x'], ['x']]
Ale w przypadku obiektów niezmiennych możesz sprawić, że będzie działać, ponieważ zmienisz odwołanie, a nie obiekt:
>>> l = [0] * 4
>>> l[0] += 1
>>> l
[1, 0, 0, 0]
>>> l = [frozenset()] * 4
>>> l[0] |= set('abc')
>>> l
[frozenset(['a', 'c', 'b']), frozenset([]), frozenset([]), frozenset([])]
Ale znowu, zmienne obiekty nie nadają się do tego, ponieważ operacje w miejscu zmieniają obiekt, a nie odwołanie:
l = [set()] * 4
>>> l[0] |= set('abc')
>>> l
[set(['a', 'c', 'b']), set(['a', 'c', 'b']), set(['a', 'c', 'b']), set(['a', 'c', 'b'])]
Itertools ma właśnie taką funkcję:
import itertools
it = itertools.repeat(e,n)
Oczywiście itertools
daje iterator zamiast listy. [e] * n
daje listę, ale w zależności od tego, co zrobisz z tymi sekwencjami, itertools
wariant może być znacznie wydajniejszy.
Jak zauważyli inni, użycie operatora * dla obiektu zmiennego powiela odniesienia, więc jeśli zmienisz jeden, zmień je wszystkie. Jeśli chcesz utworzyć niezależne instancje obiektu zmiennego, twoja składnia xrange jest najbardziej Pythońskim sposobem na zrobienie tego. Jeśli przeszkadza ci, że zmienna nazwana, która nigdy nie jest używana, możesz użyć anonimowej zmiennej podkreślenia.
[e for _ in xrange(n)]
[e] * n
powinno działać