最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python基礎(chǔ)指南之列表切片操作的高級(jí)應(yīng)用場(chǎng)景

 更新時(shí)間:2026年06月08日 09:23:16   作者:星河耀銀海  
切片操作可能是Python區(qū)別于其他編程語(yǔ)言最鮮明的特性之一,在Python中,一行 lst[2:8:2] 就能完成那些語(yǔ)言需要五六行代碼才能做到的事,本文會(huì)把切片的所有高級(jí)應(yīng)用場(chǎng)景一一拆解,希望對(duì)大家有所幫助

一、開(kāi)篇:切片是Python列表的核武器

今天我們要重點(diǎn)突破Python中最強(qiáng)大、最獨(dú)特的特性之一——切片(Slice)

切片操作可能是Python區(qū)別于其他編程語(yǔ)言最鮮明的特性之一。如果你用過(guò)Java或C++,你一定記得用循環(huán)提取子數(shù)組的繁瑣。而在Python中,一行 lst[2:8:2] 就能完成那些語(yǔ)言需要五六行代碼才能做到的事。

但切片遠(yuǎn)不止"取一段數(shù)據(jù)"這么簡(jiǎn)單。它可以原地修改列表的長(zhǎng)度、反轉(zhuǎn)序列、優(yōu)雅地處理邊界情況、實(shí)現(xiàn)高效的批量賦值。今天這篇文章,我會(huì)把切片的所有高級(jí)應(yīng)用場(chǎng)景一一拆解給你看。

二、切片的基礎(chǔ)回顧與深入理解

2.1 切片的完整語(yǔ)法

lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 完整語(yǔ)法:lst[start:stop:step]
# start:起始索引(包含),默認(rèn):step>0時(shí)為0,step<0時(shí)為-1
# stop:結(jié)束索引(不包含),默認(rèn):step>0時(shí)為len(lst),step<0時(shí)為-len(lst)-1
# step:步長(zhǎng),默認(rèn)1(不能為0)

# 從索引2到索引7(步長(zhǎng)為2)
print(lst[2:7:2])  # [2, 4, 6]

# 從索引8到索引2(反向步長(zhǎng)為2)
print(lst[8:2:-2])  # [8, 6, 4]

2.2 切片默認(rèn)值的完整規(guī)則

lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 當(dāng)step > 0(正向)時(shí):
# - start默認(rèn)值 = 0
# - stop默認(rèn)值 = len(lst)

# 以下等價(jià):
print(lst[0:10:1])  # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(lst[::1])     # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(lst[:])       # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(lst[0::1])    # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(lst[:10:1])   # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 當(dāng)step < 0(反向)時(shí):
# - start默認(rèn)值 = len(lst) - 1(即-1,最后一個(gè)元素)
# - stop默認(rèn)值 = -len(lst) - 1(即取到最前面)

# 以下等價(jià):
print(lst[::-1])    # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
print(lst[-1:-11:-1])  # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

2.3 切片參數(shù)的計(jì)算規(guī)則

# 理解切片中的索引計(jì)算
lst = [10, 20, 30, 40, 50, 60, 70, 80]
# 索引:0   1   2   3   4   5   6   7

# 規(guī)則:lst[start:stop:step] 包含索引 start, start+step, start+2*step, ...
# 直到達(dá)到或越過(guò) stop

# 例:lst[1:6:2]
# 索引序列:1, 1+2=3, 3+2=5 → 索引1, 3, 5
# 下一個(gè) 5+2=7 ≥ stop=6,停止
print(lst[1:6:2])  # [20, 40, 60]

# 例:lst[6:1:-2]
# 索引序列:6, 6-2=4, 4-2=2 → 索引6, 4, 2
# 下一個(gè) 2-2=0 ≤ stop=1,停止
print(lst[6:1:-2])  # [70, 50, 30]

# 核心記憶:step的正負(fù)決定方向,包含start不包含stop

三、切片的強(qiáng)大特性

3.1 切片不越界——這是最實(shí)用的特性

lst = [1, 2, 3, 4, 5]

# 無(wú)論start和stop有多大或多小,切片都不會(huì)報(bào)錯(cuò)
print(lst[0:100])     # [1, 2, 3, 4, 5](自動(dòng)截?cái)啵?
print(lst[-100:3])    # [1, 2, 3]
print(lst[10:20])     # [](start超出范圍,返回空列表)
print(lst[-10:-20])   # [](空范圍,返回空列表)
print(lst[100:0])     # [](start > stop,返回空列表)

# 這就是為什么切片比索引更適合處理邊界模糊的情況
# 索引訪問(wèn):越界就報(bào)錯(cuò)
# lst[100]  # IndexError

# 切片訪問(wèn):越界就截?cái)嗷蚍祷乜?,永不出錯(cuò)
# 這個(gè)特性讓很多邊界處理的代碼變簡(jiǎn)單了

3.2 切片創(chuàng)建的是淺拷貝

original = [1, 2, 3]
sliced = original[:]  # 創(chuàng)建副本

# 修改原列表不影響切片
original[0] = 999
print(original)  # [999, 2, 3]
print(sliced)    # [1, 2, 3]

# 但對(duì)于嵌套列表,內(nèi)層對(duì)象是共享的
nested = [[1, 2], [3, 4]]
copy_nested = nested[:]

nested[0][0] = 999
print(nested)       # [[999, 2], [3, 4]]
print(copy_nested)  # [[999, 2], [3, 4]](內(nèi)層共享?。?

# 如果需要完全獨(dú)立的副本,用copy.deepcopy
import copy
deep = copy.deepcopy(nested)
nested[0][0] = 111
print(nested)  # [[111, 2], [3, 4]]
print(deep)    # [[999, 2], [3, 4]](不受影響)

3.3 切片的獨(dú)立性——對(duì)切片賦值會(huì)影響原列表

# 用切片獲取一個(gè)視圖...等等,Python的切片返回的是新列表,不是視圖!
# 這一點(diǎn)和NumPy不一樣

lst = [1, 2, 3, 4, 5]
view = lst[1:4]  # 這是一個(gè)新列表!
view[0] = 999
print(lst)   # [1, 2, 3, 4, 5](原列表不變)
print(view)  # [999, 3, 4]

# 這一點(diǎn)和NumPy數(shù)組的行為不同
import numpy as np
arr = np.array([1, 2, 3, 4, 5])
arr_view = arr[1:4]  # NumPy的切片是視圖(共享底層數(shù)據(jù))
arr_view[0] = 999
print(arr)      # [  1 999   3   4   5](原數(shù)組也被改了?。?
print(arr_view) # [999   3   4]

# Python列表使用這種方式原地修改切片區(qū)域:
lst[1:4] = [999, 999, 999]
print(lst)  # [1, 999, 999, 999, 5](原列表被修改了)

這是Python列表和NumPy數(shù)組的一個(gè)重要區(qū)別。Python列表的切片總是創(chuàng)建新列表,而NumPy的切片是視圖。在數(shù)據(jù)科學(xué)領(lǐng)域切換時(shí)特別注意。

四、用切片原地修改列表

4.1 切片賦值:替換任意范圍的元素

nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 替換中間一段
nums[3:7] = [30, 40, 50, 60]
print(nums)  # [0, 1, 2, 30, 40, 50, 60, 7, 8, 9]

# 替換為更長(zhǎng)的序列——列表變長(zhǎng)!
nums[3:7] = [30, 40, 50, 60, 70, 80]
print(nums)  # [0, 1, 2, 30, 40, 50, 60, 70, 80, 7, 8, 9]

# 替換為更短的序列——列表變短!
nums[3:9] = [300]
print(nums)  # [0, 1, 2, 300, 7, 8, 9]

# 替換為空——?jiǎng)h除一段元素
nums[2:5] = []
print(nums)  # [0, 1, 7, 8, 9]

4.2 在任意位置插入元素

nums = [1, 5, 9]

# 在索引1處插入多個(gè)元素
nums[1:1] = [2, 3, 4]
print(nums)  # [1, 2, 3, 4, 5, 9]

# 在開(kāi)頭插入
nums[:0] = [-1, 0]
print(nums)  # [-1, 0, 1, 2, 3, 4, 5, 9]

# 在末尾插入
nums[len(nums):] = [10, 11]
print(nums)  # [-1, 0, 1, 2, 3, 4, 5, 9, 10, 11]

# 在中間插入
mid = len(nums) // 2
nums[mid:mid] = ['中']
print(nums)  # [-1, 0, 1, 2, 3, 4, '中', 5, 9, 10, 11]

4.3 刪除任意范圍的元素

nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 刪除前3個(gè)
nums[:3] = []
print(nums)  # [3, 4, 5, 6, 7, 8, 9]

# 刪除后3個(gè)
nums[-3:] = []
print(nums)  # [3, 4, 5, 6]

# 刪除偶數(shù)位置(每隔一個(gè))
nums[::2] = []
print(nums)  # [4, 6]

# 注意:`del lst[::2]` 和 `lst[::2] = []` 效果相同
nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
del nums[::2]
print(nums)  # [1, 3, 5, 7, 9]

4.4 帶步長(zhǎng)的切片賦值——有嚴(yán)格限制

nums = [0, 1, 2, 3, 4, 5]

# 帶步長(zhǎng)的切片賦值:右邊的長(zhǎng)度必須和切片結(jié)果長(zhǎng)度一致!
nums[::2] = [10, 20, 30]  # 3個(gè)元素對(duì)3個(gè)位置
print(nums)  # [10, 1, 20, 3, 30, 5]

# ? 長(zhǎng)度不匹配會(huì)報(bào)錯(cuò)
# nums[::2] = [10, 20]  # ValueError: attempt to assign sequence of size 2 to extended slice of size 3
# nums[::2] = [10, 20, 30, 40]  # ValueError

# 這個(gè)限制只在步長(zhǎng)≠1時(shí)存在
# 步長(zhǎng)為1的切片(lst[a:b])賦值不受此限,可以改變列表長(zhǎng)度

五、切片的實(shí)用技巧大全

5.1 反轉(zhuǎn)序列

# 方式一:[::-1](最常用)
lst = [1, 2, 3, 4, 5]
reversed_lst = lst[::-1]
print(reversed_lst)  # [5, 4, 3, 2, 1]

# 方式二:reversed()(返回迭代器,不創(chuàng)建新列表)
for item in reversed(lst):
    print(item, end=' ')  # 5 4 3 2 1
print()

# 方式三:list.reverse()(原地反轉(zhuǎn),不創(chuàng)建新列表)
lst.reverse()
print(lst)  # [5, 4, 3, 2, 1]

# 性能對(duì)比
# lst[::-1]:創(chuàng)建新列表,O(n)內(nèi)存
# lst.reverse():原地反轉(zhuǎn),O(1)額外內(nèi)存
# reversed(lst):懶迭代,O(1)額外內(nèi)存

# 反向字符串
text = 'hello world'
print(text[::-1])  # dlrow olleh

5.2 淺拷貝的多種寫法

original = [1, 2, 3, 4, 5]

# 三種等價(jià)的淺拷貝方式
copy1 = original[:]
copy2 = original.copy()
copy3 = list(original)

# 它們創(chuàng)建的都是淺拷貝
print(copy1 == copy2 == copy3)  # True
print(copy1 is original)        # False

# 哪種最快?實(shí)際測(cè)試:
import time

n = 1000000
lst = list(range(100))

start = time.perf_counter()
for _ in range(n):
    c = lst[:]
print(f'[:]      {time.perf_counter() - start:.3f}秒')

start = time.perf_counter()
for _ in range(n):
    c = lst.copy()
print(f'.copy()  {time.perf_counter() - start:.3f}秒')

start = time.perf_counter()
for _ in range(n):
    c = list(lst)
print(f'list()   {time.perf_counter() - start:.3f}秒')

# .copy()通常最快(因?yàn)槭侵苯拥腃方法調(diào)用),[:]次之,list()最慢

5.3 每隔N個(gè)取一個(gè)元素

lst = list(range(30))

# 每隔2個(gè)取一個(gè)(所有偶數(shù)索引)
print(lst[::2])
# [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28]

# 每隔3個(gè)取一個(gè)
print(lst[::3])
# [0, 3, 6, 9, 12, 15, 18, 21, 24, 27]

# 從第2個(gè)開(kāi)始,每隔4個(gè)取一個(gè)
print(lst[1::4])
# [1, 5, 9, 13, 17, 21, 25, 29]

# 實(shí)際應(yīng)用:對(duì)列表進(jìn)行降采樣
def downsample(lst, factor):
    """將列表降采樣為原來(lái)的1/factor"""
    return lst[::factor]

original = list(range(100))
reduced = downsample(original, 10)
print(reduced)  # [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]

5.4 批量交換元素位置

# 將列表的前半部分和后半部分互換
def swap_halves(lst):
    mid = len(lst) // 2
    # 注意:直接賦值會(huì)改變?cè)斜?
    lst[:] = lst[mid:] + lst[:mid]

nums = [1, 2, 3, 4, 5, 6]
swap_halves(nums)
print(nums)  # [4, 5, 6, 1, 2, 3]

# 循環(huán)左移k位
def rotate_left(lst, k):
    k %= len(lst)
    lst[:] = lst[k:] + lst[:k]

nums = [1, 2, 3, 4, 5, 6, 7]
rotate_left(nums, 2)
print(nums)  # [3, 4, 5, 6, 7, 1, 2]

# 循環(huán)右移k位
def rotate_right(lst, k):
    k %= len(lst)
    lst[:] = lst[-k:] + lst[:-k]

nums = [1, 2, 3, 4, 5, 6, 7]
rotate_right(nums, 2)
print(nums)  # [6, 7, 1, 2, 3, 4, 5]

5.5 列表"壓縮"——去除特定位置的元素

# 去除所有偶數(shù)索引位置的元素
lst = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
del lst[::2]
print(lst)  # ['b', 'd', 'f', 'h']

# 去除所有奇數(shù)索引位置的元素
lst = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
del lst[1::2]
print(lst)  # ['a', 'c', 'e', 'g']

# 保留前3個(gè)和后3個(gè),刪除中間的
lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
lst[3:-3] = []
print(lst)  # [0, 1, 2, 7, 8, 9]

六、切片的高級(jí)應(yīng)用場(chǎng)景

6.1 數(shù)據(jù)分頁(yè)

def paginate(items, page, page_size):
    """用切片實(shí)現(xiàn)數(shù)據(jù)分頁(yè)"""
    start = (page - 1) * page_size
    end = start + page_size
    return items[start:end]

# 模擬數(shù)據(jù)庫(kù)查詢結(jié)果
all_data = list(range(1, 101))  # 100條數(shù)據(jù)
page_size = 10

# 第1頁(yè)
print(f'第1頁(yè): {paginate(all_data, 1, page_size)}')
# 第3頁(yè)
print(f'第3頁(yè): {paginate(all_data, 3, page_size)}')
# 最后一頁(yè)(可能不滿一頁(yè))
print(f'第10頁(yè): {paginate(all_data, 10, page_size)}')

# 超出范圍返回空列表(不會(huì)報(bào)錯(cuò))
print(f'第20頁(yè): {paginate(all_data, 20, page_size)}')  # []


def paginate_with_info(items, page, page_size):
    """帶分頁(yè)信息的分頁(yè)"""
    total = len(items)
    total_pages = (total + page_size - 1) // page_size
    page = max(1, min(page, total_pages))

    start = (page - 1) * page_size
    end = min(start + page_size, total)

    return {
        'items': items[start:end],
        'page': page,
        'page_size': page_size,
        'total': total,
        'total_pages': total_pages,
        'has_prev': page > 1,
        'has_next': page < total_pages,
    }

info = paginate_with_info(all_data, 1, 10)
print(f'第{info["page"]}頁(yè)/共{info["total_pages"]}頁(yè)')
print(f'數(shù)據(jù): {info["items"]}')
print(f'有上一頁(yè): {info["has_prev"]}, 有下一頁(yè): {info["has_next"]}')

6.2 文本處理和截?cái)?/h3>
# 截?cái)嚅L(zhǎng)文本,加省略號(hào)
def truncate(text, max_length, ellipsis='...'):
    """用切片實(shí)現(xiàn)文本截?cái)?""
    if len(text) <= max_length:
        return text
    return text[:max_length - len(ellipsis)] + ellipsis

long_text = '這是一段很長(zhǎng)的文本內(nèi)容,我們需要將其截?cái)囡@示'
print(truncate(long_text, 15))  # 這是一段很長(zhǎng)的文本內(nèi)容,我...

# 提取摘要(取前N個(gè)字符)
def summary(text, n=100):
    return text[:n]

# 取文本的最后N行
def last_n_lines(text, n):
    lines = text.splitlines()
    return '\n'.join(lines[-n:])

log = '\n'.join(f'第{i}行日志:一切正常' for i in range(1, 101))
print(last_n_lines(log, 3))
# 第98行日志:一切正常
# 第99行日志:一切正常
# 第100行日志:一切正常

6.3 批量賦值模式

# 初始化部分元素
nums = [0] * 10
# 將前5個(gè)設(shè)為1
nums[:5] = [1] * 5
print(nums)  # [1, 1, 1, 1, 1, 0, 0, 0, 0, 0]

# 交替模式
nums = [0] * 10
nums[::2] = [1] * 5  # 偶數(shù)位為1
print(nums)  # [1, 0, 1, 0, 1, 0, 1, 0, 1, 0]

# 更復(fù)雜的模式——棋盤格
size = 8
row_template = [0] * size
row_template[::2] = [1] * (size // 2)
# row_template = [1, 0, 1, 0, 1, 0, 1, 0]

board = []
for i in range(size):
    if i % 2 == 0:
        board.append(row_template[:])
    else:
        board.append(row_template[::-1])

for row in board:
    print(' '.join('█' if c else ' ' for c in row))

6.4 螺旋遍歷矩陣

def spiral_order(matrix):
    """用切片實(shí)現(xiàn)矩陣的螺旋遍歷"""
    result = []
    while matrix:
        # 取第一行
        result.extend(matrix[0])
        # 去掉第一行,然后逆時(shí)針旋轉(zhuǎn)矩陣
        matrix = matrix[1:]
        if matrix:
            # 逆時(shí)針旋轉(zhuǎn) = 轉(zhuǎn)置 + 行反轉(zhuǎn)
            matrix = [list(row) for row in zip(*matrix)][::-1]
    return result

matrix = [
    [1,  2,  3,  4],
    [5,  6,  7,  8],
    [9, 10, 11, 12],
]
print(spiral_order(matrix))
# [1, 2, 3, 4, 8, 12, 11, 10, 9, 5, 6, 7]

七、切片對(duì)象——可復(fù)用的切片

7.1 使用slice()創(chuàng)建切片對(duì)象

# slice(start, stop, step)創(chuàng)建切片對(duì)象
s = slice(2, 8, 2)
print(s)  # slice(2, 8, 2)

lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(lst[s])  # [2, 4, 6](和lst[2:8:2]完全一樣)

# 切片對(duì)象可以復(fù)用
data1 = list(range(100))
data2 = list(range(100, 200))
data3 = list(range(200, 300))

# 定義好切片規(guī)則,到處使用
first_half = slice(None, 50)     # 等價(jià)于 [:50]
last_quarter = slice(-25, None)  # 等價(jià)于 [-25:]
every_10th = slice(None, None, 10)  # 等價(jià)于 [::10]

print(data1[first_half])
print(data2[last_quarter])
print(data3[every_10th])

7.2 切片對(duì)象的屬性

s = slice(2, 10, 3)
print(s.start)  # 2
print(s.stop)   # 10
print(s.step)   # 3

# indices()方法:根據(jù)序列長(zhǎng)度規(guī)范化切片參數(shù)
lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(s.indices(len(lst)))  # (2, 10, 3)
# 這意味著實(shí)際提取的是索引2, 5, 8

# 當(dāng)切片參數(shù)超出范圍時(shí),indices()會(huì)自動(dòng)修正
s2 = slice(5, 100, 2)
print(s2.indices(10))  # (5, 10, 2)(stop從100修正為10)

s3 = slice(-100, 3, 1)
print(s3.indices(10))  # (0, 3, 1)(start從-100修正為0)

# 用indices()實(shí)現(xiàn)自己的安全切片操作
def my_slice(sequence, slice_obj):
    """使用slice對(duì)象的通用安全切片"""
    start, stop, step = slice_obj.indices(len(sequence))
    result = []
    i = start
    if step > 0:
        while i < stop:
            result.append(sequence[i])
            i += step
    else:
        while i > stop:
            result.append(sequence[i])
            i += step
    return type(sequence)(result) if hasattr(type(sequence), '__call__') else result

7.3 切片在自定義類中的應(yīng)用

class DataSeries:
    """自定義的數(shù)據(jù)庫(kù)列——演示如何支持切片操作"""

    def __init__(self, data):
        self._data = list(data)

    def __getitem__(self, key):
        """支持索引和切片"""
        if isinstance(key, slice):
            # 可以用indices()規(guī)范化切片參數(shù)
            start, stop, step = key.indices(len(self._data))
            result = [self._data[i] for i in range(start, stop, step)]
            return DataSeries(result)
        elif isinstance(key, int):
            return self._data[key]
        else:
            raise TypeError(f'不支持的索引類型:{type(key)}')

    def __setitem__(self, key, value):
        """支持索引賦值和切片賦值"""
        if isinstance(key, slice):
            self._data[key] = value
        elif isinstance(key, int):
            self._data[key] = value
        else:
            raise TypeError(f'不支持的索引類型:{type(key)}')

    def __delitem__(self, key):
        """支持通過(guò)切片刪除"""
        if isinstance(key, slice):
            del self._data[key]
        elif isinstance(key, int):
            del self._data[key]

    def __len__(self):
        return len(self._data)

    def __repr__(self):
        return f'DataSeries({self._data})'


ds = DataSeries([10, 20, 30, 40, 50, 60, 70, 80, 90, 100])

# 使用切片
print(ds[2:5])       # DataSeries([30, 40, 50])
print(ds[::2])       # DataSeries([10, 30, 50, 70, 90])
print(ds[::-1])      # DataSeries([100, 90, 80, 70, 60, 50, 40, 30, 20, 10])

# 切片賦值
ds[2:5] = [300, 400, 500]
print(ds)  # DataSeries([10, 20, 300, 400, 500, 60, 70, 80, 90, 100])

# 切片刪除
del ds[3:7]
print(ds)  # DataSeries([10, 20, 300, 70, 80, 90, 100])

八、切片的性能與陷阱

8.1 切片的內(nèi)存消耗

import sys

# 切片總是創(chuàng)建新列表——對(duì)大列表會(huì)導(dǎo)致內(nèi)存翻倍
large_list = list(range(10000000))  # 1000萬(wàn)元素

# 取一小段也會(huì)創(chuàng)建新列表(雖然只包含幾個(gè)元素)
small_slice = large_list[1000:1010]
print(f'原列表大小: {sys.getsizeof(large_list):,} 字節(jié)')
print(f'切片大小: {sys.getsizeof(small_slice):,} 字節(jié)')

# 如果只需要遍歷,不需要切片
# 不推薦(創(chuàng)建新列表)
for item in large_list[1000:1010]:
    print(item)

# 推薦(用islice避免創(chuàng)建新列表)
from itertools import islice
for item in islice(large_list, 1000, 1010):
    print(item)

8.2 切片的常見(jiàn)陷阱

# 陷阱一:忘記切片是淺拷貝
original = [[0]] * 5
copy = original[:]
copy[0][0] = 999
print(original)  # [[999], [999], [999], [999], [999]](所有元素都變了?。?
print(copy)      # [[999], [999], [999], [999], [999]]

# 陷阱二:對(duì)切片賦值 vs 對(duì)切片變量賦值
lst = [1, 2, 3, 4, 5]
s = lst[1:4]   # s是一個(gè)新列表
s[0] = 100     # 修改s不影響lst
print(lst)     # [1, 2, 3, 4, 5](lst沒(méi)變)

lst[1:4] = [100, 100, 100]  # 這是切片賦值,修改lst本身
print(lst)     # [1, 100, 100, 100, 5]

# 陷阱三:帶步長(zhǎng)的切片賦值長(zhǎng)度必須匹配
lst = [0, 1, 2, 3, 4, 5]
# lst[::2] = [10, 20]  # ValueError(3個(gè)位置但只給了2個(gè)值)

# 陷阱四:負(fù)數(shù)步長(zhǎng)時(shí)start應(yīng)大于stop
lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(lst[2:8:2])   # [2, 4, 6](正確)
print(lst[8:2:-2])  # [8, 6, 4](正確)
print(lst[2:8:-2])  # [](空!start < stop,反向步長(zhǎng)取不到值)

# 陷阱五:給切片賦值的右邊不一定是列表
lst = [1, 2, 3, 4, 5]
lst[1:4] = 'XYZ'  # 字符串被拆為字符序列
print(lst)  # [1, 'X', 'Y', 'Z', 5]

lst[1:4] = range(100, 103)  # range也是可迭代對(duì)象
print(lst)  # [1, 100, 101, 102, 5]

九、綜合實(shí)戰(zhàn):用切片優(yōu)雅解決實(shí)際問(wèn)題

9.1 回文判斷

def is_palindrome(s):
    """用切片判斷回文"""
    # 去掉非字母數(shù)字字符,統(tǒng)一小寫
    cleaned = ''.join(c.lower() for c in s if c.isalnum())
    return cleaned == cleaned[::-1]

print(is_palindrome('A man, a plan, a canal: Panama'))  # True
print(is_palindrome('race a car'))                      # False
print(is_palindrome('上海自來(lái)水來(lái)自海上'))              # True

9.2 楊輝三角

def pascal_triangle(n):
    """生成楊輝三角——用切片輕松實(shí)現(xiàn)"""
    result = [[1]]
    for _ in range(1, n):
        prev = result[-1]
        # 核心:每行前后補(bǔ)0,相鄰元素相加
        current = [1] + [prev[i] + prev[i + 1] for i in range(len(prev) - 1)] + [1]
        result.append(current)
    return result

# 更Pythonic的寫法(用切片)
def pascal_triangle_v2(n):
    result = [[1]]
    for _ in range(1, n):
        prev = [0] + result[-1] + [0]
        current = [prev[i] + prev[i + 1] for i in range(len(prev) - 1)]
        result.append(current)
    return result

for row in pascal_triangle_v2(8):
    print(' '.join(f'{x:3d}' for x in row).center(40))

9.3 格式化輸出對(duì)齊

def format_columns(data, col_widths):
    """用切片分列展示數(shù)據(jù)"""
    result = []
    for row in data:
        formatted = [str(cell)[:w].ljust(w) for cell, w in zip(row, col_widths)]
        result.append(' | '.join(formatted))
    return '\n'.join(result)

headers = ['姓名', '年齡', '城市', '職業(yè)']
rows = [
    ['小明', 25, '北京', '軟件工程師'],
    ['小紅', 23, '上海', 'UI設(shè)計(jì)師'],
    ['Alexander Hamilton', 26, '廣州', '數(shù)據(jù)科學(xué)家'],
]

# 計(jì)算列寬
col_widths = []
for i in range(len(headers)):
    max_w = max(len(str(row[i])) for row in [headers] + rows)
    col_widths.append(max_w + 2)

print(format_columns([headers] + rows, col_widths))

十、本篇小結(jié)

切片是Python中最強(qiáng)大、最常用的序列操作工具:

  1. 完整語(yǔ)法lst[start:stop:step],三個(gè)參數(shù)都可以省略,默認(rèn)值根據(jù)step的正負(fù)確定
  2. 永不越界:切片訪問(wèn)永遠(yuǎn)不會(huì)報(bào)IndexError,越界自動(dòng)截?cái)?mdash;—這是它和索引訪問(wèn)的關(guān)鍵區(qū)別
  3. 原地修改lst[a:b] = values可以增刪改列表元素,lst[a:a] = values在任意位置插入,lst[a:b] = []刪除一段
  4. 淺拷貝lst[:]創(chuàng)建新列表,但內(nèi)層對(duì)象共享(嵌套列表要注意)
  5. 切片對(duì)象slice(start, stop, step)可復(fù)用切片規(guī)則,.indices(len)規(guī)范化參數(shù)
  6. 帶步長(zhǎng)的切片賦值:右邊長(zhǎng)度必須和切片結(jié)果長(zhǎng)度一致

切片操作是Python編程中的"基本功",但用好了就是"殺手锏"。熟練運(yùn)用切片可以讓你的代碼減少一半的循環(huán)和條件判斷。下一篇我們將進(jìn)入列表的增刪改查方法詳解——從增加元素的四大方式開(kāi)始。

到此這篇關(guān)于Python基礎(chǔ)指南之列表切片操作的高級(jí)應(yīng)用場(chǎng)景的文章就介紹到這了,更多相關(guān)Python列表切片內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • python項(xiàng)目--使用Tkinter的日歷GUI應(yīng)用程序

    python項(xiàng)目--使用Tkinter的日歷GUI應(yīng)用程序

    在 Python 中,我們可以使用 Tkinter 制作 GUI。如果你非常有想象力和創(chuàng)造力,你可以用 Tkinter 做出很多有趣的東西,希望本篇文章能夠幫到你
    2021-08-08
  • 解決Python內(nèi)層for循環(huán)如何break出外層的循環(huán)的問(wèn)題

    解決Python內(nèi)層for循環(huán)如何break出外層的循環(huán)的問(wèn)題

    今天小編就為大家分享一篇解決Python內(nèi)層for循環(huán)如何break出外層的循環(huán)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-06-06
  • OpenCV實(shí)戰(zhàn)記錄之基于分水嶺算法的圖像分割

    OpenCV實(shí)戰(zhàn)記錄之基于分水嶺算法的圖像分割

    在機(jī)器視覺(jué)中,有時(shí)需要對(duì)產(chǎn)品進(jìn)行檢測(cè)和計(jì)數(shù),其難點(diǎn)無(wú)非是對(duì)于產(chǎn)品的圖像分割,這篇文章主要給大家介紹了關(guān)于OpenCV實(shí)戰(zhàn)記錄之基于分水嶺算法的圖像分割的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • Python遞歸實(shí)現(xiàn)漢諾塔算法示例

    Python遞歸實(shí)現(xiàn)漢諾塔算法示例

    這篇文章主要介紹了Python遞歸實(shí)現(xiàn)漢諾塔算法,結(jié)合實(shí)例形式分析了漢諾塔算法的原理、實(shí)現(xiàn)步驟與相關(guān)操作技巧,需要的朋友可以參考下
    2018-03-03
  • python實(shí)現(xiàn)布隆過(guò)濾器及原理解析

    python實(shí)現(xiàn)布隆過(guò)濾器及原理解析

    布隆過(guò)濾器( BloomFilter )是一種數(shù)據(jù)結(jié)構(gòu),比較巧妙的概率型數(shù)據(jù)結(jié)構(gòu)(probabilistic data structure),特點(diǎn)是高效地插入和查詢,可以用來(lái)告訴你 “某樣?xùn)|西一定不存在或者可能存在”。這篇文章主要介紹了python實(shí)現(xiàn)布隆過(guò)濾器 ,需要的朋友可以參考下
    2019-12-12
  • python實(shí)現(xiàn)固定尺寸圖像拼接

    python實(shí)現(xiàn)固定尺寸圖像拼接

    這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)固定尺寸圖像拼接,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-04-04
  • Python?matplotlib?seaborn繪圖教程詳解

    Python?matplotlib?seaborn繪圖教程詳解

    Seaborn是在matplotlib的基礎(chǔ)上進(jìn)行了更高級(jí)的API封裝,從而使得作圖更加容易,在大多數(shù)情況下使用seaborn就能做出很具有吸引力的圖。本文將詳細(xì)講解如何利用Seaborn繪制圖表,需要的可以參考一下
    2022-03-03
  • 跟老齊學(xué)Python之dict()的操作方法

    跟老齊學(xué)Python之dict()的操作方法

    這篇文章主要介紹了dict()的操作方法,由于dict的很多方法跟list類似,所以在詳細(xì)介紹dict的同時(shí),也跟list做了對(duì)比,是篇非常不錯(cuò)的文章,有需要的朋友參考下
    2014-09-09
  • Python中如何自定義函數(shù)

    Python中如何自定義函數(shù)

    這篇文章主要介紹了Python中如何自定義函數(shù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • Django ORM filter() 的運(yùn)用詳解

    Django ORM filter() 的運(yùn)用詳解

    這篇文章主要介紹了Django ORM filter() 的運(yùn)用詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-05-05

最新評(píng)論

上犹县| 梓潼县| 江都市| 嘉义市| 衢州市| 晴隆县| 全州县| 留坝县| 灵寿县| 普洱| 嵊泗县| 五河县| 青岛市| 罗平县| 怀柔区| 任丘市| 黑龙江省| 专栏| 子长县| 酉阳| 吕梁市| 基隆市| 仁怀市| 随州市| 海宁市| 汽车| 江永县| 潜山县| 昌都县| 元阳县| 丽水市| 屯昌县| 饶河县| 根河市| 左贡县| 突泉县| 宜良县| 达拉特旗| 三原县| 高要市| 临夏县|