學習日志39 python

1?fromkeys()函數是什么

在 Python 中,fromkeys()?是字典(dict)的一個類方法,用于創建一個新字典。

它的作用是:根據指定的可迭代對象(如列表、元組等)中的元素作為鍵(key),并為所有鍵設置一個默認的初始值(value),從而快速創建一個新字典。

語法格式:

python

運行

dict.fromkeys(iterable, value=None)

  • 參數說明

    • iterable:必需參數,一個可迭代對象(如列表、元組、字符串等),其元素將作為新字典的鍵。
    • value可選參數,為所有鍵設置的默認值,默認為?None
  • 返回值:一個新的字典。

示例:

python

運行

# 用列表作為可迭代對象,創建新字典,默認值為 None
keys = ['name', 'age', 'gender']
new_dict = dict.fromkeys(keys)
print(new_dict)  # 輸出: {'name': None, 'age': None, 'gender': None}# 為所有鍵設置相同的初始值
new_dict2 = dict.fromkeys(keys, 'unknown')
print(new_dict2)  # 輸出: {'name': 'unknown', 'age': 'unknown', 'gender': 'unknown'}# 用字符串作為可迭代對象
str_keys = 'abc'
new_dict3 = dict.fromkeys(str_keys, 0)
print(new_dict3)  # 輸出: {'a': 0, 'b': 0, 'c': 0}

注意事項:

如果?value?是可變對象(如列表、字典等),則所有鍵會共享同一個對象的引用,修改其中一個鍵的值會影響其他鍵。例如:

python

運行

keys = ['a', 'b', 'c']
value = []  # 可變對象
my_dict = dict.fromkeys(keys, value)my_dict['a'].append(1)
print(my_dict)  # 輸出: {'a': [1], 'b': [1], 'c': [1]}

此時所有鍵的值都會被修改,因為它們指向同一個列表對象。如果需要避免這種情況,通常需要用其他方式(如循環)為每個鍵創建獨立的可變對象。

=> 如果希望每個鍵對應不同的初始值(尤其是可變對象)的做法

如果希望每個鍵對應不同的初始值(尤其是可變對象),可以通過循環遍歷鍵列表,為每個鍵單獨賦值。這樣能確保每個值都是獨立的對象,修改其中一個不會影響其他。

方法 1:使用普通 for 循環

python

運行

keys = ['a', 'b', 'c']
my_dict = {}# 為每個鍵設置不同的初始值(這里用索引區分)
for i, key in enumerate(keys):my_dict[key] = [i]  # 每個鍵對應一個獨立的列表print(my_dict)  # 輸出: {'a': [0], 'b': [1], 'c': [2]}# 修改其中一個值,其他不受影響
my_dict['a'].append(100)
print(my_dict)  # 輸出: {'a': [0, 100], 'b': [1], 'c': [2]}

方法 2:使用字典推導式(更簡潔)

字典推導式可以一行代碼實現上述功能,適合簡單場景:

python

運行

keys = ['a', 'b', 'c']# 為每個鍵設置不同的值(例如基于鍵名的處理)
my_dict = {key: [key.upper()] for key in keys}print(my_dict)  # 輸出: {'a': ['A'], 'b': ['B'], 'c': ['C']}# 修改一個值,其他不變
my_dict['a'].append('first')
print(my_dict)  # 輸出: {'a': ['A', 'first'], 'b': ['B'], 'c': ['C']}

方法 3:根據條件動態生成不同值

如果值的差異更復雜(比如依賴外部數據),可以結合條件判斷:

python

運行

keys = ['a', 'b', 'c']
values = [10, 20, 30]  # 提前準備好對應的值列表# 用zip配對鍵和值
my_dict = {k: [v] for k, v in zip(keys, values)}print(my_dict)  # 輸出: {'a': [10], 'b': [20], 'c': [30]}

核心原理:

通過循環或推導式,為每個鍵單獨創建新對象(如[i][key.upper()]),而不是讓所有鍵共享同一個對象引用。這樣無論值是列表、字典等可變對象,修改時都不會相互影響。

2?pop()?

pop() 函數的作用是默認刪除最后一個元素,并返回刪除的元素的值。

在 Python 中,pop()?是列表(list)的一個常用方法,其主要作用是:

  1. 默認刪除列表中的最后一個元素
  2. 返回被刪除的元素的值

基本語法:

python

運行

list.pop(index=-1)
  • index?是可選參數,默認值為?-1(即最后一個元素的索引)
  • 如果指定了有效的索引,就會刪除該索引位置的元素并返回它

示例:

python

運行

# 示例1:默認刪除最后一個元素
fruits = ['apple', 'banana', 'cherry']
last_fruit = fruits.pop()
print(last_fruit)  # 輸出: 'cherry'
print(fruits)      # 輸出: ['apple', 'banana']# 示例2:指定索引刪除元素
numbers = [10, 20, 30, 40]
removed = numbers.pop(1)  # 刪除索引為1的元素(20)
print(removed)     # 輸出: 20
print(numbers)     # 輸出: [10, 30, 40]

注意:

  • 如果列表為空,調用?pop()?會拋出?IndexError?錯誤
  • 如果指定的索引超出列表范圍,也會拋出?IndexError?錯誤

除了列表,字典(dict)也有?pop()?方法,但功能不同:字典的?pop(key)?是根據指定的鍵刪除鍵值對,并返回對應的值。

3?正則表達式(re模塊)

正則表達式(re模塊)是 Python 中非常重要且實用的工具,尤其在文本處理場景中幾乎不可或缺。如果你經常需要處理字符串(比如提取信息、驗證格式、替換內容等),系統學習re模塊會讓你效率翻倍。

為什么re模塊重要?

  1. 文本處理的 “瑞士軍刀”
    無論是爬蟲提取數據、日志分析、表單驗證(如郵箱 / 手機號格式),還是字符串清洗,正則表達式都能通過簡潔的模式完成復雜操作。
    例如:用一行正則快速提取文本中所有郵箱地址,比用字符串方法(split/find等)簡潔得多。

  2. 跨語言通用能力
    正則表達式的語法在 Python、Java、JavaScript 等主流語言中高度一致,學會后能遷移到其他場景。

  3. 簡化復雜邏輯
    很多字符串處理如果不用正則,可能需要寫十幾行循環判斷,而正則只需一個模式字符串。

如何入門re模塊?

不需要一開始就掌握所有細節,先學核心功能即可:

  1. 基礎匹配規則

    • .*??非貪婪匹配(如題目中的用法)
    • \d?匹配數字,\w?匹配字母 / 數字 / 下劃線
    • ^?開頭,$?結尾(用于嚴格驗證格式)
    • ()?捕獲組(用于提取特定部分,如題目中的group(2)
  2. 常用方法

    • re.search():查找第一個匹配(如題目中的用法)
    • re.findall():查找所有匹配并返回列表
    • re.sub():替換匹配的內容
    • re.match():從字符串開頭匹配(與search的區別)
  3. 實戰練習
    從簡單例子入手,比如:

    • 提取字符串中的所有數字
    • 驗證手機號格式(^1[3-9]\d{9}$
    • 替換文本中的敏感詞

舉個簡單例子理解 “捕獲組”

題目中的(.*) are (.*?) .*其實是用()定義了兩個 “捕獲組”,就像給需要提取的部分 “打標簽”:

  • 第一個(.*)?標簽 1:匹配 “are” 前面的內容(Cats)
  • 第二個(.*?)?標簽 2:匹配 “are” 后面的內容(smarter)

通過group(1)group(2)就能直接拿到這些 “標簽” 對應的內容,這就是正則提取信息的核心邏輯。

如果后續經常用到文本處理,建議花 1-2 天系統學一下基礎語法,之后遇到具體問題再查文檔補充。入門后你會發現,很多之前覺得復雜的字符串操作會變得非常簡單~

4 Python的多態

【Python的多態可通過鴨子類型(Duck Typing) 實現,即不依賴繼承,這一點是不是和強類型語言c,java是反的?】

你的理解有一定道理,但更準確地說,這是動態類型語言(如 Python)與靜態強類型語言(如 C、Java)在多態實現方式上的差異,而非完全 “相反”。

核心區別在于:

  1. Python(動態類型)的鴨子類型
    不要求顯式的繼承關系或接口實現,只關注對象是否具有所需的方法 / 屬性。
    例如,只要一個對象有fly()方法,就可以被當作 “會飛的東西” 來使用,無論它是否繼承自Bird類:

    python

    運行

    class Duck:def fly(self):print("鴨子飛")class Plane:def fly(self):print("飛機飛")def make_fly(obj):obj.fly()  # 只要有fly()方法就能調用make_fly(Duck())  # 可行
    make_fly(Plane())  # 也可行
    
  2. Java/C#(靜態強類型)的多態
    依賴繼承關系接口實現,編譯器會嚴格檢查類型兼容性。
    例如,要讓make_fly方法接收不同對象,必須讓它們實現同一個接口:

    java

    運行

    // 必須定義接口
    interface Flyable {void fly();
    }class Duck implements Flyable {public void fly() { ... }
    }class Plane implements Flyable {public void fly() { ... }
    }// 方法參數必須聲明為接口類型
    void makeFly(Flyable obj) {obj.fly();
    }
    
  3. C 語言
    本身沒有面向對象的多態特性,需要通過函數指針、結構體模擬,本質是手動實現類型適配,與上述兩種方式都不同。(想當然的以為也有,都不是opp了......倒是像文盲了哈哈哈)

本質差異:

  • 動態類型語言:多態是 “隱式” 的,由運行時對象的能力決定(鴨子類型)。
  • 靜態強類型語言:多態是 “顯式” 的,由編譯時的類型聲明 / 繼承關系保證。

這兩種方式沒有絕對優劣:

  • 鴨子類型更靈活,代碼簡潔,但可能在運行時才暴露類型錯誤;
  • 接口 / 繼承方式更嚴謹,編譯期即可發現問題,但需要寫更多聲明代碼。

5 什么叫可調用對象?關于對內存空間的理解

類似的開辟了幾個內存空間,我也沒有搞得很清楚....../(ㄒoㄒ)/

一、什么是可調用對象?

在 Python 中,可調用對象(Callable)?指的是可以像函數一樣被調用的對象,即可以在對象后面加括號?()?并傳入參數來執行的對象。

常見的可調用對象類型:
  1. 函數(def 定義的普通函數)

    python

    運行

    def add(a, b):return a + b
    add(1, 2)  # 調用函數,返回 3 → add 是可調用對象
    

  2. lambda 表達式(匿名函數)

    python

    運行

    multiply = lambda x, y: x * y
    multiply(3, 4)  # 調用 lambda,返回 12 → multiply 是可調用對象
    
  3. 類(實例化時會調用?__init__?方法)

    python

    運行

    class Person:def __init__(self, name):self.name = name
    p = Person("Alice")  # 調用類創建實例 → Person 是可調用對象
    
  4. 類的實例(如果類定義了?__call__?方法)

    python

    運行

    class Counter:def __init__(self):self.count = 0def __call__(self):  # 定義 __call__ 方法后,實例可被調用self.count += 1return self.count
    c = Counter()
    print(c())  # 調用實例,返回 1 → c 是可調用對象
    print(c())  # 再調用,返回 2
    
  5. 其他(如內置函數?print、方法?list.append?等)

    python

    運行

    print("Hello")  # print 是可調用對象
    [1,2].append(3)  # append 方法是可調用對象
    
判斷是否為可調用對象:

用?callable()?函數判斷:

python

運行

print(callable(add))  # True(函數可調用)
print(callable(Person))  # True(類可調用)
print(callable(123))  # False(數字不可調用)

二、關于 “內存空間” 的理解

變量、對象、函數等在內存中都會占用空間,不同類型的對象占用的空間和存儲方式不同,這里用簡單例子說明:

1. 變量與對象的內存關系
  • 對象:在內存中實際存儲數據的實體(如數字、字符串、列表、函數等)。
  • 變量:指向對象的 “標簽”,本身不存儲數據,只記錄對象在內存中的地址。

python

運行

a = 100  # 100 是一個整數對象,在內存中占據一塊空間;a 是變量,指向這塊空間
b = a    # b 也指向 100 所在的內存空間(不新開辟空間)
2. 不同對象的內存占用示例
  • 簡單類型(int、str 等):創建時開辟一塊內存。

    python

    運行

    x = "hello"  # 開辟一塊內存存 "hello",x 指向它
    y = "world"  # 再開辟一塊內存存 "world",y 指向它
    
  • 容器類型(list、dict 等):容器本身和內部元素都占內存。

    python

    運行

    lst = [1, 2, 3]  # 1. 開辟一塊內存存列表本身(記錄元素的地址)# 2. 分別開辟內存存 1、2、3 三個整數對象
    
  • 函數 / 類(可調用對象):定義時就會在內存中創建對應的對象。

    python

    運行

    def func():  # 定義函數時,內存中創建一個函數對象,func 指向它pass
    
3. 關鍵結論
  • 每個獨立的對象(如不同的字符串、列表、函數)都會開辟獨立的內存空間。
  • 多個變量可以指向同一個對象(此時共享一塊內存,不重復開辟)。
  • 可調用對象(如函數、類)也是對象的一種,定義時會在內存中分配空間,變量指向它們。

總結

  • 可調用對象:能加?()?調用的對象(函數、類、帶?__call__?的實例等)。
  • 內存空間:每個獨立對象占一塊空間,變量只是指向對象的 “指針”,多個變量可共享同一對象的內存。

通過?id()?函數可以查看對象的內存地址(唯一標識),幫助理解:

python

運行

a = 10
b = a
print(id(a), id(b))  # 輸出相同的地址(a 和 b 指向同一對象)

6 鏈式比較和邏輯運算or(以及其他Python 中容易混淆的運算符特性)

下列Python3代碼的運行結果是()
print('a' < 'b' < 'c')
A a
B b
C c
D True
E False
正確答案:D
你的答案:C#我之前做or不是返回操作數本身嗎??!!

你混淆了兩種不同的運算符行為:

  1. 比較運算符的鏈式判斷
    Python 支持類似?a < b < c?的鏈式比較,等價于?a < b and b < c,返回的是布爾值(True?或?False)。
    題目中?'a' < 'b' < 'c'?是字符的 ASCII 碼比較(a?的 ASCII 碼是 97,b?是 98,c?是 99),顯然?97 < 98 < 99?成立,所以結果為?True

  2. 邏輯運算符?or?的特性
    你提到的 “返回操作數本身” 是?or?的行為:or?會返回第一個為 “真” 的值(如果所有值都為假,則返回最后一個值)。例如:

    python

    運行

    print(0 or 'a' or 'b')  # 輸出 'a'(第一個真值)
    print('a' or 'b')       # 輸出 'a'
    

這是兩種完全不同的語法:

  • 鏈式比較(a < b < c)返回布爾值
  • 邏輯運算?or?返回第一個真值

所以題目中是比較運算,結果為?True(選項 D)。

為了避免混淆各類運算符的行為,這里整理了 Python 中容易混淆的運算符特性及對比小結

一、比較運算符(==!=><>=<=

  1. 基本作用:比較兩個值的關系,返回布爾值(True/False

    python

    運行

    print(2 == 2)  # True
    print(3 > 5)   # False
    
  2. 特殊:鏈式比較
    支持?a < b < c?這樣的連續比較,等價于?a < b and b < c最終返回布爾值

    python

    運行

    print(1 < 2 < 3)  # 等價于 1<2 and 2<3 → True
    print('x' > 'y' > 'z')  # 字符按ASCII碼比較 → False
    

二、邏輯運算符(andornot

  1. not:邏輯非,返回布爾值

    python

    運行

    print(not True)   # False
    print(not 0)      # True(0為假值)
    
  2. and:邏輯與

    • 若第一個值為,返回第一個值
    • 若第一個值為,返回第二個值(不會返回布爾值,除非操作數本身是布爾值)。

    python

    運行

    print(0 and 5)    # 0(第一個值為假,返回0)
    print(3 and 5)    # 5(第一個值為真,返回第二個值)
    print(True and False)  # False(操作數是布爾值,返回布爾值)
    
  3. or:邏輯或

    • 若第一個值為,返回第一個值
    • 若第一個值為,返回第二個值(同樣可能返回非布爾值)。

    python

    運行

    print(0 or 5)     # 5(第一個值為假,返回第二個值)
    print(3 or 5)     # 3(第一個值為真,返回第一個值)
    print(False or True)  # True(操作數是布爾值,返回布爾值)
    

三、常見混淆點對比

表達式類型運算邏輯返回值類型示例結果

單個比較

a < b

判斷關系布爾值(True/False'a' < 'b'True

鏈式比較

a < b < c

等價于?a < b and b < c布爾值1 < 3 < 2False
and?運算取第一個假值,無假值則取最后一個值

操作數本身

(或布爾值)

'a' and '' and 'b'''
or?運算取第一個真值,無真值則取最后一個值

操作數本身

(或布爾值)

'' or 'a' or 'b''a'

四、記憶技巧

  1. 比較運算(包括鏈式):最終都是 “判斷對錯”,所以返回布爾值。
  2. and/or:更像 “篩選值”,返回的是參與運算的原始值(除非原始值本身是布爾值)。
    • and?可以理解為 “找第一個不對勁的值”(假值)找不到就返回最后一個。
    • or?可以理解為 “找第一個對勁的值”(真值)找不到就返回最后一個。

7 list.extend()?方法的返回值是?None?以及 列表擴容與內存地址

執行以下程序,輸出結果為()l1 = [1,2]
l2 = [3,4]
print(id(l1) == id(l1.extend(l2)))A False
B True
C None
D 拋出異常正確答案:A

?id(l1.extend(l2)) 得到 None 對象的內存地址?(官方題解)我以為l1這種list列表內存地址是離散的,從底層理解的話extend以后會占更多的內存空間所以內存地址肯定不一樣(歪打正著,本意就是認為列表擴容一定會更改內存地址。

你的思路中有部分正確(結果確實是 False),但對底層邏輯的理解可以再精確一些。我們來詳細拆解:

核心原因:list.extend()?方法的返回值是?None

  1. l1.extend(l2)?的作用
    它會在原列表?l1?上修改,將?l2?的元素添加到?l1?末尾(不會創建新列表)。
    執行后?l1?變成?[1,2,3,4],但?l1?本身的內存地址不變(因為是原地修改)。

  2. l1.extend(l2)?的返回值
    所有列表的 “原地修改” 方法(如?extendappendsort?等)都返回?None(這是 Python 的設計規范)。
    所以?id(l1.extend(l2))?等價于?id(None),即獲取?None?對象的內存地址。

  3. 比較的本質
    id(l1) == id(l1.extend(l2))?等價于:
    id(原列表l1的地址) == id(None的地址)
    顯然兩者完全不同,因此結果為?False

關于 “列表內存地址” 的補充

  • 列表是動態數組,當元素增加導致內存不足時,Python 會重新分配更大的內存空間并復制元素(此時?id(l1)?會變化)。
  • 但本題中?l1?從?[1,2]?擴展為?[1,2,3,4],通常不會觸發內存重分配(小列表有預留空間),所以?l1?的?id?不變。
  • 即使觸發了內存重分配,l1?的?id?變化了,l1.extend(l2)?返回的依然是?Noneid?比較結果還是?False(因為?None?的地址和任何列表的地址都不同)。

關鍵結論

這道題的核心不是 “列表是否擴容”,而是 **extend?方法返回?None**,導致比較的是 “原列表地址” 和 “None的地址”,必然不等,因此選?A

【列表擴容影響內存地址嗎?】

列表擴容可能會影響內存地址,具體取決于擴容時是否需要重新分配新的內存空間。

在 Python 中,列表(list)是一種動態數組,其底層會預先分配一定的「預留內存空間」。當添加元素時:

  • 如果當前預留空間足夠容納新元素(即未超過當前容量),則直接在原有內存空間中添加,列表的內存地址(id)不會改變
  • 如果當前預留空間不足(即超過當前容量),則需要重新分配一塊更大的內存空間,并將原列表中的元素復制到新空間中,此時列表的內存地址(id)會發生改變

示例驗證:

可以通過?id()?函數觀察列表擴容時的內存地址變化:

python

運行

l = [1, 2]
print("初始id:", id(l))  # 記錄初始內存地址# 逐步添加元素,觀察id是否變化
l.append(3)
print("添加第3個元素后id:", id(l))  # 通常不變(預留空間足夠)l.append(4)
print("添加第4個元素后id:", id(l))  # 可能不變l.extend([5, 6, 7, 8, 9])  # 一次性添加多個元素,可能觸發擴容
print("添加多個元素后id:", id(l))  # 此時可能變化(預留空間不足)

運行結果可能類似(具體地址因環境而異):

plaintext

初始id: 140525422476416
添加第3個元素后id: 140525422476416  # 地址不變
添加第4個元素后id: 140525422476416  # 地址不變
添加多個元素后id: 140525422509056  # 地址改變(觸發擴容)

總結:

  • 列表擴容時,若無需重新分配內存,地址不變若需要重新分配內存,地址改變
  • 這種機制是 Python 為了平衡性能設計的:預留空間減少了頻繁分配內存的開銷,而必要時的擴容則保證了列表可以動態增長。

因此,不能認為列表擴容一定會改變內存地址,具體取決于當前容量是否足夠。

【我怎么判斷夠不夠?】

在 Python 中,列表的「當前容量」(即底層已分配的內存空間能容納的元素總數)和「實際長度」(len()?返回的值)是兩個不同的概念。可以通過一些技巧判斷當前容量是否足夠容納新元素:

方法:借助?sys.getsizeof()?間接計算容量

sys.getsizeof(list)?會返回列表對象占用的內存總字節數。由于列表存儲的是元素的引用(指針),可以通過總字節數減去列表自身固定開銷,再除以單個指針的字節數(通常與系統位數有關,64 位系統為 8 字節),得到當前容量。

步驟如下:

  1. 導入?sys?模塊
  2. 計算列表的固定開銷(空列表的內存大小)
  3. 用?(列表總字節數 - 固定開銷) // 單個指針字節數?得到當前容量

python

運行

import sysdef get_list_capacity(lst):# 空列表的內存大小(固定開銷)empty_size = sys.getsizeof([])# 列表總內存大小total_size = sys.getsizeof(lst)# 單個指針的字節數(64位系統通常為8)pointer_size = sys.getsizeof(id(lst))  # 間接獲取指針大小(id返回的是內存地址,其大小即指針大小)# 計算容量:(總大小 - 固定開銷) / 指針大小capacity = (total_size - empty_size) // pointer_sizereturn capacity# 測試示例
l = [1, 2]
print("長度:", len(l))          # 實際元素個數:2
print("容量:", get_list_capacity(l))  # 輸出當前容量(通常大于等于2,比如可能是4)l.append(3)
print("添加1個元素后,長度:", len(l))  # 3
print("添加1個元素后,容量:", get_list_capacity(l))  # 若容量仍為4,說明還能容納l.append(4)
print("添加第2個元素后,長度:", len(l))  # 4
print("添加第2個元素后,容量:", get_list_capacity(l))  # 仍為4,剛好裝滿l.append(5)
print("添加第3個元素后,長度:", len(l))  # 5
print("添加第3個元素后,容量:", get_list_capacity(l))  # 容量可能變為8(觸發擴容)

結論:如何判斷容量是否足夠?

  • 當?len(列表) < 容量?時:容量足夠,添加元素不會改變列表的內存地址(id?不變)。
  • 當?len(列表) == 容量?時:容量已滿,再添加元素會觸發擴容,此時列表的內存地址(id?會改變)。

注意:

  • 容量是 Python 內部管理的,不同版本 / 環境可能有不同的擴容策略(通常是翻倍或按比例增長),不需要手動干預。
  • 實際開發中很少需要關心容量,因為 Python 會自動處理擴容,這個知識點主要用于理解列表的底層機制。

通過上面的方法,你可以直觀地看到列表在添加元素過程中「長度」和「容量」的變化,從而判斷是否會觸發擴容。

【那我怎么做到比較extend以后的id地址?】

要比較?extend()?操作前后列表的內存地址(id),可以在調用?extend()?方法之前之后分別獲取列表的?id,再進行比較。

關鍵在于:!!!!!!!extend()?是原地修改列表(不會返回新列表),所以需要單獨獲取?extend()?執行前后的?id

示例代碼:

python

運行

l1 = [1, 2]
l2 = [3, 4]# 記錄 extend 執行前 l1 的 id
id_before = id(l1)# 執行 extend(原地修改 l1,無返回值)
l1.extend(l2)# 記錄 extend 執行后 l1 的 id
id_after = id(l1)# 比較兩個 id 是否相同
print("extend 前 id:", id_before)
print("extend 后 id:", id_after)
print("id 是否相同:", id_before == id_after)

可能的運行結果:

plaintext

extend 前 id: 140632345869056
extend 后 id: 140632345869056
id 是否相同: True

為什么會這樣?

  • extend()?是原地修改列表(直接在?l1?原有內存空間中添加元素),如果原列表的容量足夠(len(l1) + len(l2) ≤ 容量),則不需要重新分配內存,id?保持不變。
  • 即使容量不足需要擴容(id?改變),也能通過這種方式清晰對比?extend()?前后的?id

對比:如果用?+?拼接列表(會創建新列表)

python

運行

l1 = [1, 2]
l2 = [3, 4]id_before = id(l1)
l1 = l1 + l2  # 用 + 拼接會創建新列表,l1 指向新地址
id_after = id(l1)print("+ 拼接前 id:", id_before)
print("+ 拼接后 id:", id_after)
print("id 是否相同:", id_before == id_after)  # 結果為 False

總結:

  • 要比較?extend()?前后的?id,只需在調用?extend()?方法分別獲取列表的?id?即可。
  • extend()?通常不會改變列表的?id(除非擴容觸發內存重分配),而?+?拼接一定會改變?id(因為創建了新列表)。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/919610.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/919610.shtml
英文地址,請注明出處:http://en.pswp.cn/news/919610.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

SpringBoot + MyBatis-Plus 使用 listObjs 報 ClassCastException 的原因與解決辦法

在項目中我們經常會遇到這種需求&#xff1a; 根據一組 ID 查詢數據庫&#xff0c;并返回指定字段列表。 我在寫代碼的時候&#xff0c;遇到了一個典型的坑&#xff0c;分享出來給大家。一、問題背景我的代碼是這樣寫的&#xff08;查詢項目表的負責人信息&#xff09;&#xf…

WT2606B 驅屏語音芯片新增藍牙功能:功能集成一體化,產品升級自動化,語音交互無線化,場景應用普適化!

小伙伴們&#xff0c;歡迎來到我們的 &#xff03;唯創芯片小講堂&#xff01;今天我們要為大家介紹一位多才多藝的"芯片全能手"——WT2606B驅屏語音芯片。這顆芯片將在今年8月的I0TE物聯網展及ELEXCON 2025深圳國際電子展上大放異彩。在智能設備滿天飛的今天&#x…

ORA-16331: container is not open ORA-06512: at “SYS.DBMS_LOGMNR“

使用Flink CDC、Debezium等CDC工具對Oracle進行基于log的實時數據同步時遇到異常ORA-16331: container is not open的解決方案。 1. 異常信息 異常信息通常如下&#xff1a; at oracle.jdbc.driver.OracleStatement.executeInternal(OracleStatement.java:1823) at oracle.jdbc…

「三維共振」:重構實體零售的破局模式

在電商沖擊與消費升級的雙重浪潮下&#xff0c;傳統零售模式正面臨前所未有的挑戰。wo店首創的 “三維共振” 運營模式&#xff0c;以場景體驗為根基、數據驅動為引擎、社群共生為紐帶&#xff0c;構建起線上線下深度融合的新型零售生態&#xff0c;至今已實現連續 18 個月客流…

將集合拆分成若干個batch,并將batch存于新的集合

在使用saveAll()等方法時&#xff0c;為了防止集合元素過大&#xff0c;使用splitList將原集合&#xff0c;分割成若干個小集合 import java.util.ArrayList; import java.util.List;public class ListUtils {/*** 將集合拆分成若干個batch,并將batch存于新的集合** param list…

Java主流框架全解析:從企業級開發到云原生

Java作為一門歷史悠久且應用廣泛的編程語言&#xff0c;其強大的生態系統離不開各種優秀的框架支持。無論是傳統的企業級應用開發&#xff0c;還是現代的微服務、云原生架構&#xff0c;Java都提供了豐富的框架選擇。本文將全面解析當前主流的Java框架&#xff0c;涵蓋Web開發、…

機器學習——網格搜索(GridSearchCV)超參數優化

網格搜索&#xff08;Grid Search&#xff09;詳細教學1. 什么是網格搜索&#xff1f;在機器學習模型中&#xff0c;算法的**超參數&#xff08;Hyperparameters&#xff09;**對模型的表現起著決定性作用。比如&#xff1a;KNN 的鄰居數量 n_neighborsSVM 的懲罰系數 C 和核函…

【LeetCode】18. 四數之和

文章目錄18. 四數之和題目描述示例 1&#xff1a;示例 2&#xff1a;提示&#xff1a;解題思路算法一&#xff1a;排序 雙指針&#xff08;推薦&#xff09;算法二&#xff1a;通用 kSum&#xff08;含 2Sum 雙指針&#xff09;復雜度關鍵細節代碼實現要點完整題解代碼18. 四數…

Go語言入門(10)-數組

訪問數組元素&#xff1a;數組中的每個元素都可以通過“[]”和一個從0開始的索引進行訪問數組的長度可由內置函數len來確定。在聲明數組時&#xff0c;未被賦值元素的值是對應類型的零值。下面看一個例子package mainfunc main(){var planets [8]stringplanets[0] "Mercu…

為什么經過IPSec隧道后HTTPS會訪問不通?一次隧道環境下的實戰分析

在運維圈子里&#xff0c;大家可能都遇到過這種奇怪的問題&#xff1a;瀏覽器能打開 HTTP 網站&#xff0c;但一換成 HTTPS&#xff0c;頁面就死活打不開。前段時間&#xff0c;我們就碰到這么一個典型案例。故障現象某公司系統在 VPN 隧道里訪問 HTTPS 服務&#xff0c;結果就…

【Linux系統】進程信號:信號的產生和保存

上篇文章我們介紹了Syetem V IPC的消息隊列和信號量&#xff0c;那么信號量和我們下面要介紹的信號有什么關系嗎&#xff1f;其實沒有關系&#xff0c;就相當于我們日常生活中常說的老婆和老婆餅&#xff0c;二者并沒有關系1. 認識信號1.1 生活角度的信號解釋&#xff08;快遞比…

WEB服務器(靜態/動態網站搭建)

簡介 名詞:HTML(超文本標記語言),網站(多個網頁組成一臺網站),主頁,網頁,URL(統一資源定位符) 網站架構:LAMP(linux(系統)+apache(服務器程序)+mysql(數據庫管理軟件)+php(中間軟件)) 靜態站點 Apache基礎 Apache官網:www.apache.org 軟件包名稱:…

開發避坑指南(29):微信昵稱特殊字符存儲異常修復方案

異常信息 Cause: java.sql.SQLException: Incorrect string value: \xF0\x9F\x8D\x8B\xE5\xBB... for column nick_name at row 1異常背景 抽獎大轉盤&#xff0c;抽獎后需要保存用戶抽獎記錄&#xff0c;用戶再次進入游戲時根據抽獎記錄判斷剩余抽獎機會。保存抽獎記錄時需要…

leetcode-python-242有效的字母異位詞

題目&#xff1a; 給定兩個字符串 s 和 t &#xff0c;編寫一個函數來判斷 t 是否是 s 的 字母異位詞。 示例 1: 輸入: s “anagram”, t “nagaram” 輸出: true 示例 2: 輸入: s “rat”, t “car” 輸出: false 提示: 1 < s.length, t.length < 5 * 104 s 和 t 僅…

【ARM】Keil MDK如何指定單文件的優化等級

1、 文檔目標解決在MDK中如何對于單個源文件去設置優化等級。2、 問題場景在正常的項目開發中&#xff0c;我們通常都是針對整個工程去做優化&#xff0c;相當于整個工程都是使用一個編譯器優化等級去進行的工程構建。那么在一些特定的情況下&#xff0c;工程師需要保證我的部分…

零基礎學Java第二十二講---異常(2)

續接上一講 目錄 一、異常的處理&#xff08;續&#xff09; 1、異常的捕獲-try-catch捕獲并處理異常 1.1關于異常的處理方式 2、finally 3、異常的處理流程 二、自定義異常類 1、實現自定義異常類 一、異常的處理&#xff08;續&#xff09; 1、異常的捕獲-try-catch捕…

自建開發工具IDE(一)之拖找排版—仙盟創夢IDE

自建拖拽布局排版在 IDE 中的優勢及初學者開發指南在軟件開發領域&#xff0c;用戶界面&#xff08;UI&#xff09;的設計至關重要。自建拖拽布局排版功能為集成開發環境&#xff08;IDE&#xff09;帶來了諸多便利&#xff0c;尤其對于初學者而言&#xff0c;是踏入開發領域的…

GitHub Copilot - GitHub 推出的AI編程助手

本文轉載自&#xff1a;GitHub Copilot - GitHub 推出的AI編程助手 - Hello123工具導航。 ** 一、GitHub Copilot 核心定位 GitHub Copilot 是由 GitHub 與 OpenAI 聯合開發的 AI 編程助手&#xff0c;基于先進大語言模型實現代碼實時補全、錯誤檢測及文檔生成&#xff0c;顯…

基于截止至 2025 年 6 月 4 日,在 App Store 上進行交易的設備數據統計,iOS/iPadOS 各版本在所有設備中所占比例詳情

iOS 和 iPadOS 使用情況 基于截止至 2025 年 6 月 4 日&#xff0c;在 App Store 上進行交易的設備數據統計。 iPhone 在過去四年推出的設備中&#xff0c;iOS 18 的普及率達 88。 88% iOS 188% iOS 174% 較早版本 所有的設備中&#xff0c;iOS 18 的普及率達 82。 82% iOS 189…

云計算-k8s實戰指南:從 ServiceMesh 服務網格、流量管理、limitrange管理、親和性、環境變量到RBAC管理全流程

介紹 本文是一份 Kubernetes 與 ServiceMesh 實戰操作指南,涵蓋多個核心功能配置場景。從 Bookinfo 應用部署入手,詳細演示了通過 Istio 創建 Ingress Gateway 實現外部訪問,以及基于用戶身份、請求路徑的服務網格路由規則配置,同時為應用微服務設置了默認目標規則。 還包…