ทำความเข้าใจสัญกรณ์ชิ้น


3282

ฉันต้องการคำอธิบายที่ดี (มีการอ้างอิงเป็นบวก) ในสัญกรณ์ชิ้นของ Python

สำหรับฉันแล้วสัญกรณ์นี้ต้องมีการหยิบขึ้นมาบ้าง

มันดูมีพลังมาก แต่ฉันก็ไม่ได้เอาหัวไปรอบ ๆ

คำตอบ:


4500

มันค่อนข้างง่ายจริงๆ:

a[start:stop]  # items start through stop-1
a[start:]      # items start through the rest of the array
a[:stop]       # items from the beginning through stop-1
a[:]           # a copy of the whole array

นอกจากนี้ยังมีstepค่าซึ่งสามารถใช้กับสิ่งใด ๆ ข้างต้น:

a[start:stop:step] # start through not past stop, by step

จุดสำคัญที่ต้องจำคือ:stopค่าหมายถึงค่าแรกที่ไม่ได้อยู่ในส่วนที่เลือก ดังนั้นความแตกต่างระหว่างstopและstartคือจำนวนขององค์ประกอบที่เลือก (ถ้าstepเป็น 1 คือค่าเริ่มต้น)

คุณลักษณะอื่น ๆ คือstartหรือstopอาจเป็นจำนวนลบซึ่งหมายความว่านับจากจุดสิ้นสุดของอาร์เรย์แทนการเริ่มต้น ดังนั้น:

a[-1]    # last item in the array
a[-2:]   # last two items in the array
a[:-2]   # everything except the last two items

ในทำนองเดียวกันstepอาจเป็นจำนวนลบ:

a[::-1]    # all items in the array, reversed
a[1::-1]   # the first two items, reversed
a[:-3:-1]  # the last two items, reversed
a[-3::-1]  # everything except the last two items, reversed

Python นั้นใจดีกับโปรแกรมเมอร์หากมีรายการน้อยกว่าที่คุณต้องการ ตัวอย่างเช่นถ้าคุณถามa[:-2]และaมีเพียงองค์ประกอบเดียวคุณจะได้รับรายการว่างเปล่าแทนที่จะเกิดข้อผิดพลาด บางครั้งคุณอาจต้องการข้อผิดพลาดดังนั้นคุณต้องระวังว่าสิ่งนี้อาจเกิดขึ้น

ความสัมพันธ์กับslice()วัตถุ

ตัวดำเนินการแบ่ง[]กำลังถูกใช้จริงในรหัสข้างต้นกับslice()วัตถุที่ใช้:สัญกรณ์ (ซึ่งใช้ได้ภายในเท่านั้น[]) คือ:

a[start:stop:step]

เทียบเท่ากับ:

a[slice(start, stop, step)]

วัตถุชิ้นยังทำงานแตกต่างกันเล็กน้อยขึ้นอยู่กับจำนวนของอาร์กิวเมนต์เช่นเดียวกับrange()ทั้งสองslice(stop)และslice(start, stop[, step])ได้รับการสนับสนุน หากต้องการข้ามระบุอาร์กิวเมนต์ให้หนึ่งอาจจะใช้Noneเพื่อให้เช่นa[start:]เทียบเท่ากับa[slice(start, None)]หรือเทียบเท่ากับa[::-1]a[slice(None, None, -1)]

ในขณะที่:สัญกรณ์ที่ใช้เป็นประโยชน์อย่างมากสำหรับการแบ่งส่วนอย่างง่ายการใช้slice()วัตถุอย่างชัดเจนทำให้การสร้างการแบ่งตามโปรแกรมแบบง่าย


122
การแบ่งประเภทบิวด์ในตัวจะส่งคืนสำเนา แต่นั่นไม่ใช่ความเป็นสากล โดยเฉพาะการแบ่ง NumPy Arrayส่งคืนมุมมองที่แชร์หน่วยความจำกับต้นฉบับ
Beni Cherniavsky-Paskin

43
นี่คือคำตอบที่สวยงามด้วยคะแนนโหวตเพื่อพิสูจน์ แต่มันพลาดสิ่งหนึ่ง: คุณสามารถทดแทนNoneช่องว่างใด ๆ ตัวอย่างเช่น[None:None]ทำสำเนาทั้งหมด สิ่งนี้มีประโยชน์เมื่อคุณต้องการระบุจุดสิ้นสุดของช่วงโดยใช้ตัวแปรและจำเป็นต้องรวมรายการสุดท้าย
Mark Ransom

6
สิ่งที่ทำให้ฉันรำคาญจริงๆคืองูใหญ่บอกว่าเมื่อคุณไม่ได้ตั้งจุดเริ่มต้นและจุดสิ้นสุดพวกมันจะเริ่มต้นที่ 0 และความยาวของลำดับ ในทางทฤษฎีแล้วเมื่อคุณใช้ "abcdef" [:: - 1] มันควรจะเปลี่ยนเป็น "abcdef" [0: 6: -1] แต่นิพจน์ทั้งสองนี้จะไม่ได้ผลลัพธ์เดียวกัน ฉันรู้สึกว่ามีบางอย่างขาดหายไปในเอกสารประกอบของ python ตั้งแต่การสร้างภาษา
axell13

6
และฉันรู้ว่า "abcdef" [:: - 1] ถูกแปลงเป็น "abcdef" [6: -7: -1] ดังนั้นวิธีที่ดีที่สุดในการอธิบายคือ: ให้lenเป็นความยาวของลำดับ หากขั้นตอนเป็นบวกค่าเริ่มต้นสำหรับการเริ่มต้นและจุดสิ้นสุดอยู่ที่ 0 และlen
axell13

4
เนื่องจากstackoverflow.com/questions/39241529/…ถูกทำเครื่องหมายว่าเป็นกลุ่มของสิ่งนี้มันจะสมเหตุสมผลหรือไม่ที่จะเพิ่มหัวข้อที่มีdelสัญกรณ์ wrt slice โดยเฉพาะอย่างยิ่งdel arr[:]ไม่ชัดเจนในทันที ("arr [:] ทำสำเนาจึงลบสำเนานั้น ???" ฯลฯ )
khazhyk

538

หลามกวดวิชาพูดคุยเกี่ยวกับเรื่องนี้ (เลื่อนลงเล็กน้อยจนกว่าคุณจะได้รับการมีส่วนร่วมเกี่ยวกับการหั่น)

แผนภาพศิลปะ ASCII นั้นมีประโยชน์เช่นกันสำหรับการจดจำว่าชิ้นงานเป็นอย่างไร:

 +---+---+---+---+---+---+
 | P | y | t | h | o | n |
 +---+---+---+---+---+---+
 0   1   2   3   4   5   6
-6  -5  -4  -3  -2  -1

วิธีการหนึ่งที่จะจำวิธีการทำงานชิ้นคือการคิดของดัชนีชี้ระหว่างตัวละครกับขอบด้านซ้ายของตัวอักษรตัวแรกเลข 0 แล้วขอบด้านขวาของตัวอักษรตัวสุดท้ายของสตริงของnตัวละครมีดัชนีn


10
คำแนะนำนี้ใช้ได้กับการก้าวย่างที่ดี แต่ไม่ได้เป็นการก้าวย่างเชิงลบ จากแผนภาพที่ผมคาดหวังว่าa[-4,-6,-1]จะเป็นแต่มันเป็นyP tyสิ่งที่ใช้งานได้เสมอคือการคิดเป็นตัวละครหรือสล็อตและใช้การจัดทำดัชนีเป็นช่วงเปิดครึ่ง - เปิดขวาถ้าก้าวบวก, เปิดซ้ายถ้าก้าวย่างเชิงลบ
aguadopd

แต่ไม่มีทางที่จะยุบไปสู่เซตว่างที่เริ่มต้นจากจุดสิ้นสุด (เช่นx[:0]เมื่อเริ่มต้นจากจุดเริ่มต้น) ดังนั้นคุณจะต้องใช้อาร์เรย์ตัวพิมพ์เล็กพิเศษ : /
endolith

412

การแจกแจงความเป็นไปได้ที่ไวยากรณ์อนุญาตให้ทำได้:

>>> seq[:]                # [seq[0],   seq[1],          ..., seq[-1]    ]
>>> seq[low:]             # [seq[low], seq[low+1],      ..., seq[-1]    ]
>>> seq[:high]            # [seq[0],   seq[1],          ..., seq[high-1]]
>>> seq[low:high]         # [seq[low], seq[low+1],      ..., seq[high-1]]
>>> seq[::stride]         # [seq[0],   seq[stride],     ..., seq[-1]    ]
>>> seq[low::stride]      # [seq[low], seq[low+stride], ..., seq[-1]    ]
>>> seq[:high:stride]     # [seq[0],   seq[stride],     ..., seq[high-1]]
>>> seq[low:high:stride]  # [seq[low], seq[low+stride], ..., seq[high-1]]

แน่นอนถ้า(high-low)%stride != 0จากนั้นจุดสิ้นสุดจะต่ำกว่าhigh-1เล็กน้อย

หากstrideเป็นค่าลบการสั่งซื้อจะเปลี่ยนไปเล็กน้อยเนื่องจากเรานับถอยหลัง:

>>> seq[::-stride]        # [seq[-1],   seq[-1-stride],   ..., seq[0]    ]
>>> seq[high::-stride]    # [seq[high], seq[high-stride], ..., seq[0]    ]
>>> seq[:low:-stride]     # [seq[-1],   seq[-1-stride],   ..., seq[low+1]]
>>> seq[high:low:-stride] # [seq[high], seq[high-stride], ..., seq[low+1]]

การแบ่งส่วนข้อมูลแบบขยาย (ด้วยเครื่องหมายจุลภาคและจุดไข่ปลา) ส่วนใหญ่จะใช้โดยโครงสร้างข้อมูลพิเศษเท่านั้น (เช่น NumPy) ลำดับขั้นพื้นฐานไม่สนับสนุนพวกเขา

>>> class slicee:
...     def __getitem__(self, item):
...         return repr(item)
...
>>> slicee()[0, 1:2, ::5, ...]
'(0, slice(1, 2, None), slice(None, None, 5), Ellipsis)'

จริงๆแล้วยังมีบางอย่างเหลืออยู่เช่นถ้าฉันพิมพ์ 'apple' [4: -4: -1] ฉันได้รับ 'elp', python แปล -4 เป็น 1 อาจจะ?
liyuan

โปรดทราบว่า backticks จะถูกคัดค้านในความโปรดปรานของrepr
wjandrea

@liyuan ประเภทการใช้__getitem__คือ; apple[slice(4, -4, -1)]ตัวอย่างของคุณจะเทียบเท่ากับ
chepner

320

คำตอบข้างต้นไม่ได้พูดถึงการแบ่งชิ้น เพื่อให้เข้าใจถึงการกำหนดชิ้นเป็นประโยชน์ในการเพิ่มแนวคิดอื่นให้กับศิลปะ ASCII:

                +---+---+---+---+---+---+
                | P | y | t | h | o | n |
                +---+---+---+---+---+---+
Slice position: 0   1   2   3   4   5   6
Index position:   0   1   2   3   4   5

>>> p = ['P','y','t','h','o','n']
# Why the two sets of numbers:
# indexing gives items, not lists
>>> p[0]
 'P'
>>> p[5]
 'n'

# Slicing gives lists
>>> p[0:1]
 ['P']
>>> p[0:2]
 ['P','y']

หนึ่งฮิวริสติกคือหนึ่งส่วนจากศูนย์ถึง n คิดว่า: "ศูนย์คือจุดเริ่มต้นเริ่มต้นที่จุดเริ่มต้นและนำรายการ n ในรายการ"

>>> p[5] # the last of six items, indexed from zero
 'n'
>>> p[0:5] # does NOT include the last item!
 ['P','y','t','h','o']
>>> p[0:6] # not p[0:5]!!!
 ['P','y','t','h','o','n']

ฮิวริสติกอื่นคือ "สำหรับชิ้นส่วนใด ๆ เปลี่ยนจุดเริ่มต้นเป็นศูนย์ใช้ฮิวริสติกก่อนหน้าเพื่อสิ้นสุดรายการจากนั้นนับจำนวนแรกกลับไปที่รายการสับจากจุดเริ่มต้น"

>>> p[0:4] # Start at the beginning and count out 4 items
 ['P','y','t','h']
>>> p[1:4] # Take one item off the front
 ['y','t','h']
>>> p[2:4] # Take two items off the front
 ['t','h']
# etc.

กฎข้อแรกของการกำหนดค่าชิ้นคือเนื่องจากการแบ่งการส่งคืนรายการการมอบหมายชิ้นต้องใช้รายการ (หรืออื่น ๆ iterable):

>>> p[2:3]
 ['t']
>>> p[2:3] = ['T']
>>> p
 ['P','y','T','h','o','n']
>>> p[2:3] = 't'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only assign an iterable

กฎข้อที่สองของการกำหนดชิ้นซึ่งคุณสามารถเห็นด้านบนคือส่วนใดของรายการที่ถูกส่งคืนโดยการจัดทำดัชนีชิ้นนั่นคือส่วนเดียวกันที่เปลี่ยนแปลงโดยการกำหนดชิ้น:

>>> p[2:4]
 ['T','h']
>>> p[2:4] = ['t','r']
>>> p
 ['P','y','t','r','o','n']

กฎข้อที่สามของการกำหนดชิ้นคือรายการที่กำหนด (iterable) ไม่จำเป็นต้องมีความยาวเท่ากัน ชิ้นส่วนที่จัดทำดัชนีนั้นถูกตัดออกและแทนที่สิ่งที่กำหนด:

>>> p = ['P','y','t','h','o','n'] # Start over
>>> p[2:4] = ['s','p','a','m']
>>> p
 ['P','y','s','p','a','m','o','n']

ส่วนที่ยากที่สุดที่จะคุ้นเคยคือการมอบหมายให้กับชิ้นส่วนที่ว่างเปล่า การใช้ฮิวริสติกที่ 1 และ 2 ช่วยให้คุณสามารถจัดทำดัชนีชิ้นส่วนที่ว่างได้ง่าย:

>>> p = ['P','y','t','h','o','n']
>>> p[0:4]
 ['P','y','t','h']
>>> p[1:4]
 ['y','t','h']
>>> p[2:4]
 ['t','h']
>>> p[3:4]
 ['h']
>>> p[4:4]
 []

และจากนั้นเมื่อคุณเห็นว่าการแบ่งส่วนเป็นชิ้นว่างเปล่าก็สมเหตุสมผลเช่นกัน:

>>> p = ['P','y','t','h','o','n']
>>> p[2:4] = ['x','y'] # Assigned list is same length as slice
>>> p
 ['P','y','x','y','o','n'] # Result is same length
>>> p = ['P','y','t','h','o','n']
>>> p[3:4] = ['x','y'] # Assigned list is longer than slice
>>> p
 ['P','y','t','x','y','o','n'] # The result is longer
>>> p = ['P','y','t','h','o','n']
>>> p[4:4] = ['x','y']
>>> p
 ['P','y','t','h','x','y','o','n'] # The result is longer still

โปรดทราบว่าเนื่องจากเราไม่ได้เปลี่ยนจำนวนชิ้นที่สอง (4) รายการที่แทรกไว้จะเรียงซ้อนกันเสมอกับ 'o' แม้ว่าเราจะกำหนดให้ชิ้นว่างเปล่าก็ตาม ดังนั้นตำแหน่งสำหรับการกำหนดชิ้นว่างจึงเป็นส่วนขยายตรรกะของตำแหน่งสำหรับชิ้นส่วนที่ไม่ว่างเปล่า

การสำรองข้อมูลเล็กน้อยจะเกิดอะไรขึ้นเมื่อคุณเดินไปเรื่อย ๆ กับขบวนนับนับชิ้นเริ่มต้นของเรา

>>> p = ['P','y','t','h','o','n']
>>> p[0:4]
 ['P','y','t','h']
>>> p[1:4]
 ['y','t','h']
>>> p[2:4]
 ['t','h']
>>> p[3:4]
 ['h']
>>> p[4:4]
 []
>>> p[5:4]
 []
>>> p[6:4]
 []

เมื่อหั่นเสร็จแล้วคุณก็เรียบร้อย มันไม่ได้เริ่มแบ่งไปข้างหลัง ใน Python คุณจะไม่ได้รับความก้าวหน้าเชิงลบเว้นแต่คุณจะขออย่างชัดเจนโดยใช้หมายเลขติดลบ

>>> p[5:3:-1]
 ['n','o']

มีผลบางอย่างแปลก ๆ กับกฎ "เมื่อคุณทำเสร็จแล้ว"

>>> p[4:4]
 []
>>> p[5:4]
 []
>>> p[6:4]
 []
>>> p[6]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range

ในความเป็นจริงเมื่อเทียบกับการจัดทำดัชนีการแบ่ง Python เป็นข้อผิดพลาดที่ผิดปกติ:

>>> p[100:200]
 []
>>> p[int(2e99):int(1e99)]
 []

บางครั้งสิ่งนี้อาจมีประโยชน์ แต่ก็อาจนำไปสู่พฤติกรรมที่ค่อนข้างแปลก:

>>> p
 ['P', 'y', 't', 'h', 'o', 'n']
>>> p[int(2e99):int(1e99)] = ['p','o','w','e','r']
>>> p
 ['P', 'y', 't', 'h', 'o', 'n', 'p', 'o', 'w', 'e', 'r']

ขึ้นอยู่กับใบสมัครของคุณนั่นอาจ ... หรืออาจจะไม่ใช่ ... เป็นสิ่งที่คุณหวังไว้ที่นั่น!


ด้านล่างนี้เป็นข้อความของคำตอบดั้งเดิมของฉัน มันมีประโยชน์กับคนจำนวนมากดังนั้นฉันไม่ต้องการลบ

>>> r=[1,2,3,4]
>>> r[1:1]
[]
>>> r[1:1]=[9,8]
>>> r
[1, 9, 8, 2, 3, 4]
>>> r[1:1]=['blah']
>>> r
[1, 'blah', 9, 8, 2, 3, 4]

สิ่งนี้อาจอธิบายความแตกต่างระหว่างการแบ่งและการจัดทำดัชนี


246

อธิบายสัญกรณ์ของ Python

ในระยะสั้นทวิภาค ( :) ในสัญกรณ์ห้อย ( subscriptable[subscriptarg]) ให้สัญกรณ์ชิ้น - ซึ่งมีข้อโต้แย้งทางเลือกstart, stop, step:

sliceable[start:stop:step]

Python slicing เป็นวิธีที่รวดเร็วในการคำนวณเพื่อเข้าถึงส่วนต่างๆของข้อมูลของคุณ ในความคิดของฉันการเป็นโปรแกรมเมอร์ Python ระดับกลางเป็นหนึ่งในแง่มุมของภาษาที่จำเป็นต้องคุ้นเคย

คำจำกัดความที่สำคัญ

ในการเริ่มต้นให้นิยามคำศัพท์สองสามคำ:

start:ดัชนีเริ่มต้นของชิ้นมันจะรวมองค์ประกอบที่ดัชนีนี้เว้นแต่ว่าจะเป็นเช่นเดียวกับหยุดเริ่มต้นที่ 0 คือดัชนีแรก ถ้ามันเป็นลบมันหมายถึงการเริ่มต้นnรายการจากจุดสิ้นสุด

หยุด:ดัชนีสิ้นสุดของชิ้นมันไม่รวมองค์ประกอบที่ดัชนีนี้เริ่มต้นที่ความยาวของลำดับที่ถูกหั่นนั่นคือถึงและรวมถึงจุดสิ้นสุด

ขั้นตอน:จำนวนที่ดัชนีเพิ่มขึ้นค่าเริ่มต้นที่ 1 หากเป็นค่าลบคุณจะแบ่งส่วนที่ทำซ้ำได้ในสิ่งที่ตรงกันข้าม

วิธีการจัดทำดัชนีทำงาน

คุณสามารถสร้างตัวเลขที่เป็นบวกหรือลบได้ ความหมายของตัวเลขบวกนั้นตรงไปตรงมา แต่สำหรับตัวเลขลบเช่นเดียวกับดัชนีใน Python คุณจะนับถอยหลังตั้งแต่ต้นจนจบสำหรับจุดเริ่มต้นและหยุดและสำหรับขั้นตอนคุณเพียงแค่ลดดัชนีของคุณลง ตัวอย่างนี้มาจากบทช่วยสอนของเอกสารแต่ฉันได้แก้ไขเล็กน้อยเพื่อระบุว่ารายการใดในลำดับที่อ้างอิงดัชนีแต่ละรายการ:

 +---+---+---+---+---+---+
 | P | y | t | h | o | n |
 +---+---+---+---+---+---+
   0   1   2   3   4   5 
  -6  -5  -4  -3  -2  -1

วิธีการแบ่งการทำงาน

ในการใช้เครื่องหมายแบ่งที่มีลำดับที่สนับสนุนคุณต้องรวมอย่างน้อยหนึ่งโคลอนในวงเล็บเหลี่ยมที่ตามลำดับ (ซึ่งใช้__getitem__วิธีการของลำดับตามจริงตามแบบจำลองข้อมูล Python )

สัญกรณ์ Slice ทำงานเช่นนี้:

sequence[start:stop:step]

และจำได้ว่ามีค่าเริ่มต้นสำหรับการเริ่มต้น , หยุดและขั้นตอนเพื่อที่จะเข้าถึงเริ่มต้นเพียงแค่ปล่อยออกมาโต้แย้ง

สัญกรณ์ Slice เพื่อรับองค์ประกอบเก้าชิ้นสุดท้ายจากรายการ (หรือลำดับอื่น ๆ ที่สนับสนุนมันเช่นสตริง) จะมีลักษณะดังนี้:

my_list[-9:]

เมื่อฉันเห็นสิ่งนี้ฉันอ่านส่วนในวงเล็บเป็น "9 ตั้งแต่ต้นจนจบ" (ที่จริงแล้วฉันย่อว่าจิตใจเป็น "-9, on")

คำอธิบาย:

สัญกรณ์เต็มคือ

my_list[-9:None:None]

และเพื่อแทนที่ค่าเริ่มต้น (ที่จริงแล้วเมื่อstepเป็นค่าลบstopค่าเริ่มต้นคือ-len(my_list) - 1ดังนั้นNoneสำหรับการหยุดจริง ๆ ก็หมายความว่ามันจะไปยังขั้นตอนสุดท้ายที่จะนำไปใช้)

my_list[-9:len(my_list):1]

ลำไส้ใหญ่ , :เป็นสิ่งที่บอกว่างูหลามคุณให้มันเป็นชิ้นและไม่ได้เป็นดัชนีปกติ นั่นเป็นเหตุผลว่าทำไมการทำสำเนารายการตื้น ๆ ใน Python 2 จึงเป็นวิธีที่แปลกประหลาด

list_copy = sequence[:]

และล้างพวกเขาด้วย:

del my_list[:]

(Python 3 ได้รับ a list.copyและlist.clearmethod)

เมื่อstepใดที่เป็นค่าลบค่าเริ่มต้นstartและstopเปลี่ยนแปลง

โดยค่าเริ่มต้นเมื่อstepอาร์กิวเมนต์เป็นที่ว่างเปล่า (หรือNone) +1มันถูกกำหนดให้

แต่คุณสามารถผ่านเป็นจำนวนเต็มลบได้และรายการ (หรือส่วนแบ่งมาตรฐานอื่น ๆ ส่วนใหญ่) จะถูกแบ่งเป็นส่วน ๆ จากจุดเริ่มต้นไปยังจุดเริ่มต้น

ดังนั้นชิ้นเชิงลบจะเปลี่ยนค่าเริ่มต้นstartและstop!

ยืนยันสิ่งนี้ในแหล่งที่มา

ฉันต้องการสนับสนุนให้ผู้ใช้อ่านแหล่งรวมทั้งเอกสารประกอบ ซอร์สโค้ดของชิ้นวัตถุและตรรกะนี้จะพบได้ที่นี่ ก่อนอื่นเราพิจารณาว่าstepเป็นลบหรือไม่:

 step_is_negative = step_sign < 0;

ถ้าเป็นเช่นนั้นขอบล่าง-1 หมายถึงเราฝานไปจนถึงและรวมถึงจุดเริ่มต้นและขอบเขตบนคือความยาวลบ 1 ซึ่งหมายถึงเราเริ่มต้นที่จุดสิ้นสุด (หมายเหตุว่าความหมายของนี้-1เป็นที่แตกต่างจาก-1ที่ผู้ใช้อาจจะผ่านการจัดทำดัชนีในหลามแสดงให้เห็นรายการสุดท้าย.)

if (step_is_negative) {
    lower = PyLong_FromLong(-1L);
    if (lower == NULL)
        goto error;

    upper = PyNumber_Add(length, lower);
    if (upper == NULL)
        goto error;
}

มิฉะนั้นstepเป็นบวกและขอบเขตล่างจะเป็นศูนย์และขอบบน (ซึ่งเราไปถึง แต่ไม่รวม) ความยาวของรายการที่หั่นบาง ๆ

else {
    lower = _PyLong_Zero;
    Py_INCREF(lower);
    upper = length;
    Py_INCREF(upper);
}

จากนั้นเราอาจต้องใช้ค่าเริ่มต้นสำหรับstartและstop- ค่าเริ่มต้นสำหรับนั้นstartจะถูกคำนวณเป็นขอบเขตบนเมื่อstepเป็นลบ:

if (self->start == Py_None) {
    start = step_is_negative ? upper : lower;
    Py_INCREF(start);
}

และstopขอบเขตล่าง:

if (self->stop == Py_None) {
    stop = step_is_negative ? lower : upper;
    Py_INCREF(stop);
}

ตั้งชื่อที่สื่อความหมายได้!

คุณอาจพบว่ามีประโยชน์ในการแยกการขึ้นรูปชิ้นส่วนจากการส่งผ่านไปยังlist.__getitem__วิธีการ ( นั่นคือสิ่งที่วงเล็บเหลี่ยมทำ ) แม้ว่าคุณจะไม่ใหม่ แต่ก็ทำให้โค้ดของคุณอ่านง่ายขึ้นเพื่อให้ผู้อื่นที่อาจต้องอ่านรหัสของคุณสามารถเข้าใจสิ่งที่คุณกำลังทำอยู่ได้ง่ายขึ้น

อย่างไรก็ตามคุณไม่สามารถกำหนดจำนวนเต็มที่คั่นด้วยโคลอนให้กับตัวแปรได้ คุณต้องใช้วัตถุชิ้น:

last_nine_slice = slice(-9, None)

อาร์กิวเมนต์ที่สองNoneเป็นสิ่งจำเป็นเพื่อให้อาร์กิวเมนต์แรกจะถูกแปลเป็นstartอาร์กิวเมนต์มิฉะนั้นก็จะเป็นstopข้อโต้แย้ง

จากนั้นคุณสามารถส่งวัตถุชิ้นไปยังลำดับของคุณ:

>>> list(range(100))[last_nine_slice]
[91, 92, 93, 94, 95, 96, 97, 98, 99]

เป็นเรื่องที่น่าสนใจที่ช่วงนั้นจะแบ่งเป็นส่วน ๆ :

>>> range(100)[last_nine_slice]
range(91, 100)

ข้อควรพิจารณาเกี่ยวกับหน่วยความจำ:

itertools.isliceตั้งแต่ชิ้นของรายการหลามสร้างวัตถุใหม่ในความทรงจำอีกฟังก์ชั่นสำคัญที่จะต้องระวังก็คือ โดยทั่วไปแล้วคุณจะต้องวนซ้ำไปเรื่อย ๆ ไม่ใช่แค่สร้างหน่วยความจำแบบสแตติก isliceเหมาะสำหรับสิ่งนี้ ข้อแม้ก็ไม่ได้สนับสนุนข้อโต้แย้งในทางลบต่อstart, stopหรือstepดังนั้นหากที่เป็นปัญหาคุณอาจจำเป็นต้องคำนวณดัชนีหรือย้อนกลับ iterable ล่วงหน้า

length = 100
last_nine_iter = itertools.islice(list(range(length)), length-9, None, 1)
list_last_nine = list(last_nine_iter)

และตอนนี้:

>>> list_last_nine
[91, 92, 93, 94, 95, 96, 97, 98, 99]

ข้อเท็จจริงที่ว่าตัวแบ่งส่วนรายการทำสำเนาเป็นคุณลักษณะของรายการเอง หากคุณกำลังแบ่งวัตถุขั้นสูงเช่น Pandas DataFrame มันอาจส่งคืนมุมมองบนต้นฉบับไม่ใช่สำเนา


146

และบางสิ่งที่ฉันไม่เห็นได้ชัดเมื่อฉันเห็นไวยากรณ์การแบ่งเป็นครั้งแรก:

>>> x = [1,2,3,4,5,6]
>>> x[::-1]
[6,5,4,3,2,1]

วิธีง่ายๆในการย้อนกลับลำดับ!

และถ้าคุณต้องการด้วยเหตุผลบางอย่างทุกรายการที่สองในลำดับที่กลับรายการ:

>>> x = [1,2,3,4,5,6]
>>> x[::-2]
[6,4,2]

100

ใน Python 2.7

การแบ่งส่วนใน Python

[a:b:c]

len = length of string, tuple or list

c -- default is +1. The sign of c indicates forward or backward, absolute value of c indicates steps. Default is forward with step size 1. Positive means forward, negative means backward.

a --  When c is positive or blank, default is 0. When c is negative, default is -1.

b --  When c is positive or blank, default is len. When c is negative, default is -(len+1).

การทำความเข้าใจกับการกำหนดดัชนีมีความสำคัญมาก

In forward direction, starts at 0 and ends at len-1

In backward direction, starts at -1 and ends at -len

เมื่อคุณพูดว่า [a: b: c] คุณกำลังพูดโดยขึ้นอยู่กับเครื่องหมายของ c (ไปข้างหน้าหรือข้างหลัง) เริ่มต้นที่ a และสิ้นสุดที่ b (ยกเว้นองค์ประกอบที่ดัชนี bth) ใช้กฎการจัดทำดัชนีด้านบนและจำไว้ว่าคุณจะพบองค์ประกอบในช่วงนี้เท่านั้น:

-len, -len+1, -len+2, ..., 0, 1, 2,3,4 , len -1

แต่ช่วงนี้ยังคงดำเนินต่อไปในทั้งสองทิศทาง:

...,-len -2 ,-len-1,-len, -len+1, -len+2, ..., 0, 1, 2,3,4 , len -1, len, len +1, len+2 , ....

ตัวอย่างเช่น:

             0    1    2   3    4   5   6   7   8   9   10   11
             a    s    t   r    i   n   g
    -9  -8  -7   -6   -5  -4   -3  -2  -1

หากคุณเลือก a, b และ c อนุญาตให้เหลื่อมกับช่วงข้างบนในขณะที่คุณใช้กฎสำหรับ a, b, c ข้างต้นคุณจะได้รับรายการที่มีองค์ประกอบ (สัมผัสระหว่างการสำรวจเส้นทาง) หรือคุณจะได้รายการที่ว่างเปล่า

สิ่งหนึ่งที่สุดท้าย: ถ้า a และ b เท่ากันคุณก็จะได้รายการว่าง:

>>> l1
[2, 3, 4]

>>> l1[:]
[2, 3, 4]

>>> l1[::-1] # a default is -1 , b default is -(len+1)
[4, 3, 2]

>>> l1[:-4:-1] # a default is -1
[4, 3, 2]

>>> l1[:-3:-1] # a default is -1
[4, 3]

>>> l1[::] # c default is +1, so a default is 0, b default is len
[2, 3, 4]

>>> l1[::-1] # c is -1 , so a default is -1 and b default is -(len+1)
[4, 3, 2]


>>> l1[-100:-200:-1] # Interesting
[]

>>> l1[-1:-200:-1] # Interesting
[4, 3, 2]


>>> l1[-1:-1:1]
[]


>>> l1[-1:5:1] # Interesting
[4]


>>> l1[1:-7:1]
[]

>>> l1[1:-7:-1] # Interesting
[3, 2]

>>> l1[:-2:-2] # a default is -1, stop(b) at -2 , step(c) by 2 in reverse direction
[4]

2
อีกตัวอย่างที่น่าสนใจ: a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]; a[:-2:-2]ซึ่งส่งผลให้[9]
Deviacium

96

พบกับตารางที่ยอดเยี่ยมนี้ได้ที่http://wiki.python.org/moin/MovingToPythonFromOtherLanguages

Python indexes and slices for a six-element list.
Indexes enumerate the elements, slices enumerate the spaces between the elements.

Index from rear:    -6  -5  -4  -3  -2  -1      a=[0,1,2,3,4,5]    a[1:]==[1,2,3,4,5]
Index from front:    0   1   2   3   4   5      len(a)==6          a[:5]==[0,1,2,3,4]
                   +---+---+---+---+---+---+    a[0]==0            a[:-2]==[0,1,2,3]
                   | a | b | c | d | e | f |    a[5]==5            a[1:2]==[1]
                   +---+---+---+---+---+---+    a[-1]==5           a[1:-1]==[1,2,3,4]
Slice from front:  :   1   2   3   4   5   :    a[-2]==4
Slice from rear:   :  -5  -4  -3  -2  -1   :
                                                b=a[:]
                                                b==[0,1,2,3,4,5] (shallow copy of a)

65

หลังจากใช้ไปสักพักฉันก็รู้ว่าคำอธิบายที่ง่ายที่สุดคือมันเหมือนกับสิ่งที่ขัดแย้งกันในforวง ...

(from:to:step)

ใด ๆ ของพวกเขาเป็นตัวเลือก:

(:to:step)
(from::step)
(from:to)

จากนั้นการจัดทำดัชนีเชิงลบเพียงต้องการให้คุณเพิ่มความยาวของสตริงลงในดัชนีลบเพื่อทำความเข้าใจ

ใช้ได้กับฉันแล้ว ...


52

ฉันพบว่ามันง่ายกว่าที่จะจำว่ามันทำงานอย่างไรและจากนั้นฉันสามารถหาชุดค่าผสมแบบเริ่ม / หยุด / ขั้นตอนที่เฉพาะเจาะจงได้

เป็นคำแนะนำให้เข้าใจrange()ก่อน:

def range(start=0, stop, step=1):  # Illegal syntax, but that's the effect
    i = start
    while (i < stop if step > 0 else i > stop):
        yield i
        i += step

เริ่มต้นจากstart, เพิ่มขึ้นโดยไม่ถึงstep stopง่ายมาก.

สิ่งที่ต้องจดจำเกี่ยวกับขั้นตอนเชิงลบคือstopจุดสิ้นสุดที่ถูกแยกออกเสมอไม่ว่าจะสูงหรือต่ำกว่า หากคุณต้องการให้ชิ้นงานเรียงกันเรียงกันมันจะสะอาดกว่าถ้าทำการกลับรายการแยกกัน: เช่น'abcde'[1:-2][::-1]ตัดเศษถ่านหนึ่งอันออกจากซ้ายสองจากขวาจากนั้นกลับด้าน (ดูเพิ่มเติมที่reversed())

การแบ่งส่วนลำดับเหมือนกันยกเว้นอันดับแรกจะทำให้ดัชนีเชิงลบเป็นปกติและจะไม่สามารถออกไปนอกลำดับได้:

สิ่งที่ต้องทำ : รหัสด้านล่างมีข้อผิดพลาดกับ "ไม่เคยออกไปข้างนอกลำดับ" เมื่อ abs (ขั้นตอน)> 1; ฉันคิดว่าฉันแก้ไขมันให้ถูกต้อง แต่มันยากที่จะเข้าใจ

def this_is_how_slicing_works(seq, start=None, stop=None, step=1):
    if start is None:
        start = (0 if step > 0 else len(seq)-1)
    elif start < 0:
        start += len(seq)
    if not 0 <= start < len(seq):  # clip if still outside bounds
        start = (0 if step > 0 else len(seq)-1)
    if stop is None:
        stop = (len(seq) if step > 0 else -1)  # really -1, not last element
    elif stop < 0:
        stop += len(seq)
    for i in range(start, stop, step):
        if 0 <= i < len(seq):
            yield seq[i]

ไม่ต้องกังวลเกี่ยวกับis Noneรายละเอียด - เพียงจำไว้ว่าการละเว้นstartและ / หรือstopทำสิ่งที่ถูกต้องเสมอเพื่อให้ลำดับทั้งหมด

ดัชนีเชิงลบ Normalizing แรกที่ช่วยให้การเริ่มต้นและ / หรือหยุดที่จะนับจากปลายอิสระ: แม้จะมี'abcde'[1:-2] == 'abcde'[1:3] == 'bc' range(1,-2) == []การปรับสภาพบางครั้งคิดว่าเป็น "โมดูโลความยาว" แต่โปรดทราบว่ามันเพิ่มความยาวเพียงครั้งเดียว: เช่น'abcde'[-53:42]เป็นเพียงสายอักขระทั้งหมด


3
สิ่งthis_is_how_slicing_worksนี้ไม่เหมือนกับ python slice EG [0, 1, 2][-5:3:3]จะได้ [0] เป็นไพ ธ อน แต่list(this_is_how_slicing_works([0, 1, 2], -5, 3, 3))รับ [1]
Eastsun

@Eastun โอ๊ะคุณพูดถูก! กรณีที่ชัดเจน: แต่range(4)[-200:200:3] == [0, 3] list(this_is_how_slicing_works([0, 1, 2, 3], -200, 200, 3)) == [2]ฉันif 0 <= i < len(seq):เป็นความพยายามในการใช้งาน "ไม่เคยออกนอกลำดับ" เพียง แต่ผิดสำหรับขั้นตอน> 1 ฉันจะเขียนมันใหม่ในวันนี้ (พร้อมการทดสอบ)
Beni Cherniavsky-Paskin

40

ฉันใช้วิธีการ "ชี้ดัชนีระหว่างองค์ประกอบ" ในการคิดเกี่ยวกับมันด้วยตัวเอง แต่วิธีหนึ่งในการอธิบายซึ่งบางครั้งช่วยให้ผู้อื่นได้รับสิ่งนี้:

mylist[X:Y]

X คือดัชนีขององค์ประกอบแรกที่คุณต้องการ
Y คือดัชนีองค์ประกอบแรกที่คุณไม่ต้องการ


40
Index:
      ------------>
  0   1   2   3   4
+---+---+---+---+---+
| a | b | c | d | e |
+---+---+---+---+---+
  0  -4  -3  -2  -1
      <------------

Slice:
    <---------------|
|--------------->
:   1   2   3   4   :
+---+---+---+---+---+
| a | b | c | d | e |
+---+---+---+---+---+
:  -4  -3  -2  -1   :
|--------------->
    <---------------|

ฉันหวังว่านี่จะช่วยให้คุณสร้างแบบจำลองรายการใน Python

การอ้างอิง: http://wiki.python.org/moin/MovingToPythonFromOtherLanguages


38

สัญกรณ์การแบ่งหลาม:

a[start:end:step]
  • สำหรับstartและendค่าลบถูกตีความว่าสัมพันธ์กับจุดสิ้นสุดของลำดับ
  • ดัชนีเชิงบวกสำหรับendระบุตำแหน่งหลังจากองค์ประกอบสุดท้ายที่จะรวม
  • [+0:-0:1]ค่าว่างเปล่าจะผิดนัดดังต่อไปนี้:
  • การใช้ขั้นตอนเชิงลบย้อนกลับการตีความstartและend

สัญกรณ์ขยายไปถึงเมทริกซ์ (numpy) และอาร์เรย์หลายมิติ ตัวอย่างเช่นหากต้องการแบ่งคอลัมน์ทั้งหมดคุณสามารถใช้:

m[::,0:2:] ## slice the first two columns

ชิ้นถือการอ้างอิงไม่คัดลอกขององค์ประกอบอาร์เรย์ deepcopy()หากคุณต้องการที่จะทำสำเนาแยกต่างหากอาร์เรย์คุณสามารถใช้


34

คุณยังสามารถใช้การกำหนดชิ้นเพื่อลบองค์ประกอบหนึ่งรายการหรือมากกว่าจากรายการ:

r = [1, 'blah', 9, 8, 2, 3, 4]
>>> r[1:4] = []
>>> r
[1, 2, 3, 4]

33

นี่เป็นเพียงข้อมูลเพิ่มเติม ... พิจารณารายการด้านล่าง

>>> l=[12,23,345,456,67,7,945,467]

ไม่กี่เทคนิคอื่น ๆ สำหรับการย้อนกลับรายการ:

>>> l[len(l):-len(l)-1:-1]
[467, 945, 7, 67, 456, 345, 23, 12]

>>> l[:-len(l)-1:-1]
[467, 945, 7, 67, 456, 345, 23, 12]

>>> l[len(l)::-1]
[467, 945, 7, 67, 456, 345, 23, 12]

>>> l[::-1]
[467, 945, 7, 67, 456, 345, 23, 12]

>>> l[-1:-len(l)-1:-1]
[467, 945, 7, 67, 456, 345, 23, 12]

33

นี่คือวิธีที่ฉันสอนการแบ่งส่วนสำหรับมือใหม่:

ทำความเข้าใจความแตกต่างระหว่างการจัดทำดัชนีและการแบ่งส่วน:

Wiki Python มีภาพที่น่าทึ่งซึ่งแยกการจัดทำดัชนีและการแบ่ง

ป้อนคำอธิบายภาพที่นี่

มันเป็นรายการที่มีหกองค์ประกอบในนั้น เพื่อให้เข้าใจการแบ่งส่วนได้ดีขึ้นให้พิจารณารายการนั้นเป็นชุดของหกกล่องที่วางไว้ด้วยกัน แต่ละกล่องมีตัวอักษรอยู่ในนั้น

การจัดทำดัชนีเป็นเหมือนการจัดการกับเนื้อหาของกล่อง คุณสามารถตรวจสอบเนื้อหาของกล่องใด ๆ แต่คุณไม่สามารถตรวจสอบเนื้อหาของกล่องหลายกล่องพร้อมกัน คุณสามารถแทนที่เนื้อหาของกล่อง แต่คุณไม่สามารถวางสองลูกในกล่องเดียวหรือแทนที่สองลูกในเวลาเดียวกัน

In [122]: alpha = ['a', 'b', 'c', 'd', 'e', 'f']

In [123]: alpha
Out[123]: ['a', 'b', 'c', 'd', 'e', 'f']

In [124]: alpha[0]
Out[124]: 'a'

In [127]: alpha[0] = 'A'

In [128]: alpha
Out[128]: ['A', 'b', 'c', 'd', 'e', 'f']

In [129]: alpha[0,1]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-129-c7eb16585371> in <module>()
----> 1 alpha[0,1]

TypeError: list indices must be integers, not tuple

การแบ่งเป็นเหมือนการจัดการกับกล่องด้วยตัวเอง คุณสามารถหยิบกล่องแรกและวางบนโต๊ะอื่น ในการรับกล่องสิ่งที่คุณต้องรู้ก็คือตำแหน่งของจุดเริ่มต้นและจุดสิ้นสุดของกล่อง

คุณสามารถเลือกสามกล่องแรกหรือสองกล่องสุดท้ายหรือกล่องทั้งหมดระหว่าง 1 ถึง 4 ดังนั้นคุณสามารถเลือกชุดของกล่องใดก็ได้หากคุณทราบจุดเริ่มต้นและจุดสิ้นสุด ตำแหน่งเหล่านี้เรียกว่าตำแหน่งเริ่มและหยุด

สิ่งที่น่าสนใจคือคุณสามารถแทนที่กล่องหลายกล่องพร้อมกัน นอกจากนี้คุณสามารถวางหลายกล่องได้ทุกที่ที่คุณต้องการ

In [130]: alpha[0:1]
Out[130]: ['A']

In [131]: alpha[0:1] = 'a'

In [132]: alpha
Out[132]: ['a', 'b', 'c', 'd', 'e', 'f']

In [133]: alpha[0:2] = ['A', 'B']

In [134]: alpha
Out[134]: ['A', 'B', 'c', 'd', 'e', 'f']

In [135]: alpha[2:2] = ['x', 'xx']

In [136]: alpha
Out[136]: ['A', 'B', 'x', 'xx', 'c', 'd', 'e', 'f']

ขั้นตอน:

จนถึงตอนนี้คุณได้เลือกกล่องอย่างต่อเนื่อง แต่บางครั้งคุณจำเป็นต้องรับอย่างไม่น่าเชื่อ ตัวอย่างเช่นคุณสามารถรับกล่องทุกวินาที คุณสามารถรับกล่องทุก ๆ สามจากตอนท้าย ค่านี้เรียกว่าขนาดขั้นตอน นี่แสดงถึงช่องว่างระหว่างการเลือกรถปิคอัพที่ต่อเนื่องของคุณ ขนาดขั้นตอนควรเป็นค่าบวกหากคุณกำลังเลือกกล่องตั้งแต่ต้นจนจบและในทางกลับกัน

In [137]: alpha = ['a', 'b', 'c', 'd', 'e', 'f']

In [142]: alpha[1:5:2]
Out[142]: ['b', 'd']

In [143]: alpha[-1:-5:-2]
Out[143]: ['f', 'd']

In [144]: alpha[1:5:-2]
Out[144]: []

In [145]: alpha[-1:-5:2]
Out[145]: []

Python แสดงให้เห็นว่าพารามิเตอร์ที่ขาดหายไปได้อย่างไร:

เมื่อแบ่งส่วนถ้าคุณไม่ใช้พารามิเตอร์ใด ๆ Python จะพยายามหาค่าโดยอัตโนมัติ

หากคุณตรวจสอบซอร์สโค้ดของCPythonคุณจะพบฟังก์ชันที่เรียกว่า PySlice_GetIndicesEx () ซึ่งเป็นตัวบ่งชี้ดัชนีเป็นชิ้นสำหรับพารามิเตอร์ที่กำหนด นี่คือรหัสเทียบเท่าแบบลอจิคัลใน Python

ฟังก์ชันนี้ใช้วัตถุ Python และพารามิเตอร์ทางเลือกสำหรับการแบ่งและส่งคืนค่าเริ่มต้นหยุดขั้นตอนและความยาวส่วนสำหรับชิ้นที่ร้องขอ

def py_slice_get_indices_ex(obj, start=None, stop=None, step=None):

    length = len(obj)

    if step is None:
        step = 1
    if step == 0:
        raise Exception("Step cannot be zero.")

    if start is None:
        start = 0 if step > 0 else length - 1
    else:
        if start < 0:
            start += length
        if start < 0:
            start = 0 if step > 0 else -1
        if start >= length:
            start = length if step > 0 else length - 1

    if stop is None:
        stop = length if step > 0 else -1
    else:
        if stop < 0:
            stop += length
        if stop < 0:
            stop = 0 if step > 0 else -1
        if stop >= length:
            stop = length if step > 0 else length - 1

    if (step < 0 and stop >= start) or (step > 0 and start >= stop):
        slice_length = 0
    elif step < 0:
        slice_length = (stop - start + 1)/(step) + 1
    else:
        slice_length = (stop - start - 1)/(step) + 1

    return (start, stop, step, slice_length)

นี่คือความเฉลียวฉลาดที่อยู่ด้านหลังชิ้น เนื่องจาก Python มีฟังก์ชันในตัวที่เรียกว่า slice คุณสามารถผ่านพารามิเตอร์บางตัวและตรวจสอบวิธีการคำนวณพารามิเตอร์ที่ขาดหายไปอย่างชาญฉลาด

In [21]: alpha = ['a', 'b', 'c', 'd', 'e', 'f']

In [22]: s = slice(None, None, None)

In [23]: s
Out[23]: slice(None, None, None)

In [24]: s.indices(len(alpha))
Out[24]: (0, 6, 1)

In [25]: range(*s.indices(len(alpha)))
Out[25]: [0, 1, 2, 3, 4, 5]

In [26]: s = slice(None, None, -1)

In [27]: range(*s.indices(len(alpha)))
Out[27]: [5, 4, 3, 2, 1, 0]

In [28]: s = slice(None, 3, -1)

In [29]: range(*s.indices(len(alpha)))
Out[29]: [5, 4]

หมายเหตุ:โพสต์นี้ถูกเขียนเดิมในบล็อกของฉันข่าวกรองเบื้องหลังหลามชิ้น


29

ตามกฎทั่วไปการเขียนโค้ดที่มีค่าดัชนี hardcoded จำนวนมากนำไปสู่ความไม่สะดวกในการอ่านและการบำรุงรักษา ตัวอย่างเช่นหากคุณกลับมาที่รหัสในอีกหนึ่งปีต่อมาคุณจะเห็นและสงสัยว่าคุณคิดอย่างไรเมื่อคุณเขียนมัน วิธีแก้ปัญหาที่แสดงเป็นเพียงวิธีการที่ชัดเจนยิ่งขึ้นว่ารหัสของคุณกำลังทำอะไรอยู่ โดยทั่วไป slice ในตัว () จะสร้างวัตถุชิ้นที่สามารถใช้ได้ทุกที่ที่ได้รับอนุญาต ตัวอย่างเช่น:

>>> items = [0, 1, 2, 3, 4, 5, 6]
>>> a = slice(2, 4)
>>> items[2:4]
[2, 3]
>>> items[a]
[2, 3]
>>> items[a] = [10,11]
>>> items
[0, 1, 10, 11, 4, 5, 6]
>>> del items[a]
>>> items
[0, 1, 4, 5, 6]

หากคุณมีอินสแตนซ์ส่วนแบ่ง s คุณสามารถรับข้อมูลเพิ่มเติมเกี่ยวกับมันได้โดยดูที่แอ็ตทริบิวต์ s.start, s.stop และ s.step ตัวอย่างเช่น:

>>> a = slice(10, 50, 2)
>>> a.start
10
>>> a.stop
50
>>> a.step
2
>>>

25

1. สัญกรณ์ Slice

เพื่อให้ง่ายขึ้นโปรดจำไว้ว่าslice มีรูปแบบเดียวเท่านั้น:

s[start:end:step]

และนี่คือวิธีการทำงาน:

  • s: วัตถุที่สามารถหั่นได้
  • start: ดัชนีแรกเพื่อเริ่มการทำซ้ำ
  • end: ดัชนีล่าสุดโปรดทราบว่าendดัชนีจะไม่รวมอยู่ในส่วนที่เป็นผลลัพธ์
  • step: เลือกองค์ประกอบทุกstepดัชนี

สิ่งที่นำเข้าอื่น ๆ : ทั้งหมดstart, end, stepสามารถละเว้น! และถ้าพวกเขาจะถูกตัดออกค่าเริ่มต้นของพวกเขาจะถูกนำมาใช้: 0, len(s), 1ตาม

ดังนั้นรูปแบบที่เป็นไปได้คือ:

# Mostly used variations
s[start:end]
s[start:]
s[:end]

# Step-related variations
s[:end:step]
s[start::step]
s[::step]

# Make a copy
s[:]

หมายเหตุ: หากstart >= end(พิจารณาเฉพาะเมื่อstep>0) []งูหลามจะกลับมาเป็นชิ้นที่ว่างเปล่า

2. ข้อผิดพลาด

ส่วนด้านบนจะอธิบายเกี่ยวกับคุณสมบัติหลักของชิ้นงานและมันจะทำงานในเกือบทุกครั้ง อย่างไรก็ตามอาจมีข้อผิดพลาดที่คุณควรระวังและส่วนนี้อธิบายถึงพวกเขา

ดัชนีเชิงลบ

สิ่งแรกที่สร้างความสับสนให้กับผู้เรียน Python คือดัชนีสามารถลบได้! อย่าตกใจ: ดัชนีลบหมายถึงนับถอยหลัง

ตัวอย่างเช่น:

s[-5:]    # Start at the 5th index from the end of array,
          # thus returning the last 5 elements.
s[:-5]    # Start at index 0, and end until the 5th index from end of array,
          # thus returning s[0:len(s)-5].

ขั้นตอนเชิงลบ

การทำให้สิ่งต่าง ๆ สับสนมากขึ้นนั่นstepก็อาจเป็นลบเช่นกัน!

ขั้นตอนเชิงลบหมายถึงวนซ้ำอาร์เรย์ไปข้างหลัง: ตั้งแต่ต้นจนจบโดยมีดัชนีสิ้นสุดรวมอยู่ด้วยและดัชนีเริ่มต้นไม่รวมอยู่ในผลลัพธ์

หมายเหตุ : เมื่อขั้นตอนเป็นลบค่าเริ่มต้นสำหรับstartคือlen(s)(ในขณะที่endไม่เท่ากับ0เนื่องจากs[::-1]มีs[0]) ตัวอย่างเช่น:

s[::-1]            # Reversed slice
s[len(s)::-1]      # The same as above, reversed slice
s[0:len(s):-1]     # Empty list

ผิดพลาดนอกช่วงหรือไม่

จะประหลาดใจ: ชิ้นจะไม่เพิ่ม IndexError เมื่อดัชนีอยู่นอกช่วง!

หากดัชนีอยู่นอกช่วง Python จะพยายามอย่างดีที่สุดเพื่อตั้งค่าดัชนีให้เป็น0หรือlen(s)ตามสถานการณ์ ตัวอย่างเช่น:

s[:len(s)+5]      # The same as s[:len(s)]
s[-len(s)-5::]    # The same as s[0:]
s[len(s)+5::-1]   # The same as s[len(s)::-1], and the same as s[::-1]

3. ตัวอย่าง

ให้คำตอบนี้จบด้วยตัวอย่างอธิบายทุกสิ่งที่เราพูดถึง:

# Create our array for demonstration
In [1]: s = [i for i in range(10)]

In [2]: s
Out[2]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [3]: s[2:]   # From index 2 to last index
Out[3]: [2, 3, 4, 5, 6, 7, 8, 9]

In [4]: s[:8]   # From index 0 up to index 8
Out[4]: [0, 1, 2, 3, 4, 5, 6, 7]

In [5]: s[4:7]  # From index 4 (included) up to index 7(excluded)
Out[5]: [4, 5, 6]

In [6]: s[:-2]  # Up to second last index (negative index)
Out[6]: [0, 1, 2, 3, 4, 5, 6, 7]

In [7]: s[-2:]  # From second last index (negative index)
Out[7]: [8, 9]

In [8]: s[::-1] # From last to first in reverse order (negative step)
Out[8]: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

In [9]: s[::-2] # All odd numbers in reversed order
Out[9]: [9, 7, 5, 3, 1]

In [11]: s[-2::-2] # All even numbers in reversed order
Out[11]: [8, 6, 4, 2, 0]

In [12]: s[3:15]   # End is out of range, and Python will set it to len(s).
Out[12]: [3, 4, 5, 6, 7, 8, 9]

In [14]: s[5:1]    # Start > end; return empty list
Out[14]: []

In [15]: s[11]     # Access index 11 (greater than len(s)) will raise an IndexError
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-15-79ffc22473a3> in <module>()
----> 1 s[11]

IndexError: list index out of range

24

คำตอบก่อนหน้านี้ไม่ได้พูดถึงการแบ่งส่วนข้อมูลแบบหลายมิติซึ่งเป็นไปได้โดยใช้แพ็คเกจNumPy ที่มีชื่อเสียง:

การแบ่งส่วนสามารถนำไปใช้กับอาร์เรย์หลายมิติได้

# Here, a is a NumPy array

>>> a
array([[ 1,  2,  3,  4],
       [ 5,  6,  7,  8],
       [ 9, 10, 11, 12]])
>>> a[:2, 0:3:2]
array([[1, 3],
       [5, 7]])

" :2" ก่อนเครื่องหมายจุลภาคจะทำงานในมิติแรกและ " 0:3:2" หลังจากเครื่องหมายจุลภาคทำงานในมิติที่สอง


4
เตือนความทรงจำที่เป็นมิตรที่คุณไม่สามารถทำได้ใน Python listแต่เฉพาะarrayใน Numpy
Mars Lee

15
#!/usr/bin/env python

def slicegraphical(s, lista):

    if len(s) > 9:
        print """Enter a string of maximum 9 characters,
    so the printig would looki nice"""
        return 0;
    # print " ",
    print '  '+'+---' * len(s) +'+'
    print ' ',
    for letter in s:
        print '| {}'.format(letter),
    print '|'
    print " ",; print '+---' * len(s) +'+'

    print " ",
    for letter in range(len(s) +1):
        print '{}  '.format(letter),
    print ""
    for letter in range(-1*(len(s)), 0):
        print ' {}'.format(letter),
    print ''
    print ''


    for triada in lista:
        if len(triada) == 3:
            if triada[0]==None and triada[1] == None and triada[2] == None:
                # 000
                print s+'[   :   :   ]' +' = ', s[triada[0]:triada[1]:triada[2]]
            elif triada[0] == None and triada[1] == None and triada[2] != None:
                # 001
                print s+'[   :   :{0:2d} ]'.format(triada[2], '','') +' = ', s[triada[0]:triada[1]:triada[2]]
            elif triada[0] == None and triada[1] != None and triada[2] == None:
                # 010
                print s+'[   :{0:2d} :   ]'.format(triada[1]) +' = ', s[triada[0]:triada[1]:triada[2]]
            elif triada[0] == None and triada[1] != None and triada[2] != None:
                # 011
                print s+'[   :{0:2d} :{1:2d} ]'.format(triada[1], triada[2]) +' = ', s[triada[0]:triada[1]:triada[2]]
            elif triada[0] != None and triada[1] == None and triada[2] == None:
                # 100
                print s+'[{0:2d} :   :   ]'.format(triada[0]) +' = ', s[triada[0]:triada[1]:triada[2]]
            elif triada[0] != None and triada[1] == None and triada[2] != None:
                # 101
                print s+'[{0:2d} :   :{1:2d} ]'.format(triada[0], triada[2]) +' = ', s[triada[0]:triada[1]:triada[2]]
            elif triada[0] != None and triada[1] != None and triada[2] == None:
                # 110
                print s+'[{0:2d} :{1:2d} :   ]'.format(triada[0], triada[1]) +' = ', s[triada[0]:triada[1]:triada[2]]
            elif triada[0] != None and triada[1] != None and triada[2] != None:
                # 111
                print s+'[{0:2d} :{1:2d} :{2:2d} ]'.format(triada[0], triada[1], triada[2]) +' = ', s[triada[0]:triada[1]:triada[2]]

        elif len(triada) == 2:
            if triada[0] == None and triada[1] == None:
                # 00
                print s+'[   :   ]    ' + ' = ', s[triada[0]:triada[1]]
            elif triada[0] == None and triada[1] != None:
                # 01
                print s+'[   :{0:2d} ]    '.format(triada[1]) + ' = ', s[triada[0]:triada[1]]
            elif triada[0] != None and triada[1] == None:
                # 10
                print s+'[{0:2d} :   ]    '.format(triada[0]) + ' = ', s[triada[0]:triada[1]]
            elif triada[0] != None and triada[1] != None:
                # 11
                print s+'[{0:2d} :{1:2d} ]    '.format(triada[0],triada[1]) + ' = ', s[triada[0]:triada[1]]

        elif len(triada) == 1:
            print s+'[{0:2d} ]        '.format(triada[0]) + ' = ', s[triada[0]]


if __name__ == '__main__':
    # Change "s" to what ever string you like, make it 9 characters for
    # better representation.
    s = 'COMPUTERS'

    # add to this list different lists to experement with indexes
    # to represent ex. s[::], use s[None, None,None], otherwise you get an error
    # for s[2:] use s[2:None]

    lista = [[4,7],[2,5,2],[-5,1,-1],[4],[-4,-6,-1], [2,-3,1],[2,-3,-1], [None,None,-1],[-5,None],[-5,0,-1],[-5,None,-1],[-1,1,-2]]

    slicegraphical(s, lista)

คุณสามารถเรียกใช้สคริปต์นี้และทดลองกับมันด้านล่างนี้เป็นตัวอย่างบางส่วนที่ฉันได้รับจากสคริปต์

  +---+---+---+---+---+---+---+---+---+
  | C | O | M | P | U | T | E | R | S |
  +---+---+---+---+---+---+---+---+---+
  0   1   2   3   4   5   6   7   8   9   
 -9  -8  -7  -6  -5  -4  -3  -2  -1 

COMPUTERS[ 4 : 7 ]     =  UTE
COMPUTERS[ 2 : 5 : 2 ] =  MU
COMPUTERS[-5 : 1 :-1 ] =  UPM
COMPUTERS[ 4 ]         =  U
COMPUTERS[-4 :-6 :-1 ] =  TU
COMPUTERS[ 2 :-3 : 1 ] =  MPUT
COMPUTERS[ 2 :-3 :-1 ] =  
COMPUTERS[   :   :-1 ] =  SRETUPMOC
COMPUTERS[-5 :   ]     =  UTERS
COMPUTERS[-5 : 0 :-1 ] =  UPMO
COMPUTERS[-5 :   :-1 ] =  UPMOC
COMPUTERS[-1 : 1 :-2 ] =  SEUM
[Finished in 0.9s]

เมื่อใช้ขั้นตอนเชิงลบให้สังเกตว่าคำตอบถูกเลื่อนไปทางขวา 1


14

สมองของฉันดูเหมือนจะมีความสุขที่จะยอมรับว่าlst[start:end]มีstartรายการ -th ฉันอาจจะบอกว่ามันเป็น 'ข้อสันนิษฐานตามธรรมชาติ'

แต่ในบางครั้งมีข้อสงสัยเกิดขึ้นและสมองของฉันขอความมั่นใจว่าไม่มีendองค์ประกอบ -th

ในช่วงเวลาเหล่านี้ฉันพึ่งพาทฤษฎีบทง่ายๆนี้:

for any n,    lst = lst[:n] + lst[n:]

คุณสมบัตินี้สวยบอกว่าlst[start:end]ไม่ได้มีendรายการ -th lst[end:]เพราะมันอยู่ใน

โปรดทราบว่าทฤษฎีบทนี้เป็นจริงสำหรับnทุก ๆ ตัวอย่างเช่นคุณสามารถตรวจสอบได้

lst = range(10)
lst[:-42] + lst[-42:] == lst

Trueผลตอบแทน


12

ในความคิดของฉันคุณจะเข้าใจและจดจำเครื่องหมาย Python ของการแบ่งสตริงได้ดียิ่งขึ้นหากคุณดูด้วยวิธีดังต่อไปนี้ (อ่านต่อ)

มาทำงานกับสตริงต่อไปนี้ ...

azString = "abcdefghijklmnopqrstuvwxyz"

สำหรับผู้ที่ไม่ทราบคุณสามารถสร้างสตริงย่อยจากการazStringใช้สัญลักษณ์azString[x:y]

มาจากภาษาโปรแกรมอื่น ๆ นั่นคือเมื่อสามัญสำนึกได้รับความเสียหาย x และ y คืออะไร

ฉันต้องนั่งลงและเรียกใช้หลายสถานการณ์ในการค้นหาเทคนิคการท่องจำที่จะช่วยให้ฉันจำได้ว่า x และ y คืออะไรและช่วยให้ฉันฝานสตริงอย่างถูกต้องตั้งแต่ครั้งแรก

ข้อสรุปของฉันคือ x และ y ควรถูกมองว่าเป็นดัชนีขอบเขตที่ล้อมรอบสตริงที่เราต้องการเพิ่ม ดังนั้นเราควรจะเห็นการแสดงออกเป็นหรือมากขึ้นชัดเจนเป็นazString[index1, index2]azString[index_of_first_character, index_after_the_last_character]

นี่คือตัวอย่างการสร้างภาพข้อมูล ...

Letters   a b c d e f g h i j ...
         ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
             ┊           ┊
Indexes  0 1 2 3 4 5 6 7 8 9 ...
             ┊           ┊
cdefgh    index1       index2

ดังนั้นสิ่งที่คุณต้องทำคือการตั้งค่า index1 และ index2 เป็นค่าที่ล้อมรอบซับสตริงที่ต้องการ ตัวอย่างเช่นในการรับสตริงย่อย "cdefgh" คุณสามารถใช้azString[2:8]เพราะดัชนีทางด้านซ้ายของ "c" คือ 2 และหนึ่งในขนาดที่เหมาะสมของ "h" คือ 8

จำไว้ว่าเรากำลังกำหนดขอบเขต และขอบเขตเหล่านั้นคือตำแหน่งที่คุณสามารถวางวงเล็บที่จะพันรอบสตริงย่อยแบบนี้ ...

ab [ cdefgh ] ij

เคล็ดลับนั้นใช้ได้ตลอดเวลาและง่ายต่อการจดจำ


11

คำตอบก่อนหน้านี้ส่วนใหญ่ล้างคำถามเกี่ยวกับสัญกรณ์สไลซ์

ไวยากรณ์การจัดทำดัชนีเพิ่มเติมที่ใช้สำหรับการแบ่งเป็นaList[start:stop:step]และตัวอย่างพื้นฐานคือ:

ป้อนคำอธิบายภาพที่นี่:

ตัวอย่างการตัดเพิ่มเติม: 15 ส่วนเพิ่มเติม


10

ใน Python รูปแบบพื้นฐานที่สุดสำหรับการแบ่งเป็นดังนี้:

l[start:end]

โดยที่lมีการรวบรวมstartเป็นดัชนีรวมและendเป็นดัชนีพิเศษ

In [1]: l = list(range(10))

In [2]: l[:5] # First five elements
Out[2]: [0, 1, 2, 3, 4]

In [3]: l[-5:] # Last five elements
Out[3]: [5, 6, 7, 8, 9]

เมื่อตัดจากจุดเริ่มต้นคุณสามารถละเว้นดัชนีเป็นศูนย์และเมื่อแบ่งเป็นจุดสิ้นสุดคุณสามารถละเว้นดัชนีสุดท้ายเนื่องจากซ้ำซ้อนจึงไม่ต้อง verbose:

In [5]: l[:3] == l[0:3]
Out[5]: True

In [6]: l[7:] == l[7:len(l)]
Out[6]: True

จำนวนเต็มลบมีประโยชน์เมื่อทำการชดเชยที่สัมพันธ์กับจุดสิ้นสุดของการรวบรวม:

In [7]: l[:-1] # Include all elements but the last one
Out[7]: [0, 1, 2, 3, 4, 5, 6, 7, 8]

In [8]: l[-3:] # Take the last three elements
Out[8]: [7, 8, 9]

เป็นไปได้ที่จะให้ดัชนีที่อยู่นอกขอบเขตเมื่อมีการแบ่งส่วนเช่น:

In [9]: l[:20] # 20 is out of index bounds, and l[20] will raise an IndexError exception
Out[9]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [11]: l[-20:] # -20 is out of index bounds, and l[-20] will raise an IndexError exception
Out[11]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

โปรดทราบว่าผลลัพธ์ของการแบ่งคอลเล็กชันเป็นคอลเล็กชันใหม่ทั้งหมด นอกจากนี้เมื่อใช้สัญกรณ์ชิ้นในการกำหนดความยาวของการกำหนดชิ้นไม่จำเป็นต้องเหมือนกัน ค่าก่อนและหลังชิ้นที่ได้รับมอบหมายจะถูกเก็บไว้และการรวบรวมจะลดขนาดหรือขยายเพื่อให้มีค่าใหม่:

In [16]: l[2:6] = list('abc') # Assigning fewer elements than the ones contained in the sliced collection l[2:6]

In [17]: l
Out[17]: [0, 1, 'a', 'b', 'c', 6, 7, 8, 9]

In [18]: l[2:5] = list('hello') # Assigning more elements than the ones contained in the sliced collection l [2:5]

In [19]: l
Out[19]: [0, 1, 'h', 'e', 'l', 'l', 'o', 6, 7, 8, 9]

หากคุณไม่ใช้ดัชนีเริ่มต้นและสิ้นสุดคุณจะทำสำเนาของคอลเล็กชัน:

In [14]: l_copy = l[:]

In [15]: l == l_copy and l is not l_copy
Out[15]: True

หากละเว้นดัชนีเริ่มต้นและสิ้นสุดเมื่อดำเนินการกำหนดเนื้อหาทั้งหมดของคอลเลกชันจะถูกแทนที่ด้วยสำเนาของสิ่งที่อ้างอิง:

In [20]: l[:] = list('hello...')

In [21]: l
Out[21]: ['h', 'e', 'l', 'l', 'o', '.', '.', '.']

นอกจากการแบ่งส่วนพื้นฐานแล้วยังสามารถใช้สัญลักษณ์ต่อไปนี้:

l[start:end:step]

โดยที่lคือคอลเล็กชันstartเป็นดัชนีแบบรวมendเป็นดัชนีพิเศษและstepเป็นขั้นตอนที่สามารถใช้เพื่อนำทุกรายการที่nเข้าlมา

In [22]: l = list(range(10))

In [23]: l[::2] # Take the elements which indexes are even
Out[23]: [0, 2, 4, 6, 8]

In [24]: l[1::2] # Take the elements which indexes are odd
Out[24]: [1, 3, 5, 7, 9]

การใช้stepเป็นเคล็ดลับที่มีประโยชน์ในการเก็บรวบรวมย้อนกลับใน Python:

In [25]: l[::-1]
Out[25]: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

นอกจากนี้ยังเป็นไปได้ที่จะใช้จำนวนเต็มลบเพื่อstepเป็นตัวอย่างต่อไปนี้:

In[28]:  l[::-2]
Out[28]: [9, 7, 5, 3, 1]

อย่างไรก็ตามการใช้ค่าลบสำหรับstepอาจทำให้สับสนมาก นอกจากนี้ในการที่จะPythonicคุณควรหลีกเลี่ยงการใช้start, endและstepในชิ้นเดียว ในกรณีนี้จำเป็นต้องพิจารณาการทำเช่นนี้ในสองงานที่ได้รับมอบหมาย (หนึ่งไปยังชิ้นและอื่น ๆ ที่จะก้าว)

In [29]: l = l[::2] # This step is for striding

In [30]: l
Out[30]: [0, 2, 4, 6, 8]

In [31]: l = l[1:-1] # This step is for slicing

In [32]: l
Out[32]: [2, 4, 6]

10

ฉันต้องการเพิ่มHello, World! ตัวอย่างที่อธิบายพื้นฐานของสไลซ์สำหรับผู้เริ่มต้น มันช่วยฉันได้มาก

มีรายการที่มีค่าหกค่า['P', 'Y', 'T', 'H', 'O', 'N']:

+---+---+---+---+---+---+
| P | Y | T | H | O | N |
+---+---+---+---+---+---+
  0   1   2   3   4   5

ตอนนี้ส่วนที่ง่ายที่สุดของรายการนั้นคือรายการย่อย สัญกรณ์คือ[<index>:<index>]และที่สำคัญคือการอ่านมันเช่นนี้:

[ start cutting before this index : end cutting before this index ]

ตอนนี้ถ้าคุณทำ[2:5]รายการด้านบนนี้จะเกิดขึ้น:

        |           |
+---+---|---+---+---|---+
| P | Y | T | H | O | N |
+---+---|---+---+---|---+
  0   1 | 2   3   4 | 5

คุณได้ทำการตัดก่อนองค์ประกอบดัชนี2และตัดอีกก่อน5องค์ประกอบที่มีค่าดัชนี ['T', 'H', 'O']ดังนั้นผลจะเป็นชิ้นระหว่างทั้งสองตัดเป็นรายการ


10

โดยส่วนตัวฉันคิดว่ามันเหมือนforวน:

a[start:end:step]
# for(i = start; i < end; i += step)

นอกจากนี้ทราบว่าค่าลบสำหรับstartและเป็นญาติกับส่วนท้ายของรายการและคำนวณได้ในตัวอย่างข้างต้นโดยendgiven_index + a.shape[0]


8

ด้านล่างเป็นตัวอย่างของดัชนีของสตริง:

 +---+---+---+---+---+
 | H | e | l | p | A |
 +---+---+---+---+---+
 0   1   2   3   4   5
-5  -4  -3  -2  -1

str="Name string"

ตัวอย่างการแบ่งส่วน: [start: end: step]

str[start:end] # Items start through end-1
str[start:]    # Items start through the rest of the array
str[:end]      # Items from the beginning through end-1
str[:]         # A copy of the whole array

ด้านล่างคือตัวอย่างการใช้งาน:

print str[0] = N
print str[0:2] = Na
print str[0:7] = Name st
print str[0:7:2] = Nm t
print str[0:-1:2] = Nm ti

5

len - indexถ้าคุณรู้สึกว่าดัชนีติดลบในหั่นเป็นความสับสนที่นี่เป็นวิธีที่ง่ายมากที่จะคิดเกี่ยวกับมันเพียงแค่เปลี่ยนดัชนีเชิงลบด้วย len(list) - 3ดังนั้นสำหรับตัวอย่างเช่นแทนที่ด้วย -3

วิธีที่ดีที่สุดในการแสดงให้เห็นว่าการแบ่งส่วนข้อมูลใดภายในเป็นการแสดงในโค้ดที่ใช้การดำเนินการนี้:

def slice(list, start = None, end = None, step = 1):
  # Take care of missing start/end parameters
  start = 0 if start is None else start
  end = len(list) if end is None else end

  # Take care of negative start/end parameters
  start = len(list) + start if start < 0 else start
  end = len(list) + end if end < 0 else end

  # Now just execute a for-loop with start, end and step
  return [list[i] for i in range(start, end, step)]

4

เทคนิคการแบ่งขั้นพื้นฐานคือการกำหนดจุดเริ่มต้นจุดหยุดและขนาดขั้นตอน - หรือที่เรียกว่าก้าวย่าง

ก่อนอื่นเราจะสร้างรายการค่าที่จะใช้ในการแบ่งส่วนของเรา

สร้างสองรายการเพื่อแบ่ง รายการแรกคือรายการตัวเลขตั้งแต่ 1 ถึง 9 (รายการ A) รายการที่สองเป็นรายการตัวเลขตั้งแต่ 0 ถึง 9 (รายการ B):

A = list(range(1, 10, 1)) # Start, stop, and step
B = list(range(9))

print("This is List A:", A)
print("This is List B:", B)

ทำดัชนีหมายเลข 3 จาก A และหมายเลข 6 จาก B

print(A[2])
print(B[6])

การแบ่งขั้นพื้นฐาน

ไวยากรณ์การจัดทำดัชนีเพิ่มเติมที่ใช้สำหรับการแบ่งเป็น aList [start: stop: step] อาร์กิวเมนต์เริ่มต้นและอาร์กิวเมนต์ขั้นตอนทั้งคู่ไม่มีค่าเริ่มต้น - อาร์กิวเมนต์ที่จำเป็นเท่านั้นคือหยุด คุณสังเกตเห็นว่าสิ่งนี้คล้ายคลึงกับช่วงที่ใช้ในการกำหนดรายการ A และ B หรือไม่ นี่เป็นเพราะวัตถุชิ้นแสดงชุดของดัชนีที่ระบุโดยช่วง (เริ่มหยุดขั้นตอน) เอกสาร Python 3.4

อย่างที่คุณเห็นการกำหนดหยุดเพียงแค่คืนค่าองค์ประกอบเดียว ตั้งแต่เริ่มต้นเริ่มต้นที่ไม่มีสิ่งนี้แปลเป็นการดึงองค์ประกอบเดียวเท่านั้น

มันเป็นสิ่งสำคัญที่จะต้องทราบองค์ประกอบแรกคือดัชนี 0 ไม่ใช่ดัชนี 1 นี่คือเหตุผลที่เราใช้ 2 รายการสำหรับการออกกำลังกายนี้ องค์ประกอบของรายการ A จะถูกกำหนดหมายเลขตามตำแหน่งอันดับ (องค์ประกอบแรกคือ 1 องค์ประกอบที่สองคือ 2 ฯลฯ ) ในขณะที่องค์ประกอบรายการของ B คือตัวเลขที่จะใช้ในการทำดัชนีองค์ประกอบเหล่านั้น ([0] สำหรับองค์ประกอบแรก 0 ฯลฯ )

ด้วยไวยากรณ์การจัดทำดัชนีแบบขยายเราเรียกช่วงของค่า ตัวอย่างเช่นค่าทั้งหมดจะถูกดึงด้วยโคลอน

A[:]

ในการเรียกชุดย่อยขององค์ประกอบจำเป็นต้องกำหนดตำแหน่งเริ่มต้นและหยุด

รับรูปแบบ aList [start: stop] ดึงสององค์ประกอบแรกจากรายการ A


3

ฉันไม่คิดว่าPython tutorial diagram (อ้างถึงในคำตอบอื่น ๆ อีกมากมาย) นั้นดีเพราะคำแนะนำนี้ใช้ได้กับการก้าวย่างที่ดี แต่ไม่เหมาะสำหรับการก้าวเดินเชิงลบ

นี่คือแผนภาพ:

 +---+---+---+---+---+---+
 | P | y | t | h | o | n |
 +---+---+---+---+---+---+
 0   1   2   3   4   5   6
-6  -5  -4  -3  -2  -1

จากแผนภาพที่ผมคาดหวังว่าa[-4,-6,-1]จะเป็นแต่มันเป็นyPty

>>> a = "Python"
>>> a[2:4:1] # as expected
'th'
>>> a[-4:-6:-1] # off by 1
'ty'

สิ่งที่ใช้งานได้เสมอคือคิดเป็นตัวละครหรือสล็อตและใช้การจัดทำดัชนีเป็นช่วงเวลาครึ่งเปิด - เปิดด้านขวาถ้าก้าวบวก, เปิดซ้ายถ้าก้าวย่างเชิงลบ

ด้วยวิธีนี้ฉันสามารถคิดa[-4:-6:-1]เป็นa(-6,-4]ในคำศัพท์ช่วงเวลา

 +---+---+---+---+---+---+
 | P | y | t | h | o | n |
 +---+---+---+---+---+---+
   0   1   2   3   4   5  
  -6  -5  -4  -3  -2  -1

 +---+---+---+---+---+---+---+---+---+---+---+---+
 | P | y | t | h | o | n | P | y | t | h | o | n |
 +---+---+---+---+---+---+---+---+---+---+---+---+
  -6  -5  -4  -3  -2  -1   0   1   2   3   4   5  
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.