2012-02-28 8 views
41

Dlaczego 'example'[999:9999] nie powoduje błędu? Od 'example'[9], co jest za tym motywacja?Dlaczego indeks fragmentacji podcinania poza zasięgiem działa w języku Python?

Z tego zachowania mogę założyć, że 'example'[3] jest zasadniczo/wewnętrznie odmienne od 'example'[3:4], nawet jeśli oba mają ten sam ciąg znaków 'm'.

+9

'[999: 9999]' nie jest indeksem, jest krojem i ma inną semantykę. Od wstępu do Pythona: "Indeksy Degenerate slice są obsługiwane z wdziękiem: indeks, który jest zbyt duży, jest zastępowany przez rozmiar ciągu, górna granica mniejsza niż dolna granica zwraca pusty ciąg." – geoffspear

+0

@Woble, to jest aktualna odpowiedź – jondavidjohn

+1

@Wooble I czy wiesz, dlaczego tak jest? Dziękuję Ci za wyjaśnienie. – ijverig

Odpowiedz

5

Krojenie nie jest sprawdzane przez wbudowane typy. I chociaż oba przykłady wydają się mieć ten sam rezultat, działają one różnie; wypróbuj je z listą.

31

W zasadzie odpowiedziałeś na własne pytanie. Krojenie poza granicami sekwencji (przynajmniej dla wbudowanych) nie powoduje błędu. Ma to sens, gdy się nad tym zastanowić. Indeksowanie zwraca pojedynczy element, ale wycinanie zwraca podsekwencję elementów. Więc kiedy próbujesz zindeksować nieistniejącą wartość, nie ma nic do zwrócenia; ale gdy wycinasz sekwencję poza granicami, wciąż możesz zwrócić pustą sekwencję.

Należy również zauważyć, że to różnica między wartościami x[3] i x[3:4]. Na przykład:

>>> [0, 1, 2, 3, 4, 5][3] 
3 
>>> [0, 1, 2, 3, 4, 5][3:4] 
[3] 

Powodem wyglądają tak samo w przypadku strun jest to, że nie ma czegoś takiego jak indywidualny charakter poza ciągiem; pojedyncza postać jest po prostu ciągiem 1-znakowym.

+1

Indeks poza zakresem mógł zwrócić 'Brak' zamiast pomyłki - taka jest zwykła konwencja Pythona, kiedy nie masz nic do zwrócenia. –

+3

@MarkRansom, to prawda; ale zwracanie 'None' w tym przypadku utrudniłoby odróżnienie indeksu poza granicami od wartości' None' na liście. Ale nawet gdyby istniało obejście tego problemu, pozostaje dla mnie jasne, że powracanie pustej sekwencji jest właściwą rzeczą do zrobienia, gdy otrzymasz kawałek poza zasięgiem. Jest to analogiczne do połączenia dwóch rozłącznych zestawów. – senderle

+0

Dla jasności nie powiedziałem, że się mylisz. Widzę twój punkt o wartościach 'Brak' na liście. –

8

Dla dodawania odpowiedź wskazującą na solidnej sekcji w documentation:

Given wyrażenie plaster jak s[i:j:k],

The slice of s from i to j with step k is defined as the sequence of items with index x = i + n*k such that 0 <= n < (j-i)/k. In other words, the indices are i, i+k, i+2*k, i+3*k and so on, stopping when j is reached (but never including j). When k is positive, i and j are reduced to len(s) if they are greater

jeśli piszesz s[999:9999], pyton wraca s[len(s):len(s)] od len(s) < 999 a twój krok jest dodatni (1 - domyślny).

+0

Przypuszczalnie gdy 'k' jest dodatnie,' i' i 'j' są również zwiększane do' -len (s) ', gdy są mniejsze? na przykład 's = 'bac'; s [-100: 2] == s [-len (s): 2] ' –

+0

@Chris_Rands Kiedy' k' jest dodatnie, Python przeskaluje 'i' i' j', tak aby pasowały do ​​granic sekwencji. W twoim przykładzie 's [-100: 2] == s [0: 2]' ('== s [-len (s): 2]', nawiasem mówiąc). Podobnie, 's [-100: 100] == s [0: 2]'. – tylerc0816