python對象下的可變類型與不可變類型

      網(wǎng)友投稿 730 2025-04-01

      前言

      python對象對于修改這個(gè)行為,大家的操作方式都是不一樣的。有些對象是可變類型,所以他就可以直接修改。其它的都是不可變類型,那我們要修改他時(shí)怎么辦呢,這個(gè)時(shí)候就新生成的一個(gè)對象,然后將變量名指向這個(gè)新對象,修改動作就完成了。關(guān)于可變類型與不可變類型的一個(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

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      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

      你有沒有覺得,a b 明明都是不同的對象,但是使用a is b 的時(shí)候 竟然返回了true ,這里面就會深入到對象的別名,標(biāo)識與相等性,先說回到可變類型與不可變類型

      分類

      不可變類型

      int

      float

      decimal

      complex

      bool

      string

      tuple

      range

      frozenset

      bytes

      可變類型

      list

      dict

      set

      bytearray

      user-defined classes (unless specifically made immutable)

      有個(gè)簡單的方式來區(qū)分這些類型,類似的容器類型的數(shù)據(jù)就是可變類型(list,set,dict)—我們就想像一個(gè)容器可以不停的注入內(nèi)容,其它的基本都是不可變的類型,這里有幾個(gè)特殊的

      元組 tuple

      frozenset

      str

      區(qū)分類型?有這個(gè)必要嗎?

      當(dāng)然是顯然的,雖然我們在實(shí)際的工程環(huán)節(jié)都會圍繞整體的業(yè)務(wù)問題,很少去了解底層的原理,但是我們一旦涉及到優(yōu)化,涉及到底層的時(shí)候就很有必要了解技術(shù)細(xì)節(jié)。舉個(gè)例子,如何高效的拼接字符串,我想下面的代碼大部分人都寫過,包括我

      In [13]: str_build = '' In [14]: for p in 'aaabbbccc': ...: str_build = str_build + p

      1

      2

      3

      4

      In [13]: str_build = ''

      In [14]: for p in 'aaabbbccc':

      ...:???? str_build = str_build + p

      事實(shí)上,這樣的效率并不是很高。如上所言,我們知道str 是不可變類型,我們在拼接字符串的時(shí)候,實(shí)際上是生成了一個(gè)新的對象,然后在變量名指向他,隨著拼接的次數(shù)越來越多,我們生成對象的操作次數(shù)也會越來越多,這樣就很沒有這個(gè)必要(C# 里面的StringBuilder 就是為了解決字符串拼接的),那有效率的寫法是怎樣的呢

      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))

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      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))

      我們通過使用列表,可以輕松的在本身對象的基礎(chǔ)上修改內(nèi)容,不會生成新對象來處理操作,這樣就會節(jié)省內(nèi)存

      另外的一個(gè)我們會遇到關(guān)于可變類型的一個(gè)坑

      def my_function(param=[]): param.append("thing") return param my_function() # returns ["thing"] my_function() # returns ["thing", "thing"]

      1

      2

      3

      4

      5

      6

      7

      def my_function(param=[]):

      param.append("thing")

      return param

      my_function() # returns ["thing"]

      my_function() # returns ["thing", "thing"]

      你會不會覺得,我去,不管我調(diào)用多少次,這丫不是應(yīng)該就返回一個(gè)[‘thing’]回來嗎?但是事實(shí)上你也看到了,因?yàn)榭勺儗ο笠恢倍紩猛欢蝺?nèi)容,我們在操作列表的時(shí)候都會對同一個(gè)列表操作,比如我們在函數(shù)體里面操作了一個(gè)set ,list ,或者 dict ,雖然我們沒有返回內(nèi)容,但是外部的內(nèi)容還是會變的,所以我們要記得,不要給可變對象做為參數(shù)的時(shí)候加上默認(rèn)值!

      def my_function2(param=None): if param is None: param = [] param.append("thing") return param

      1

      2

      3

      4

      5

      6

      python對象下的可變類型與不可變類型

      def my_function2(param=None):

      if param is None:

      param = []

      param.append("thing")

      return param

      結(jié)論

      正確的區(qū)分可變類型與不可變類型,對于我們深入了解python是非常有幫助的,更多的關(guān)注技術(shù)細(xì)節(jié),才能更好的拔高我們的技術(shù)水平

      番外

      我們在前言里面有提到的那個(gè)奇怪的問題,很顯然,那是共享了字符串的字面量,這種Cpython里面一個(gè)優(yōu)化策略,叫駐留(interning).CPython 還會在小的整數(shù)上使用這個(gè)優(yōu)化措施,防止重復(fù)的創(chuàng)建”熱門“數(shù)字,比如0,-1,和42等等,但是CPython不會駐留所有的字符串和整數(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

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      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

      所以千萬不要依賴字符串或者整數(shù)的駐留!比較字符串或者整數(shù)是否相等的時(shí),應(yīng)該使用== 而不是is. 駐留是python 解釋器內(nèi)部使用的一個(gè)特性。

      Python

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:WPS表格中怎么制作折線圖呢(WPS表格做折線圖)
      下一篇:定制家居訂單管理流程:打造個(gè)性家居的完美體驗(yàn)
      相關(guān)文章
      亚洲an日韩专区在线| 亚洲国产人成在线观看| 亚洲日本VA中文字幕久久道具| 亚洲欧洲精品一区二区三区| 久热综合在线亚洲精品| 国产亚洲一区二区精品| 亚洲精品乱码久久久久66| 亚洲中文字幕无码一区| 亚洲自偷自偷图片| 亚洲啪啪AV无码片| 国产l精品国产亚洲区在线观看| 亚洲一区二区三区自拍公司| 亚洲永久无码3D动漫一区| 亚洲夜夜欢A∨一区二区三区| 亚洲乱码精品久久久久..| 日韩亚洲一区二区三区| 亚洲av日韩av无码| 精品亚洲成AV人在线观看| 亚洲黄色网站视频| 亚洲国产精品张柏芝在线观看| 亚洲国产夜色在线观看| 亚洲综合精品成人| 亚洲成av人片天堂网无码】| 在线看亚洲十八禁网站| 亚洲情a成黄在线观看| 亚洲热线99精品视频| 亚洲av综合avav中文| 久久夜色精品国产噜噜亚洲AV| 亚洲精品国产成人| 亚洲av成人综合网| 亚洲一区二区三区丝袜| 鲁死你资源站亚洲av| jizzjizz亚洲| 亚洲无人区午夜福利码高清完整版| 亚洲成a人片77777kkkk| 中文字幕亚洲综合久久2| 亚洲乱码一二三四区国产| 亚洲欧美一区二区三区日产| 亚洲国产精品一区二区第一页免| 亚洲精品第一国产综合精品99| 中文字幕日韩亚洲|