Python進(jìn)階6

對(duì)象引用、垃圾回收、可變性

Python中的變量是什么

引言

  • Pythonjava中的變量本質(zhì)不一樣,java的變量可以理解為一個(gè)盒子,用來(lái)容納我們的對(duì)象,使用前要先聲明它,好分配給我們合適的內(nèi)存空間。Python的變量可以理解為一個(gè)標(biāo)簽,先構(gòu)造出對(duì)象,再將變量貼在對(duì)象上。
  • Python變量沒(méi)有類型,對(duì)象才有,本質(zhì)上是指針。同一個(gè)變量,可以表示不同對(duì)象。

使用案例

"""
a 和 b 都貼在了同一個(gè)對(duì)象上
"""
a = [1, 2]
b = a
a.append(6)

print(a, b)
print(a is b)
print(id(a), id(b))

# result:
# [1, 2, 6] [1, 2, 6]
# True
# 1840524096136 1840524096136

is和==的區(qū)別

引言

  • is用來(lái)判斷引用是否相同
  • ==用來(lái)判斷值是否相等

使用案例

"""
對(duì)于小整數(shù) 和 較短的字符串多次出現(xiàn),Python有一種緩存機(jī)制
多次出現(xiàn)的對(duì)象不再反復(fù)創(chuàng)建,后出現(xiàn)的對(duì)象直接引用前面的對(duì)象
"""
a, b, c, d = 1, 1, -123, -123
print(a is b)
print(c is d)

# result:
# True
# False

a, b = [1, 2, 3], [1, 2, 3]
print(a is b)
print(a == b)

# result:
# False
# True

del和垃圾回收

引言

  • del語(yǔ)句直接回收變量,將它所貼對(duì)象的引用計(jì)數(shù)器減一。每有一個(gè)新變量引用對(duì)象,其引用計(jì)數(shù)器就會(huì)加一
  • 引用計(jì)數(shù)器為 0 的對(duì)象會(huì)被后續(xù)回收

使用案例

a = "hello"
b = a       # a,b 兩個(gè)標(biāo)簽都貼在了對(duì)象 "hello" 上
            # "hello"的引用計(jì)數(shù)器為2
del a       # "hello"的引用計(jì)數(shù)器減一
print(b)
print(a)

# result:
# hello
# NameError: name 'a' is not defined

傳參問(wèn)題

引言

  • 在學(xué)習(xí)Java的時(shí)候,都討論過(guò)傳引用還是傳值的問(wèn)題
  • Python中全部都是傳用

使用案例

"""
函數(shù)傳參時(shí),實(shí)際上是把實(shí)參賦值給形參
由形參來(lái)完成函數(shù)主體的運(yùn)算
"""
def add(aa, bb):
    aa += bb
    return aa


a, b = 1, 2
c = add(a, b)
"""
函數(shù)調(diào)用之后
aa = 1, bb = 2
aa += bb => aa = aa + bb
int 是不可變類型,內(nèi)存中會(huì)增加一塊空間來(lái)存儲(chǔ)(aa+bb),然后將aa標(biāo)簽貼在上面
a 沒(méi)變,b也沒(méi)變
"""

x, y = [1, 2], [3]
z = add(x, y)
"""
函數(shù)調(diào)用之后
aa = [1, 2], bb = [3]
結(jié)合鴨子類型,以及前面講的魔法函數(shù),可以知道,此時(shí)會(huì)調(diào)用aa.extend(bb)
list是可變類型,直接在原地修改,aa和a都指向[1, 2]
a 變了,b沒(méi)變
"""

m, n = (1, 2), (3,)
p = add(m, n)
"""
和整數(shù)一樣
"""

print(a, b, c)
print(x, y, z)
print(m, n, p)

# result:
# 1 2 3
# [1, 2, 3] [3] [1, 2, 3]
# (1, 2) (3,) (1, 2, 3)

默認(rèn)值問(wèn)題

# 返回一個(gè)名字列表
def name_list(li=[]):
    # 這里可能對(duì)列表做一些包裝
    # todo
    # print(id(li))     # for later use
    return li

# 創(chuàng)建出兩個(gè)空的名字列表
x = name_list()
y = name_list()

# 在 x 中添加一個(gè)名字
x.append("MetaTian")
print(x, y)

# result:
# ['MetaTian'] ['MetaTian']

我們創(chuàng)建出兩個(gè)空的名字列表,稍后給其中一個(gè)添加了一個(gè)名字。結(jié)果,這兩個(gè)名字列表是一樣的,我們?cè)賮?lái)看下二者的id

print(id(x), id(y))

# result:
# 2499670504072 2499670504072

兩者id是一樣的,說(shuō)明兩者指向同一個(gè)對(duì)象,那這個(gè)對(duì)象又是什么呢?其實(shí)它就是函數(shù)參數(shù)列表中一個(gè)變量的默認(rèn)值,就是那個(gè)空列表,可以自己在代碼中打開(kāi)注釋,打印liid即可驗(yàn)證。

Python中,一切皆對(duì)象,函數(shù)也是一個(gè)對(duì)象,那么函數(shù)是什么類型的呢?

print(type(name_list))

# result:
# <class 'function'>

當(dāng)解釋器執(zhí)行到def關(guān)鍵字時(shí),它會(huì)結(jié)合下面的代碼生成一個(gè)函數(shù)對(duì)象,而我們提供的參數(shù)默認(rèn)值,就被當(dāng)做對(duì)象的一種屬性封裝起來(lái)了。于是,后面的兩次函數(shù)調(diào)用,都是將這個(gè)對(duì)象賦值給了x, y兩個(gè)變量。也就是說(shuō)x, y指向了同一個(gè)對(duì)象。

最后編輯于
?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 包(lib)、模塊(module) 在Python中,存在包和模塊兩個(gè)常見(jiàn)概念。 模塊:編寫Python代碼的py...
    清清子衿木子水心閱讀 3,913評(píng)論 0 27
  • 一、Python簡(jiǎn)介和環(huán)境搭建以及pip的安裝 4課時(shí)實(shí)驗(yàn)課主要內(nèi)容 【Python簡(jiǎn)介】: Python 是一個(gè)...
    _小老虎_閱讀 6,339評(píng)論 0 10
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒(méi)有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,674評(píng)論 1 32
  • 可能是因?yàn)樯婕暗讲荒芨淖兊默F(xiàn)實(shí)及記憶,這部片子看了會(huì)讓人有種在人生的某處泥足深陷的感覺(jué)。過(guò)去、他人、社會(huì),這些東西...
    聞卻危閱讀 150評(píng)論 0 1
  • 硬件:處理器,高速緩存和主內(nèi)存間的交互關(guān)系 線程,主內(nèi)存,工作內(nèi)存的關(guān)系 線程對(duì)變量所有操作(讀取,賦值)等必須在...
    簡(jiǎn)書徐小耳閱讀 516評(píng)論 0 0

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