:: (dấu hai chấm) trong Python là gì khi đăng ký trình tự?


264

Tôi biết rằng tôi có thể sử dụng một cái gì đó như string[3:4]để có được một chuỗi con trong Python, nhưng 3 có nghĩa là somesequence[::3]gì?


điều đó có nghĩa là ai đến trước :: thích [5::]. Vậy 5 nghĩa là gì?
Umar Asghar

1
[5 ::] có nghĩa là bắt đầu với phần tử đầu tiên, không có gì cho phần tử thứ hai và chọn phần tử tiếp theo
Gagan

Câu trả lời:


243

nó có nghĩa là 'không có gì cho đối số thứ nhất, không có gì cho lần thứ hai và nhảy qua ba'. Nó được mọi thứ ba của chuỗi được cắt lát. Lát mở rộng là những gì bạn muốn. Mới trong Python 2.3


99
Nó cũng có thể được sử dụng để đảo ngược danh sách bằng cách sử dụng [:: - 1]
thavan

22
Nó trả về mọi mục trên một vị trí là bội số của 3 . Vì 3 * 0 = 0, nó cũng trả về mục ở vị trí 0. Ví dụ: range(10)[::3]đầu ra[0, 3, 6, 9]
Ricky Robinson

1
điều đó có nghĩa là ai đến trước ::như [n ::]. Vậy nó có nghĩa là ngì?
Umar Asghar

154

Địa chỉ lát trình tự Python có thể được viết dưới dạng [start: end: step] và bất kỳ bắt đầu, dừng hoặc kết thúc nào cũng có thể được loại bỏ. a[::3]là mọi yếu tố thứ ba của chuỗi.


85

seq[::n]là một chuỗi của mỗi nmục thứ trong toàn bộ chuỗi.

Thí dụ:

>>> range(10)[::2]
[0, 2, 4, 6, 8]

Cú pháp là:

seq[start:end:step]

Vì vậy, bạn có thể làm:

>>> range(100)[5:18:2]
[5, 7, 9, 11, 13, 15, 17]

4
Trong Python 3, phạm vi ví dụ của bạn (N) [:: step] tạo ra một đối tượng phạm vi, không phải danh sách. Để thực sự thấy những gì đang xảy ra, bạn cần phải đưa phạm vi vào một danh sách, np.array, v.v.
GulalaxALT

57

Giải trình

s[i:j:k]là, theo tài liệu , "lát s từ i đến j với bước k". Khi ijvắng mặt, toàn bộ chuỗi được giả định và do đó s[::k]có nghĩa là "mọi mục thứ k".

Ví dụ

Đầu tiên, hãy khởi tạo một danh sách:

>>> s = range(20)
>>> s
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

Hãy lấy mọi thứ thứ 3 từ s:

>>> s[::3]
[0, 3, 6, 9, 12, 15, 18]

Hãy lấy mọi thứ thứ 3 từ s[2:]:

>>> s[2:]
[2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> s[2::3]
[2, 5, 8, 11, 14, 17]

Hãy lấy mọi thứ thứ 3 từ s[5:12]:

>>> s[5:12]
[5, 6, 7, 8, 9, 10, 11]
>>> s[5:12:3]
[5, 8, 11]

Hãy lấy mọi thứ thứ 3 từ s[:10]:

>>> s[:10]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> s[:10:3]
[0, 3, 6, 9]

câu trả lời tuyệt vời!
Jürgen K.

30

TL; DR

Ví dụ trực quan này sẽ chỉ cho bạn cách chọn các phần tử gọn gàng trong Ma trận NumPy (mảng 2 chiều) theo cách khá thú vị (tôi hứa). Bước 2 dưới đây minh họa việc sử dụng "dấu hai chấm" đó ::trong câu hỏi.

(Chú ý: đây là ví dụ cụ thể về mảng NumPy với mục đích minh họa trường hợp sử dụng "dấu hai chấm" ::để nhảy các phần tử trong nhiều trục. Ví dụ này không bao gồm các cấu trúc dữ liệu Python nguyên gốc như List).

Một ví dụ cụ thể để cai trị tất cả ...

Giả sử chúng ta có một ma trận NumPy trông như thế này:

In [1]: import numpy as np

In [2]: X = np.arange(100).reshape(10,10)

In [3]: X
Out[3]:
array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
       [20, 21, 22, 23, 24, 25, 26, 27, 28, 29],
       [30, 31, 32, 33, 34, 35, 36, 37, 38, 39],
       [40, 41, 42, 43, 44, 45, 46, 47, 48, 49],
       [50, 51, 52, 53, 54, 55, 56, 57, 58, 59],
       [60, 61, 62, 63, 64, 65, 66, 67, 68, 69],
       [70, 71, 72, 73, 74, 75, 76, 77, 78, 79],
       [80, 81, 82, 83, 84, 85, 86, 87, 88, 89],
       [90, 91, 92, 93, 94, 95, 96, 97, 98, 99]])

Nói vì một số lý do, sếp của bạn muốn bạn chọn các yếu tố sau:

nhập mô tả hình ảnh ở đây

"Nhưng làm thế nào ???" ... Đọc tiếp! (Chúng ta có thể làm điều này theo cách tiếp cận 2 bước)

Bước 1 - Lấy tập hợp con

Chỉ định "chỉ mục bắt đầu" và "chỉ mục kết thúc" theo cả hai hướng theo hàng và theo cột.

nhập mô tả hình ảnh ở đây

Trong mã:

In [5]: X2 = X[2:9,3:8]

In [6]: X2
Out[6]:
array([[23, 24, 25, 26, 27],
       [33, 34, 35, 36, 37],
       [43, 44, 45, 46, 47],
       [53, 54, 55, 56, 57],
       [63, 64, 65, 66, 67],
       [73, 74, 75, 76, 77],
       [83, 84, 85, 86, 87]])

Bây giờ hãy lưu ý rằng chúng ta vừa thu được tập hợp con của mình, với việc sử dụng kỹ thuật lập chỉ mục bắt đầu và kết thúc đơn giản. Tiếp theo, làm thế nào để thực hiện "nhảy" đó ... (đọc tiếp!)

Bước 2 - Chọn các yếu tố (với đối số "bước nhảy")

Bây giờ chúng ta có thể chỉ định "các bước nhảy" theo cả hai hướng theo hàng và theo cột (để chọn các phần tử theo cách "nhảy") như sau:

nhập mô tả hình ảnh ở đây

Trong mã (lưu ý dấu hai chấm):

In [7]: X3 = X2[::3, ::2]

In [8]: X3
Out[8]:
array([[23, 25, 27],
       [53, 55, 57],
       [83, 85, 87]])

Chúng tôi vừa chọn tất cả các yếu tố theo yêu cầu! :)

 Hợp nhất Bước 1 (bắt đầu và kết thúc) và Bước 2 ("nhảy")

Bây giờ chúng ta đã biết khái niệm này, chúng ta có thể dễ dàng kết hợp bước 1 và bước 2 thành một bước hợp nhất - cho sự gọn nhẹ:

In [9]: X4 = X[2:9,3:8][::3,::2]

    In [10]: X4
    Out[10]:
    array([[23, 25, 27],
           [53, 55, 57],
           [83, 85, 87]])

Làm xong!


Điều gì xảy ra nếu tôi muốn đặt từng mục được đánh dấu thành 0 trong đối tượng ban đầu? Làm thế nào để tiến hành?
dùng1211030

1
Làm một X[2:9,3:8][::3,::2] = 0 (để thay thế các mục được đánh dấu thành 0). Nếu bạn nhập Xlại, bạn sẽ thấy tất cả các mục được đánh dấu hiện được đặt thành 0.
Atlas7

15

Khi cắt trong Python tham số thứ ba là bước. Như những người khác đã đề cập, hãy xem Extended Slices để có cái nhìn tổng quan đẹp.

Với kiến ​​thức này, [::3]chỉ có nghĩa là bạn chưa chỉ định bất kỳ chỉ số bắt đầu hoặc kết thúc nào cho lát cắt của mình. Vì bạn đã chỉ định một bước, 3nên điều này sẽ mất mỗi lần nhập thứ ba somethingbắt đầu ở chỉ mục đầu tiên. Ví dụ:

>>> '123123123'[::3]
'111'

7

Bạn cũng có thể sử dụng ký hiệu này trong các lớp tùy chỉnh của riêng bạn để làm cho nó làm bất cứ điều gì bạn muốn

class C(object):
    def __getitem__(self, k):
        return k

# Single argument is passed directly.
assert C()[0] == 0

# Multiple indices generate a tuple.
assert C()[0, 1] == (0, 1)

# Slice notation generates a slice object.
assert C()[1:2:3] == slice(1, 2, 3)

# If you omit any part of the slice notation, it becomes None.
assert C()[:] == slice(None, None, None)
assert C()[::] == slice(None, None, None)
assert C()[1::] == slice(1, None, None)
assert C()[:2:] == slice(None, 2, None)
assert C()[::3] == slice(None, None, 3)

# Tuple with a slice object:
assert C()[:, 1] == (slice(None, None, None), 1)

# Ellipsis class object.
assert C()[...] == Ellipsis

Sau đó chúng ta có thể mở các đối tượng lát như:

s = slice(1, 2, 3)
assert s.start == 1
assert s.stop == 2
assert s.step == 3

Điều này đáng chú ý được sử dụng trong Numpy để cắt các mảng đa chiều theo bất kỳ hướng nào.

Tất nhiên, bất kỳ API lành mạnh nào cũng nên sử dụng ::3với ngữ nghĩa "cứ 3" thông thường.

Các liên quan Ellipsisđược đề cập sâu hơn tại: Đối tượng Ellipsis làm gì?


6

Tham số thứ ba là bước. Vì vậy, [:: 3] sẽ trả về mọi phần tử thứ 3 của danh sách / chuỗi.


4

Python sử dụng :: để phân tách giá trị Kết thúc, Bắt đầu và Bước.


1
Điều này không cung cấp đủ chi tiết để thực sự hữu ích.
bstpierre

4
Ý bạn không phải là "Bắt đầu, Kết thúc và Bước"? Có vẻ sai lệch để liệt kê chúng ra khỏi trật tự.
Jon Coombs
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.