Tại sao cắt chuỗi con với chỉ mục ngoài phạm vi hoạt động?


88

Tại sao không 'example'[999:9999]dẫn đến lỗi? Kể từ 'example'[9]đó, động lực đằng sau nó là gì?

Từ hành vi này, tôi có thể giả định rằng 'example'[3], về cơ bản / bên trong, không giống như 'example'[3:4], mặc dù cả hai đều dẫn đến cùng một 'm'chuỗi.


17
[999:9999]không phải là một chỉ mục, nó là một lát cắt và có các ngữ nghĩa khác nhau. Từ phần giới thiệu python: "Các chỉ số lát cắt tạo được xử lý một cách duyên dáng: chỉ mục quá lớn được thay thế bằng kích thước chuỗi, giới hạn trên nhỏ hơn giới hạn dưới trả về một chuỗi trống."
Wooble

2
@ Wooble đó là câu trả lời thực tế
jondavidjohn

2
@Wooble Và bạn có biết tại sao nó lại như vậy không? Cảm ơn sự trình bày rõ ràng của bạn.
ijverig

Tại sao? Bạn phải hỏi Guido, nhưng tôi nghĩ thật tuyệt khi có thể cho rằng một lát cắt luôn là loại trình tự giống với trình tự gốc, bản thân tôi.
Wooble

1
@Lapinot yes Tôi đã viết mã phụ thuộc vào hành vi này. Rất tiếc, tôi không thể nhớ mã chính xác nên không thể cho bạn biết tại sao. Có lẽ phải làm với chuỗi con; nhận được một chuỗi trống có thể là chính xác những gì bạn muốn đôi khi.
Mark Ransom vào

Câu trả lời:


68

Bạn hoàn toàn đúng! 'example'[3:4]'example'[3]khác nhau về cơ bản, và việc cắt ra bên ngoài giới hạn của một chuỗi (ít nhất là đối với các bản cài sẵn) không gây ra lỗi.

Thoạt nghe có thể ngạc nhiên nhưng khi nghĩ lại sẽ thấy rất hợp lý. Việc lập chỉ mục trả về một mục duy nhất, nhưng việc cắt sẽ trả về một dãy con của các mục. Vì vậy, khi bạn cố gắng lập chỉ mục một giá trị không tồn tại, sẽ không có gì để trả về. Nhưng khi bạn cắt một chuỗi ngoài giới hạn, bạn vẫn có thể trả về một chuỗi trống.

Một phần của điều khó hiểu ở đây là chuỗi hoạt động hơi khác so với danh sách. Hãy xem điều gì sẽ xảy ra khi bạn làm điều tương tự với một danh sách:

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

Ở đây sự khác biệt là rõ ràng. Trong trường hợp chuỗi, kết quả có vẻ giống nhau vì trong Python, không có ký tự riêng lẻ nào nằm ngoài chuỗi. Một ký tự chỉ là một chuỗi 1 ký tự.

(Để biết ngữ nghĩa chính xác của việc cắt bên ngoài phạm vi của một chuỗi, hãy xem câu trả lời của mgilson .)


1
Chỉ mục nằm ngoài phạm vi có thể đã trả về Nonethay vì lỗi - đó là quy ước thông thường của Python khi bạn không có gì để trả lại.
Mark Ransom

8
@MarkRansom, đó là sự thật; nhưng việc quay lại Nonetrong trường hợp này sẽ khiến việc phân biệt giữa chỉ mục nằm ngoài giới hạn và Nonegiá trị bên trong danh sách trở nên khó khăn hơn . Nhưng ngay cả khi có một giải pháp cho điều đó, tôi vẫn thấy rõ rằng trả về một chuỗi trống là điều đúng đắn cần làm khi đưa ra một lát cắt nằm ngoài giới hạn. Nó tương tự như biểu diễn sự kết hợp của hai tập hợp rời rạc.
gửi

Chỉ cần nói rõ, tôi không nói rằng bạn đã sai. Tôi thấy quan điểm của bạn về Nonecác giá trị trong một danh sách.
Mark Ransom

1
@MarkRansom, tôi biết - xin lỗi nếu tôi có vẻ phòng thủ. Thực sự tôi chỉ muốn có một cái cớ để tham khảo lý thuyết tập hợp :).
gửi

4
Ồ, ngoại trừ tôi đã nói "union" thay vì "giao nhau".
gửi

31

Để có thêm câu trả lời trỏ đến phần mạnh mẽ trong tài liệu :

Đưa ra một biểu thức lát cắt như s[i:j:k],

Lát s từ i đến j với bước k được định nghĩa là chuỗi các mục có chỉ mục x = i + n*ksao cho 0 <= n < (j-i)/k. Nói cách khác, các chỉ số là i, i+k, i+2*k, i+3*kvà như vậy, dừng lại khi k đạt được (nhưng không bao giờ bao gồm j ). Khi k dương, ij giảm xuống len(s)nếu chúng lớn hơn

nếu bạn viết s[999:9999], trăn đang trở lại s[len(s):len(s)]kể từ len(s) < 999và bước của bạn là dương tính ( 1- mặc định).


Có lẽ khi nào klà tích cực ijcũng tăng lên -len(s)khi chúng thấp hơn? ví dụs = 'bac'; s[-100:2] == s[-len(s):2]
Chris_Rands

@Chris_Rands Khi klà tích cực, Python sẽ mở rộng quy mô ijsao cho chúng phù hợp với giới hạn của chuỗi. Trong ví dụ của bạn, s[-100:2] == s[0:2]( == s[-len(s):2], nhân tiện). Tương tự s[-100:100] == s[0:2],.
tylerc0816

Tốt, cảm ơn. Đây là phản hồi tốt hơn cho nhận xét của @ speedplane ở trên.
gửi 14/1218

8

Việc cắt lát không được kiểm tra bởi các loại tích hợp. Và mặc dù cả hai ví dụ của bạn đều có cùng kết quả, nhưng chúng hoạt động khác nhau; thay vào đó hãy thử chúng với một danh sách.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.