Python 可變 不可變物件和賦值技巧序列解包

2022-03-21 10:34:19 字數 3603 閱讀 9475

在python中一切皆物件。在python中不存在所謂的值傳遞呼叫,一切傳遞都是物件的引用,也可認為是傳址。

python中,物件分為可變(mutable)和不可變(immutable)兩種型別,元組(tuple)、數值型(number)、字串(string)均為不可變物件,而字典型(dictionary)和列表型(list)的物件是可變物件。

見乙個例子,分析不可變物件的特點

python內建id()函式,用於返回物件的唯一標識(identity)。id()返回的是十進位制,物件實際記憶體位址為hex(id(object)),本文中將id()與hex(id())等價使用。

>>> a = 1 #將變數a與記憶體中的值為1的記憶體繫結在一起

>>> a = 2 # 將變數a與記憶體中值為2的記憶體繫結在一起,並不是修改原來a繫結的記憶體中的值,

# 這時,原來的這個值為1的記憶體位址的引用次數減一,當引用計數為0時,記憶體位址被**

>>> b = a # 變數b繫結與a一樣的記憶體

>>> id(b),id(a) # 列印a,b的繫結的記憶體位址

(1972461824, 1972461824)

>>> b = 3 # 建立乙個記憶體值為3的記憶體位址與變數名字b進行繫結。這時,a還是指向值為2的記憶體位址

>>> a,b

(2, 3)

>>> id(b),id(a) # 列印a,b的繫結的記憶體位址

(1972461856, 1972461824)

>>> x = 1

>>> y = 1

>>> z = 1

>>> x is y

true

>>> y is z

true

>>> id(x),id(y),id(z)

(1972461792, 1972461792, 1972461792)

從第二個例子可看出因為整數為不可變物件,x,y,z在記憶體中均指向乙個值為1的記憶體位址。

不可變物件最大的優點便是減少重複的值對記憶體空間的占用。

缺點便是如第乙個例子中所示,我要修改這個變數繫結的值,如果記憶體中沒有存在該值的記憶體塊,那麼必須重新開闢一塊記憶體,把新位址與變數名繫結。

而不是修改變數原來指向的記憶體塊的值,這回給執行效率帶來一定的降低。

原來的記憶體塊會因變數與其他記憶體塊繫結而引用次數減1.

下面是對第乙個例子的**

繼續看乙個例子

例1

>>> a = [1]

>>> b = a # a,b繫結同一記憶體位址,記憶體中值為[1]

>>> id(a),id(b)

(1991064334856, 1991064334856)

>>> a,b

([1, 2], [1, 2])

變數名a和b是繫結的同一記憶體位址,對任乙個變數對應的值的修改,都會反映到另乙個變數上。也就是說對可變物件的操作,是直接對這個物件進行改變。

例2

>>> a =[1]

>>> b=[1]

>>> id(a),id(b)

(1991065258248, 1991064760520)

由此可見,在可變物件中值相同的變數繫結的不一定是相同的記憶體位址,會指向不同的物件。

例3在函式預設形參值中使用可變物件會出現乙個大坑見例子:

>>> def add_end(l=):

... return l

...>>> add_end([1,2])

[1, 2, 'end']

>>> add_end([a,b])

[[1], [1], 'end']

>>> add_end()

['end']

>>> add_end()

['end', 'end']

>>> add_end()

['end', 'end', 'end']

這裡當正常傳參呼叫函式時一切正常,可是不斷呼叫帶預設形參是值得函式時,我們覺得的答案應該是['end'],但是彷彿次呼叫都記住了上次的值。

這原因為何?

這看起來有點像是每次呼叫的預設形參值變化了。我們用add_end.__defaults__來檢視函式物件的預設引數變化情況

>>> def add_end(l=):

... return l

...>>> add_end.__defaults__

(,)>>> add_end()

['end']

>>> add_end.__defaults__

(['end'],)

>>> add_end()

['end', 'end']

>>> add_end()

['end', 'end', 'end']

>>> add_end.__defaults__

(['end', 'end', 'end'],)

由上可知每呼叫一次帶預設形參值的函式,該函式物件的預設形參值就會發生變化,所以下次呼叫的預設形參值就是變化過後的。究其原因還是因為預設形參值為可變物件,導致每次呼叫會改變預設形參值

所以,在程式設計時可盡量將物件設計為不變物件,可以避免一些麻煩。

將含多個值的序列解開,放到變數的序列中。解包序列中元素的數量必須和賦值符號=左邊變數數量一致,否則會報錯,引數太多或太少。

>>> values = 1,2,3

>>> values

(1, 2, 3)

>>> x,y,z = values

>>> print(x,y,z)

1 2 3

>>> a,b,c = 1,2,3,4,5

traceback (most recent call last):

file "", line 1, in valueerror: too many values to unpack (expected 3)

>>> a,b,c=1,2

traceback (most recent call last):

file "", line 1, in valueerror: not enough values to unpack (expected 3, got 2)

當解包序列中的元素多多餘變數數量時,變數序列中可以使用星號運算子*,對值進行收集

>>> a,b,*c=1,2,3,4,5

>>> print(a,b,c)

1 2 [3, 4, 5]

python 可變物件和不可變物件

變數沒有型別,那麼就意味著它可以隨意指向任何物件。python中的變數相當於乙個指標。當將乙個變數a賦值給另乙個變數b時,無論變數a指向的是可變物件還是不可變物件,變數b指向變數a指向的物件。例 alist 1 2,3 anolist alist id alist id anolist true b...

Python可變物件和不可變物件

python中一切皆物件,每個物件都有其唯一的id,對應的型別和值,其中id指的是物件在記憶體中的位置。根據物件的值是否可修改分為可變物件和不可變物件。其中,不可物件包括 數字,字串,tuple,frozenset 不可變集合 可變物件包括 list,dict,set python中的變數可以指向任...

Python 可變物件和不可變物件

python在heap中分配的物件分成兩類 可變物件和不可變物件。所謂可變物件是指,物件的內容是可變的,例如list。而不可變的物件則相反,表示其內容不可變。一 不可變物件 由於python中的變數存放的是物件引用,所以對於不可變物件而言,儘管物件本身不可變,但變數的物件引用是可變的。從上面得知,不...