列表推導(dǎo)式、深淺拷貝

本文將會(huì)總結(jié)以下幾個(gè)知識(shí)點(diǎn):

  • 列表推導(dǎo)式
  • ==is
  • 深拷貝和淺拷貝

列表推導(dǎo)式

需求:如果我們想生成一個(gè)連續(xù)的列表,可以采用哪些方式呢?首先可以使用 forwhile 循環(huán):

def createList(num):
    lis = []
    for i in range(num):
        lis.append(i)
    return lis

print(createList(10))
def createList(num):
    lis = []
    count = 0
    while True:
        if num == count:
            break;
        else:
            count += 1
            lis.append(count)
    return lis

print(createList(10))

如果我們想在生成列表的時(shí)候進(jìn)行篩選,可以這樣做:

def createList(num):
    lis = []
    for i in range(num):
        if not i%2:
            lis.append(i)

    return lis

print(createList(10))
def createList(num):
    lis = []
    count = 0
    while True:
        if num == count:
            break;
        else:
            count += 1
            if not count % 2:
                lis.append(count)
    return lis

print(createList(10))

上面的代碼可以生成任何我們想要的列表,但是代碼量有點(diǎn)多,因此,Python 提供了列表推導(dǎo)式讓我們快捷生成列表,其格式為:

[ 變量 for 表達(dá)式 判斷條件 ]

上面的變量有且只能有一個(gè),如果需要多個(gè)變量,可以采用列表或元組的方式實(shí)現(xiàn)。下面是一些常見(jiàn)用途:
1.生成一個(gè)列表:

def createList(num):
    return [i for i in range(num)]

print(createList(10))

運(yùn)行結(jié)果:

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

2.生成列表時(shí)進(jìn)行篩選:

def createList(num):
    return [i for i in range(num) if not i%2]

print(createList(10))

運(yùn)行結(jié)果:

[0, 2, 4, 6, 8]

3.循環(huán)嵌套,生成多維列表

def createList(num):
    return [(i,j) for i in range(num) for j in range(3)]

print(createList(3))

運(yùn)行結(jié)果:

[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]

上面就是列表推導(dǎo)式的簡(jiǎn)單用法。

==is

Python 中,== 用來(lái)判斷兩個(gè)變量的值是否相同,is 用來(lái)判斷兩個(gè)變量是否指向同一塊內(nèi)存空間。
看如下實(shí)例:

a = [1,2,3]
b = a
c = [1,2,3]
d = [1,2,3,4]

print("a == b: %s"%(a == b))
print("a == c: %s"%(a == c))
print("b == c: %s"%(b == c))
print("a == d: %s"%(a == d))

運(yùn)行結(jié)果:

a == b: True
a == c: True
b == c: True
a == d: False

如上,a,bc 三個(gè)變量的值相同,都是 [1,2,3],因此使用 == 操作符判斷的結(jié)果為 True,a,b,cd 的值不相同,因此判斷的結(jié)果為 False
再來(lái)看下 is 運(yùn)算符:

a = [1,2,3]
b = a
c = [1,2,3]
d = [1,2,3,4]

print("a == b: %s"%(a is b))
print("a == c: %s"%(a is c))
print("b == c: %s"%(b is c))
print("a == d: %s"%(a is d))

運(yùn)行結(jié)果:

a == b: True
a == c: False
b == c: False
a == d: False

上例中,只有 ab 變量指向同一塊內(nèi)存,因此對(duì)它們使用 is 操作符判斷的結(jié)果為 True,而其他的幾個(gè)判斷返回 True。

深拷貝和淺拷貝

實(shí)現(xiàn)深拷貝和淺拷貝,可以使用函數(shù)遞歸完成,也可以使用 Python 內(nèi)置的 copy 模塊。深拷貝使用 deepcopy 函數(shù),淺拷貝使用 copy 函數(shù)。
深拷貝和淺拷貝的區(qū)別如下:

  • 深拷貝會(huì)對(duì)變量進(jìn)行遞歸拷貝,拷貝后的值和原始值之間沒(méi)有引用關(guān)系
  • 淺拷貝只對(duì)變量的外層進(jìn)行拷貝,拷貝后內(nèi)層值與原始值之間扔存在引用關(guān)系

看一下深拷貝的例子:

from copy import deepcopy

a = [1,2,3]
b = [4,5,6]
# c 中保存了 a 和 b 的引用,修改 a 和 b 的值會(huì)同步影響到 c 的值
c = [a,b]
# 對(duì) c 進(jìn)行深拷貝
d = deepcopy(c)
# 修改 a 的值
a.append(666)
# 打印 c 和 d
print(c)
print(d)
print(c is d)

運(yùn)行結(jié)果如下:

[[1, 2, 3, 666], [4, 5, 6]]
[[1, 2, 3], [4, 5, 6]]
False

進(jìn)行深拷貝時(shí),會(huì)對(duì)變量?jī)?nèi)部一層一層進(jìn)行遞歸拷貝,拷貝到新變量中的值和原始值之間沒(méi)有引用關(guān)系,修改原始值不會(huì)影響到新變量中的值。示意圖如下:


深拷貝示意圖.png

接下看看一下淺拷貝的例子:

from copy import copy

a = [1,2,3]
b = [4,5,6]
# c 中保存了 a 和 b 的引用,修改 a 和 b 的值會(huì)同步影響到 c 的值
c = [a,b]
# 對(duì) c 進(jìn)行淺拷貝
d = copy(c)
# 修改 a 的值
a.append(666)
# 打印 c 和 d
print(c)
print(d)
print(c is d)

運(yùn)行結(jié)果如下:

[[1, 2, 3, 666], [4, 5, 6]]
[[1, 2, 3, 666], [4, 5, 6]]
False

可見(jiàn),淺拷貝只能對(duì)外層進(jìn)行拷貝,而對(duì)于內(nèi)層的值不會(huì)進(jìn)行拷貝,仍然指向原始的引用。示意圖如下:

淺拷貝示意圖.png

對(duì)元組進(jìn)行淺拷貝

修改代碼,實(shí)現(xiàn)對(duì)元組進(jìn)行淺拷貝:

from copy import copy

a = [1,2,3]
b = [4,5,6]
c = (a,b)
d = copy(c)
print(c is d)
print(id(c),id(d))

運(yùn)行結(jié)果如下:

True
17322512 17322512

修改代碼,實(shí)現(xiàn)對(duì)元組進(jìn)行深拷貝:

from copy import deepcopy

a = [1,2,3]
b = [4,5,6]
c = (a,b)
d = deepcopy(c)
print(c is d)
print(id(c),id(d))

運(yùn)行結(jié)果如下:

False
15881080 15207040

可見(jiàn),進(jìn)行淺拷貝時(shí),如果是不可變類(lèi)型,則不會(huì)對(duì)外層進(jìn)行拷貝,調(diào)用 copy 函數(shù)的返回值仍然是指向原始值的一個(gè)引用,進(jìn)行深拷貝時(shí)才會(huì)對(duì)外層和內(nèi)層進(jìn)行拷貝,這點(diǎn)需要注意。

完。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,030評(píng)論 25 709
  • *面試心聲:其實(shí)這些題本人都沒(méi)怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個(gè)offer,總結(jié)起來(lái)就是把...
    Dove_iOS閱讀 27,618評(píng)論 30 472
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,554評(píng)論 19 139
  • 十年前,高齡未婚。用后來(lái)的流行詞叫“資深剩女”。 青春熱烈而美好,那時(shí)內(nèi)心追求的,是像影視劇里的樣子:有純純的愛(ài)情...
    暖香閣主閱讀 501評(píng)論 1 1
  • 對(duì)于日本似乎我們總有說(shuō)不完的話題,總是喜歡說(shuō)作為一名中國(guó)人,要勿忘國(guó)恥,銘記歷史! 我所熟悉的應(yīng)試教育,也讓我聯(lián)想...
    我是一直流浪的豬閱讀 630評(píng)論 0 1

友情鏈接更多精彩內(nèi)容