python的內存分配

1、前言

  大多數編譯型語言,變量在使用前必須先聲明,其中C語言更加苛刻:變量聲明必須位於代碼塊最開始,且在任何其餘語句以前。其餘語言,想C++和java,容許「隨時隨地」聲明變量,好比,變量聲明能夠在代碼塊的中間,不過仍然必須在變量被使用前聲明變量的名字和類型。在Python中,無序此類顯式變量聲明語句,變量在第一次被賦值時自動聲明。和其餘大多數語言同樣,變量只有被建立和賦值後才能被使用。html

複製代碼
 1 # 變量未聲明
 2 >>> x
 3 Traceback (most recent call last):
 4   File "<stdin>", line 1, in <module>
 5 NameError: name 'x' is not defined
 6 
 7 #變量一旦被賦值,就能夠經過變量名來訪問它
 8 
 9 >>> x=1
10 >>> y="It's wonderful."
11 >>> x
12 1
13 >>> y
14 "It's wonderful."
複製代碼

 

2、動態類型

   Python中不但變量名無需事先聲明,並且也無需類型聲明。在Python語言中,對象的類型和內存佔用都是運行時肯定的。儘管代碼被編譯成字節碼,Python仍然是一種解釋型語言。在賦值時解釋器會根據語法和右側的操做數來決定新對象的類型。在對象建立後,一個該對象的應用會被賦值給左側的變量。java

 

3、內存分配

  做爲一個負責任的程序員,咱們知道在爲變量分配內存時,是在借用系統資源,在用完以後,應該釋放借用的系統資源。Python解釋器承擔了內存管理的複雜任務,這大大簡化了應用程序的編寫。程序員

3.1 引用計數

  要保持追蹤內存中的對象,Python使用了引用計數這一簡單技術。也就是說Python內部記錄着全部使用中的對象 各有多少引用。一個內部跟蹤變量,稱爲引用計數器。每一個對象各有多少個引用,簡稱引用計數。當對象被建立時,就建立了一個引用計數,當這個對象再也不須要時,也就是說,這個對象的引用計數變爲0時,它被垃圾回收。(並非100%這樣)函數

 

3.2 增長引用計數

  當對象被建立並賦值給變量時,該對象的引用計數就被設置爲1。spa

    當同一個變量又被賦值給其餘變量時,或做爲參數傳遞給函數、方法或類實例,或者被賦值爲一個窗口對象的成員時,該對象的一個新的引用,或者稱爲別名,就被建立(則該對象的引用計數就自動加1)。code

  以下代碼:  htm

1 >>> x = 3
2 >>> y = x

 

 

 

  語句x=3咱們將3賦值給x。x是第一個引用,所以,該對象的引用計數被設置爲1。語句y=x建立了一個指向同一對象的別名y。事實上並無爲y建立一個新的對象,而是該對象的引用計數增長了一次(變成了2)。這是對象引用計數增長的方式之一。還有一些其餘的方式也能增長對象的引用計數,好比該對象做爲參數被函數調用或這個對象被加入到某個列表等對象當中。對象

   總之,對象的引用計數增長是:blog

  • 對象被建立

    x = 3內存

  • 另外的別名被建立

    y = x

  • 做爲參數傳遞給函數

    foo(x)

  • 成爲容器對象的一部分

    mylist = [1,2,x,'xyz']

 

 3.3 減小引用計數

     當對象的引用被銷燬時,引用計數會減少。最明顯的例子就是當引用離開其做用範圍時,這種狀況最常常出如今函數運行結束時,全部的局部變量都被自動銷燬,對象的引用計數也就隨之減小。

   當變量被賦值給另一個對象時,原對象的引用計數也會自動減1:

1 >>> foo = 'xyz'
2 >>> bar = foo
3 >>> foo = 123

  當字符串對象「xyz」被建立並賦值給foo時,它的引用計數是1。當增長一個別名bar時,引用計數變成了2。不過當foo被從新賦值給整型對象123時,xyz對象的引用計數自動減1,又從新變成了1。

  其餘形成對象引用計數減小的方式包括使用del語句刪除一個變量,或者當一個對象被移出一個窗口對象時。

   對象引用計數減小的狀況:

  • 一個本地引用離開了其做用的範圍。好比foo() 函數結束時。
  •  對象別名被顯式銷燬

    del y

  •  對象的一個別名被賦值給其餘對象

    x = 123

  • 對象被從一個窗口對象中移除

    mylist.remove(x)

  • 窗口對象自己被銷燬

    del mylist

 

4、垃圾收集

  再也不使用的內存會被一種稱爲垃圾收集的機制釋放。像上面說的,雖然解釋器跟蹤對象的引用計數,但垃圾收集器負責釋放內存。垃圾收集器是一塊獨立代碼,它用來尋找計數爲0的對象。它也負責檢查那些雖然引用計數大於0但也應該被銷燬的對象。特定情形會致使循環引用。

相關文章
相關標籤/搜索