2015-07-05 8 views

Odpowiedz

33

w Pythonie 3.x

range(0,3) zwraca klasę niezmiennych iterowalny obiektów, które umożliwia iteracyjne nad nimi, nie produkują listy, a oni nie przechowywać wszystkie elementy w zakresie pamięci, zamiast oni wytwarzają elementy w locie (tak jak je przeglądasz), podczas gdy list(range(0,3)) tworzy listę (przez powtarzanie wszystkich elementów i dołączanie do listy wewnętrznie).

Przykład -

>>> range(0,3) 
range(0, 3) 
>>> list(range(0,3)) 
[0, 1, 2] 

Idealnie, jeśli tylko chcesz iteracyjne nad tym przedziale wartości, range(0,3) byłoby szybciej niż (list(range(0,3)) ponieważ ten ostatni ma napowietrznej produkujących listę przed rozpoczęciem iteracji nad nim.

w Pythonie 2.x, range(0,3) tworzy listę, a nie my również mieliśmy xrange() funkcję, która ma podobne zachowanie range() funkcji z Pythona 3.x (XRange został przemianowany na klasy w Pythonie 3.x)

dla Pythona 3.5, z documentation -

obiektów klasy uruchomienie systemu collections.abc.Sequence ABC i oferują funkcje takie jak testy obudowy, odnośnika indeksu elementu, krojenie i wsparcia dla indeksów ujemnych

Więc można robić takie rzeczy -

>>> range(0,10)[5] 
5 
>>> range(0,10)[3:7] 
range(3, 7) 
>>> 5 in range(6,10) 
False 
>>> 7 in range(1,8) 
True 

a wszystkie te operacje są stałe w czasie, jak widać z tego testu -

In [11]: %timeit a = xrange(0,1000000)[1000] 
1000000 loops, best of 3: 342 ns per loop 

In [12]: %timeit a = xrange(0,1000000)[10000] 
1000000 loops, best of 3: 342 ns per loop 

In [13]: %timeit a = xrange(0,1000000)[100000] 
1000000 loops, best of 3: 342 ns per loop 

In [14]: %timeit a = xrange(0,1000000)[999999] 
1000000 loops, best of 3: 342 ns per loop 

In [15]: %timeit a = xrange(0,10000000)[9999999] 
1000000 loops, best of 3: 339 ns per loop 

In [16]: %timeit a = xrange(0,1000000000000)[9999999999] 
1000000 loops, best of 3: 341 ns per loop 
+0

Więc w Pythonie 3 jest "range (x, y)" coś zbliżonego do generatora? Właśnie coś zastanawiałem się odkąd pierwszy raz zobaczyłem to zachowanie ... – Kyrubas

+0

Na razie celowe, ponieważ tłumacz online, którego użyłem do uzyskania przykładu timeit to Python 2.7, więc użyłem xrange zamiast zakresu. Ale nie powinno to mieć znaczenia, ponieważ zasięg Pythona 3 to xrange Pythona 2.x() –

+0

Ok Pomyślałem, że to coś takiego. Chciałem tylko upewnić się, że jest to zamierzone. – Scott

12

To zależy od wersji Pythona, z której korzystasz.

W języku Python 2.x, range() zwraca listę, więc są one równoważne.

W języku Python 3.x, zwraca niezmienny typ sekwencji, aby uzyskać listę, trzeba uzyskać list(range(0,2)).

+4

Faktycznie 'zasięg' nie zwraca generatora, jest to obiekt niezmienny. Spróbuj wykonać 'next (zakres (0,5))'. Zrozumiesz. –

+0

@AnandSKumar Poprawione teraz. –

1

W python3.x, ma swój zakres typ

>>> range(1) 
range(0, 1) 
>>> type(range(1)) 
<class 'range'> 

Więc jeśli chcesz użyć zasięgu() w pętli for, to jest w porządku. Jednak nie można go użyć jako obiektu listy jako purely. Aby to zrobić, musisz przekonwertować go na listę.

python2 przykład:

>>> L = range(10) 
>>> L[::-1] 
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0] 

Python3 przykład:

>>> L = range(10) 
>>> L[::-1] 
range(9, -1, -1) 
+1

Możesz wycinać zakres - '>>> zakres (0,3) [1: 3] zakres (1, 3)' –

+0

Jak @AnandSKumar wskazuje w swojej odpowiedzi, python3 'range()' jest typem sekwencji i ma te same operacje co listy i krotki (z wyjątkiem konkatencji i powtórzeń) https://docs.python.org/3/library/stdtypes.html#sequence-types-list-tuple-range – Scott

+0

@Anand, masz rację krojenie, które na nim działa. Zaktualizowałem swoją odpowiedź na to, co miałem na myśli. Dzięki! –

2

Oba polecenia listy powrót w Python2.x. Ale w zakresie Python3.x jest niezmienna sekwencja i nie zwraca listy. Służy do iteracji pętli reklamowych

1

Zasadniczo różnica polega na tym, że range(0, 2) jest funkcją generatora, a list(range(0, 2)) jest faktyczną listą.

Funkcja generatora jest używana w pętlach. Na przykład funkcja generatora pliku odczytuje bardzo duży plik wiersz po linii.

def gen(): 
    for line in open("hugefile.csv", "r"): 
     yield line #Gives back the line every time it is read, but forgets that line after 

for line in gen(): 
    print(line) 

Spowoduje to wydrukowanie każdej linii bez przeciążania pamięci RAM komputera, ponieważ czyta się tylko jeden po drugim w obu funkcjach. Jeśli jednak zrobimy coś takiego, jak

def readEntireFile(): 
    return [line for line in open("hugefile.csv", "r")] #Python has lazy ways of making lists, this is the same as returning a list with all the lines in the file 

for line in readEntireFile(): 
    print(line) 

Druga część wygląda tak samo, ale tak nie jest. Początkowo pętliśmy wszystkie wiersze w pliku i przechodziliśmy do następnego wiersza, kiedy już to zrobiliśmy. Tutaj Python ma listę WSZYSTKICH linii: /, wyobraź sobie, że robisz to z plikiem 10GB! Twój kod się zawiesił.

Teraz wróćmy do zakresu() i lista (zakres())

Doing for x in range(0, 6): pozwala nam przejść do następnego numeru w zakresie i całkowicie zapomnieć o poprzednim (gramatyki śrubki).

jednak robi for x in list(range(0, 6)): utrzymuje całą listę numerów zapisanych w pamięci i jest taka sama jak robi

numlist = [x for x in range(6)] 
for x in numlist: 
    print(x) 

Kiedy trzeba całą listę danych w kodzie, należy użyć metody listy. Ale gdy potrzebujesz tylko jednego kawałka danych na raz (najprostszy przykład, kopiowanie pliku w porcjach), użyj funkcji generatora, aby zaoszczędzić miejsce. Możesz skopiować co 1 milion linii pliku, używając tylko 54 MB (zakładając, że nie masz szalenie długich linii). Jednakże, jeśli mamy mały plik 2kb, możemy po prostu skopiować to bez generatora. To nie jest warte czasu i jest wolniejsze w tym przypadku.

Powiązane problemy