歡迎加入QQ討論群258996829
麥子學(xué)院 頭像
蘋(píng)果6袋
6
麥子學(xué)院

python對(duì)象的可變類(lèi)型與不可變類(lèi)型

發(fā)布時(shí)間:2017-09-18 15:35  回復(fù):0  查看:2980   最后回復(fù):2017-09-18 15:35  
本文和大家分享的主要是python 對(duì)象的可變類(lèi)型與不可變類(lèi)型相關(guān)內(nèi)容,一起來(lái)看看吧,希望對(duì)大家 學(xué)習(xí)python有所幫助。
  python 對(duì)象對(duì)于修改這個(gè)行為,大家的操作方式都是不一樣的。有些對(duì)象是可變類(lèi)型,所以他就可以直接修改。其它的都是不可變類(lèi)型,那我們要修改他時(shí)怎么辦呢,這個(gè)時(shí)候就新生成的一個(gè)對(duì)象,然后將變量名指向這個(gè)新對(duì)象,修改動(dòng)作就完成了。關(guān)于可變類(lèi)型與不可變類(lèi)型的一個(gè)特點(diǎn),我們可以先看看一段奇怪的代碼
   In [1]: a = 'a'
   In [2]: b = 'a'
   In [3]: a  is b
  Out[3]: True
   In [4]: a == b
  Out[4]: True
   In [5]: c = [1]
   In [6]: d = [1]
   In [7]: c  is d
  Out[7]: False
   In [8]: c == d
  Out[8]: True
  你有沒(méi)有覺(jué)得,a b  明明都是不同的對(duì)象,但是使用 a is b  的時(shí)候 竟然返回了 true  ,這里面就會(huì)深入到對(duì)象的別名,標(biāo)識(shí)與相等性,先說(shuō)回到可變類(lèi)型與不可變類(lèi)型
   分類(lèi)
   不可變類(lèi)型
  · int
  · float
  · decimal
  · complex
  · bool
  · string
  · tuple
  · range
  · frozenset
  · bytes
   可變類(lèi)型
  · list
  · dict
  · set
  · bytearray
  · user-defined classes (unless specifically made immutable)
  有個(gè)簡(jiǎn)單的方式來(lái)區(qū)分這些類(lèi)型,類(lèi)似的容器類(lèi)型的數(shù)據(jù)就是可變類(lèi)型(list,set,dict)— 我們就想像一個(gè)容器可以不停的注入內(nèi)容,其它的基本都是不可變的類(lèi)型,這里有幾個(gè)特殊的
  ·  元組  tuple
  · frozenset
  · str
   區(qū)分類(lèi)型?有這個(gè)必要嗎?
  當(dāng)然是顯然的,雖然我們?cè)趯?shí)際的工程環(huán)節(jié)都會(huì)圍繞整體的業(yè)務(wù)問(wèn)題,很少去了解底層的原理,但是我們一旦涉及到優(yōu)化,涉及到底層的時(shí)候就很有必要了解技術(shù)細(xì)節(jié)。舉個(gè)例子,如何高效的拼接字符串,我想下面的代碼大部分人都寫(xiě)過(guò),包括我
   In [13]: str_build = '' In [14]:  for p  in 'aaabbbccc':
  ...:     str_build = str_build + p
  事實(shí)上,這樣的效率并不是很高。如上所言,我們知道str  是不可變類(lèi)型,我們?cè)谄唇幼址臅r(shí)候,實(shí)際上是生成了一個(gè)新的對(duì)象,然后在變量名指向他,隨著拼接的次數(shù)越來(lái)越多,我們生成對(duì)象的操作次數(shù)也會(huì)越來(lái)越多,這樣就很沒(méi)有這個(gè)必要 (C#  里面的 StringBuilder  就是為了解決字符串拼接的 ) ,那有效率的寫(xiě)法是怎樣的呢
  builder_list = [] for data in container:
  builder_list. append(str(data))"". join(builder_list)
  ### Another way  is  to use  a  list comprehension"". join([str(data)  for data in container])
  ### or use the  map  function"". join( map(str, container))
  我們通過(guò)使用列表,可以輕松的在本身對(duì)象的基礎(chǔ)上修改內(nèi)容,不會(huì)生成新對(duì)象來(lái)處理操作,這樣就會(huì)節(jié)省內(nèi)存
  另外的一個(gè)我們會(huì)遇到關(guān)于可變類(lèi)型的一個(gè)坑
   def  my_function(param=[]):
  param.append("thing")
   return param
  my_function() # returns ["thing"]
  my_function() # returns ["thing", "thing"]
  你會(huì)不會(huì)覺(jué)得,我去,不管我調(diào)用多少次,這丫不是應(yīng)該就返回一個(gè)[‘thing’] 回來(lái)嗎?但是事實(shí)上你也看到了,因?yàn)榭勺儗?duì)象一直都會(huì)引用同一段內(nèi)容,我們?cè)诓僮髁斜淼臅r(shí)候都會(huì)對(duì)同一個(gè)列表操作,比如我們?cè)诤瘮?shù)體里面操作了一個(gè) set ,list , 或者  dict  ,雖然我們沒(méi)有返回內(nèi)容,但是外部的內(nèi)容還是會(huì)變的,所以我們要記得,不要給可變對(duì)象做為參數(shù)的時(shí)候加上默認(rèn)值!
   def  my_function2(param=None):
   if param  is  None:
  param = []
  param.append("thing")
   return param
   結(jié)論
  正確的區(qū)分可變類(lèi)型與不可變類(lèi)型,對(duì)于我們深入了解python 是非常有 python 的,更多的關(guān)注技術(shù)細(xì)節(jié),才能更好的拔高我們的技術(shù)水平
   番外
  我們?cè)谇把岳锩嬗刑岬降哪莻€(gè)奇怪的問(wèn)題,很顯然,那是共享了字符串的字面量,這種Cpython 里面一個(gè)優(yōu)化策略,叫駐留 (interning).CPython  還會(huì)在小的整數(shù)上使用這個(gè)優(yōu)化措施,防止重復(fù)的創(chuàng)建 熱門(mén) 數(shù)字,比如 0 -1 ,和 42 等等,但是 CPython 不會(huì)駐留所有的字符串和整數(shù)。比如如下的代碼
   In [5]: c = 1
   In [6]: d = 1
   In [7]: id(c) Out[7]: 4297514912
   In [8]: id(d) Out[8]: 4297514912
   In [9]: e = 22569
   In [10]: f = 22569
   In [11]: e  is f Out[11]: False
   In [12]: c  is d Out[12]: True
  所以千萬(wàn)不要依賴字符串或者整數(shù)的駐留!比較字符串或者整數(shù)是否相等的時(shí),應(yīng)該使用==  而不是 is.  駐留是 python  解釋器內(nèi)部使用的一個(gè)特性。
來(lái)源:大魚(yú)的博客
您還未登錄,請(qǐng)先登錄

熱門(mén)帖子

最新帖子

?