本文將會(huì)總結(jié)以下幾個(gè)知識(shí)點(diǎn):
- 列表推導(dǎo)式
-
==和is - 深拷貝和淺拷貝
列表推導(dǎo)式
需求:如果我們想生成一個(gè)連續(xù)的列表,可以采用哪些方式呢?首先可以使用 for 和 while 循環(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,b,c 三個(gè)變量的值相同,都是 [1,2,3],因此使用 == 操作符判斷的結(jié)果為 True,a,b,c 與 d 的值不相同,因此判斷的結(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
上例中,只有 a 和 b 變量指向同一塊內(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ì)影響到新變量中的值。示意圖如下:

接下看看一下淺拷貝的例子:
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)行拷貝,仍然指向原始的引用。示意圖如下:

對(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)需要注意。
完。