Python 3 zmienia zakres w listę

178

Próbuję zrobić listę z liczbami 1-1000. Oczywiście pisanie / czytanie byłoby denerwujące, więc próbuję utworzyć listę z zakresem. W Pythonie 2 wygląda na to, że:

some_list = range(1,1000)

zadziałałoby, ale w Pythonie 3 zakres jest podobny do zakresu xrangew Pythonie 2?

Czy ktoś może dać wgląd w to?

Boathouse
źródło
1
także, some_list[i] == i+1więc prawdopodobnie i tak nie potrzebujesz listy.
njzk2
1
@RikPoggi. na przykład może być konieczne podanie listy funkcji kreślącej. Czasami zakres będzie wystarczający, ale zakresu nie można łączyć (jest niezmienny), więc jeśli chcesz dodać domyślną wartość początkową do wszystkich drukowanych list, należy ją również przekształcić w listę.
SherylHohman

Odpowiedzi:

223

Możesz po prostu utworzyć listę z obiektu zakresu:

my_list = list(range(1, 1001))

W ten sposób robisz to również z generatorami w python2.x. Zwykle jednak lista prawdopodobnie nie jest potrzebna, ponieważ można przyjąć wartość my_list[i]bardziej efektywnie ( i + 1), a jeśli potrzebujesz tylko iterować, możesz po prostu wrócić do niej range.

Należy również zauważyć, że w python2.x xrangejest nadal indeksowalny 1 . Oznacza to, że rangena python3.x również ma tę samą właściwość 2

1print xrange(30)[12] działa dla python2.x

2 Analogiczna instrukcja do 1 w python3.x to print(range(30)[12])i to też działa.

mgilson
źródło
4
To jest zdecydowanie droga, ale czubek: to nie jest tak naprawdę „obsada”
jterrace
@jterrace zmieniło „cast” na „convert”. Masz rację, że to nie jest obsada ... Naprawdę nie wiem, jak to dokładnie nazwać.
mgilson
2
Powiedziałbym „skonstruuj” lub „zbuduj” (lub prawdopodobnie „zmaterializuj”) - ponieważ nie „konwertujesz” (jako takiego) generatora na listę, tworzysz nowy obiekt listy ze źródła danych, co się dzieje być generatorem ... (ale załóżmy, że po prostu dzielę włosy i nie jestem w 100% pewien, co lubię)
Jon Clements
2
Moje +1 dla „konstrukcji”, ponieważ jest zgodne z innymi językami obiektowymi. W list(arg)innych językach jest rozumiane jako wywołanie konstruktora listklasy. W rzeczywistości jest to również przypadek Pythona. Debata, czy obiekt jest wypełniany w trakcie konstrukcji (jak w przypadku C ++), czy tylko podczas pierwszej automatycznie wywoływanej metody (jak w __init__()metodzie Pythona ) nie może zmienić podstawowej abstrakcyjnej idei. Uważam, że konstruktor listy przyjmuje iterator i wypełnia listę zwracanymi wartościami .
pepr
2
Dlaczego daje błąd w notebooku jupyter i działa dobrze w powłoce? Błąd:'range' object is not callable
subtleseeker
34

W Pythonie <= 3.4 możesz, jak sugerowali inni, użyć list(range(10))do utworzenia listy spoza zakresu (ogólnie rzecz biorąc, dowolna iterowalna).

Inną alternatywą, wprowadzoną w Pythonie 3.5z uogólnieniami dotyczącymi rozpakowywania, jest użycie *w liście literału []:

>>> r = range(10)
>>> l = [*r]
>>> print(l)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Chociaż jest to równoważne z list(r), jest to składnia dosłowna, a fakt, że nie jest zaangażowane żadne wywołanie funkcji, pozwala jej wykonywać szybciej. To także mniej znaków, jeśli chcesz zakodować golfa :-)

Dimitris Fasarakis Hilliard
źródło
4
Aby było jasne, nadal możesz to zrobić w jednym wierszu: [*range(10)]działa dobrze, gdy nie potrzebujesz rangedo żadnego celu, ale zainicjowanie list. Na marginesie: Moją ulubioną (dobrze, nie do końca) częścią rozpakowywania uogólnień jest to, że puste sets mają teraz dosłowną składnię {*()}, lub jak to nazywam, jednooki operator małpy. ;-)
ShadowRanger
@ShadowRanger tak właśnie myślałem o napisaniu tego. Postanowiłem być bardziej rozwlekły, aby nie zmylić nowych użytkowników Pythona :-)
Dimitris Fasarakis Hilliard
26

w Pythonie 3.x range()funkcja ma swój własny typ. więc w tym przypadku musisz użyć iteratora

list(range(1000))

nurulhudamustaqim
źródło
11
„w takim przypadku musisz użyć iteratora”? Co to do cholery ma znaczyć?
user2357112 obsługuje Monikę
2
Używam Pythona 3.7 i wypróbowałem x = list (zakres (1000)), ale pojawił się błąd TypeError: obiekt „list” nie jest wywoływany
Earthshaker
@Earthshaker Musisz mieć literówkę, na przykładlist(range(1000))()
wjandrea
17

Powodem, dla którego Python3 nie ma funkcji do bezpośredniego pobierania listy zakresowej, jest to, że oryginalny projektant Python3 był całkiem nowicjuszem w Pythonie2. Rozważał tylko użycie range()funkcji w pętli for, dlatego lista nie powinna nigdy wymagać rozszerzenia. W rzeczywistości bardzo często musimy użyć tej range()funkcji, aby utworzyć listę i przekazać ją do funkcji.

Dlatego w tym przypadku Python3 jest mniej wygodny w porównaniu do Python2, ponieważ:

  • W Pythonie2 mamy xrange()i range();
  • W Pythonie3 mamy range()ilist(range())

Niemniej jednak możesz nadal korzystać z rozwijania listy w ten sposób:

[*range(N)]
xuancong84
źródło
3
Cały punkt jest, aby to mniej wygodne zrobić list, bo to zwykle źle rzeczą do zrobienia. W 99 na 100 przypadków użycia tworzenie rzeczywistej wartości listjest nieefektywne i bezcelowe, ponieważ rangesamo w sobie zachowuje się jak niezmienna sekwencja prawie pod każdym względem, czasami bardziej efektywnie przy ładowaniu (np. Testy ograniczające dla ints są O(1), a nie O(n)dla lists). W Pythonie 2 ludzie zwykle używali rangedomyślnie, chociaż xrangeprawie zawsze była to lepsza opcja; w Pythonie 3 możesz jawnie wyrazić zgodę na to list, a nie dostać to przypadkowo, używając złej nazwy.
ShadowRanger
7
Komentarz dotyczący projektanta Pythona 3 i jego wiedzy na temat Pythona 2 jest dość odważny i bezczelny.
kazarey
@kazarey Ale czy to prawda? W Pythonie jest wiele rzeczy, które są wątpliwe
javadba
1
Głosowałbym za, szczególnie za unpacking-shorthand do skonstruowania listy, ale zgadzam się z @kazarey. Komentarz o projektantce jest zarówno bezpodstawny (a przynajmniej nie poparty odniesieniami), jak i niepotrzebny.
Nubarke
12

Naprawdę nie powinieneś używać liczb 1-1000 na liście. Ale jeśli z jakiegoś powodu naprawdę potrzebujesz tych liczb, możesz zrobić:

[i for i in range(1, 1001)]

Rozumienie listy w pigułce:

Powyższe rozumienie listy przekłada się na:

nums = []
for i in range(1, 1001):
    nums.append(i)

To jest tylko składnia listy, chociaż od 2.x. Wiem, że to zadziała w Pythonie 3, ale nie jestem pewien, czy istnieje również ulepszona składnia

Zakres zaczyna się łącznie z pierwszym parametrem; ale kończy się do, bez drugiego parametru (jeśli podano 2 parametry; jeśli pierwszy parametr zostanie pozostawiony, rozpocznie się od „0”)

range(start, end+1)
[start, start+1, .., end]
inspectorG4dget
źródło
20
Dlaczego rozumienie? Po prostu:list(range(1000))
Rik Poggi
Dzięki! Czy mógłbyś wyjaśnić, dlaczego jestem dla mnie ... zamiast po prostu dla mnie?
Boathouse
Nie pracowałem z pythonem3. Więc nie jestem do końca pewien, jak to działa. Wiem, że rozumienie zadziała, ale nie było 100% na castingu. Ale jeśli casting działa, masz rację, a twoja droga jest bardziej pytoniczna.
inspectorG4dget
1
@ inspectorG4dget: To nie jest „rzutowanie”, to wywołanie list()konstruktora z iterowalnym . list()Konstruktor wie, jak utworzyć nową listę, gdy podano żadnych iterable obiektu.
Greg Hewgill,
4
@ inspectorG4dget: list(range(1000))będzie działać w python3 tak jak list(xrange(1000))w python2
Rik Poggi
4

Właściwie, jeśli chcesz 1-1000 (włącznie), użyj range(...)funkcji z parametrami 1 i 1001:, range(1, 1001)ponieważ range(start, end)funkcja przechodzi od początku do (koniec-1) włącznie.

CosmicComputer
źródło
0

Użyj zakresu w Pythonie 3.

Oto przykładowa funkcja, która zwraca między liczbami z dwóch liczb

def get_between_numbers(a, b):
    """
    This function will return in between numbers from two numbers.
    :param a:
    :param b:
    :return:
    """
    x = []
    if b < a:
        x.extend(range(b, a))
        x.append(a)
    else:
        x.extend(range(a, b))
        x.append(b)

    return x

Wynik

print(get_between_numbers(5, 9))
print(get_between_numbers(9, 5))

[5, 6, 7, 8, 9]  
[5, 6, 7, 8, 9]
Rajiv Sharma
źródło
To wydaje się odpowiadać na inne pytanie ...?
wjandrea
-1

W rzeczywistości jest to retro-gradacja Pythona3 w porównaniu do Pythona2. Z pewnością Python2, który używa range () i xrange (), jest wygodniejszy niż Python3, który używa odpowiednio list (range ()) i range (). Powodem jest to, że pierwotny projektant Pythona3 nie jest zbyt doświadczony, rozważali tylko użycie funkcji zakresu przez wielu początkujących w celu iteracji dużej liczby elementów, w których zarówno pamięć, jak i procesor są nieefektywne; ale zaniedbali użycie funkcji zakresu do utworzenia listy liczb. Teraz jest już za późno, aby mogli się już zmienić.

Gdybym miał być projektantem Pythona3, to:

  1. użyj irange, aby zwrócić iterator sekwencji
  2. użyj lrange, aby zwrócić listę sekwencji
  3. użyj zakresu, aby zwrócić iterator sekwencji (jeśli liczba elementów jest duża, np. zakres (9999999) lub lista sekwencji (jeśli liczba elementów jest mała, np. zakres (10)))

To powinno być optymalne.

xuancong84
źródło
Jak to odpowiada na pytanie?
wjandrea
Tak, odpowiada na to pytanie, prosząc programistów Python3 o zmianę i ulepszenie Python3. Ale jest mało prawdopodobne, że się zmienią, ponieważ nie są tak eleganckie.
xuancong84