python中沒有賦值,只有引用。
(1)沒有限制條件的分片表達(dá)式(L[:])能夠復(fù)制序列,但此法只能淺層復(fù)制(淺復(fù)制出來的對(duì)象內(nèi)存地址和原來不一樣)。
(2)字典 copy 方法,D.copy() 能夠復(fù)制字典,但此法只能淺層復(fù)制
(3)有些內(nèi)置函數(shù),例如 list,能夠生成拷貝 list(L)
(4)copy 標(biāo)準(zhǔn)庫模塊能夠生成完整拷貝:deepcopy 本質(zhì)上是遞歸 copy(之前遇到過keystone.seesion來傳證書,然后發(fā)現(xiàn)參數(shù)里有session,同時(shí)還有其他參數(shù)里也包含了session,這樣不能deepcopy)
對(duì)象分為可變與不可變的,
可變:list set dict
可變對(duì)象更改的時(shí)候,內(nèi)存地址不變,只是區(qū)域長(zhǎng)度會(huì)變長(zhǎng)或變短;但不可變對(duì)象如string更改的時(shí)候,內(nèi)存地址會(huì)發(fā)生改變,及id(d)會(huì)變化即身份標(biāo)示
對(duì)象的三要素:id(身份標(biāo)示),type(數(shù)據(jù)類型)、value(值)
is比較的是兩個(gè)對(duì)象的id值是否相等,也就是比較兩個(gè)對(duì)象是否為同一個(gè)實(shí)例對(duì)象,是否指向同一個(gè)內(nèi)存地址。
==比較的是兩個(gè)對(duì)象的內(nèi)容是否相等,默認(rèn)會(huì)調(diào)用對(duì)象的eq()方法。
>>> b = 10**3
>>> a == b
True
>>> a is b
False
>>>
數(shù)字類型不一樣,id也不一樣
>>> c = 'pythontab.com'
>>> d = 'pythontab.com'
>>> c is d
False
>>> c == d
True
>>> c = 'pythontabcom'
>>> d = 'pythontabcom'
>>> c is c
True
>>> c == d
True
字符串類型不一樣,導(dǎo)致id不一樣
4.為什么修改全局的dict變量不用global關(guān)鍵字
為什么修改字典d的值不用global關(guān)鍵字先聲明呢?
s = 'foo'
d = {'a':1}
def f():
s = 'bar'
d['b'] = 2
f()
print s # foo
print d # {'a': 1, 'b': 2}
這是因?yàn)?,?】在s = 'bar'這句中,它是“有歧義的“,因?yàn)樗瓤梢允潜硎疽萌肿兞縮,也可以是創(chuàng)建一個(gè)新的局部變量,所以在python中,默認(rèn)它的行為是創(chuàng)建局部變量,除非顯式聲明global,global定義的本地變量會(huì)變成其對(duì)應(yīng)全局變量的一個(gè)別名,即是同一個(gè)變量。【2】在d['b']=2這句中,它是“明確的”,因?yàn)槿绻裠當(dāng)作是局部變量的話,它會(huì)報(bào)KeyError,所以它只能是引用全局的d,故不需要多此一舉顯式聲明global。
上面這兩句賦值語句其實(shí)是不同的行為,一個(gè)是rebinding(不可變對(duì)象), 一個(gè)是mutation(可變對(duì)象).
但是如果是下面這樣:
d = {'a':1}
def f():
d = {}
d['b'] = 2
f()
print d # {'a': 1}
在d = {}這句,它是”有歧義的“了,所以它是創(chuàng)建了局部變量d,而不是引用全局變量d,所以d['b']=2也是操作的局部變量。
推而遠(yuǎn)之,這一切現(xiàn)象的本質(zhì)就是”它是否是明確的“。
仔細(xì)想想,就會(huì)發(fā)現(xiàn)不止dict不需要global,所有”明確的“東西都不需要global。因?yàn)閕nt類型str類型之類的不可變對(duì)象,每一次操作就重建新的對(duì)象,他們只有一種修改方法,即x = y, 恰好這種修改方法同時(shí)也是創(chuàng)建變量的方法,所以產(chǎn)生了歧義,不知道是要修改還是創(chuàng)建。而dict/list/對(duì)象等可變對(duì)象,操作不會(huì)重建對(duì)象,可以通過dict['x']=y或list.append()之類的來修改,跟創(chuàng)建變量不沖突,不產(chǎn)生歧義,所以都不用顯式global。
5.list的=和append/extend的區(qū)別
list_a = []
def a():
list_a = [1] ## 語句1
a()
print list_a # []
print "======================"
list_b = []
def b():
list_b.append(1) ## 語句2
b()
print list_b # [1]
因?yàn)?= 創(chuàng)建了局部變量,而 .append() 或者 .extend() 重用了全局變量。
可參考這個(gè)[https://blog.csdn.net/dream_allday/article/details/78767813]
一般可變對(duì)象的id變了,值也就不一樣了
6.5、陷阱:使用可變的默認(rèn)參數(shù)
我多次見到過如下的代碼:
def foo(a, b, c=[]):
# append to c
# do some more stuff
永遠(yuǎn)不要使用可變的默認(rèn)參數(shù),可以使用如下的代碼代替:
def foo(a, b, c=None):
if c is None:
c = []
# append to c
# do some more stuff
??與其解釋這個(gè)問題是什么,不如展示下使用可變默認(rèn)參數(shù)的影響:??
In[2]: def foo(a, b, c=[]):
... c.append(a)
... c.append(b)
... print(c)
...
In[3]: foo(1, 1)
[1, 1]
In[4]: foo(1, 1)
[1, 1, 1, 1]
In[5]: foo(1, 1)
[1, 1, 1, 1, 1, 1]
同一個(gè)變量c在函數(shù)調(diào)用的每一次都被反復(fù)引用。這可能有一些意想不到的后果。