Python变量的理解与内存管理
Python變量與內(nèi)存管理
–與C語言中的變量做對比,更好的理解Python的變量。
變量
變量在C語言中
全局變量:其存放在內(nèi)存的靜態(tài)變量區(qū)中。
局部變量:代碼塊中存放在內(nèi)存的代碼區(qū)當(dāng)中,當(dāng)被調(diào)用后存放在內(nèi)存棧區(qū)。
Python中的變量與變量存儲(chǔ)–引用與對象
Python作為OOP(面向?qū)ο?#xff09;編程,一直信奉著一個(gè)信條,就是萬物皆對象。
所謂對象,它可以看成經(jīng)過一系列的抽象以后,將具有共性的一類物體進(jìn)行實(shí)例化(具象化)的個(gè)體,就如同我們每個(gè)人就是人類里面的一個(gè)對象。
輸出的是:
class ‘function’
class ‘int’
class ‘main.A’
class ‘list’
class ‘dict’
class ‘tuple’
class ‘str’
很明顯,Python中不管是基礎(chǔ)數(shù)據(jù)類型,類,函數(shù),所有的一切都是作為一個(gè)類的對象存儲(chǔ)在內(nèi)存,也可以單純的看做一個(gè)值。
而Python的變量就是作為一個(gè)引用,讀取對象所存儲(chǔ)的信息,與C面向過程所不同,Python變量即對象的引用,通俗來說就是指向值的名稱。
所以Python的變量只是不過對于一塊指定內(nèi)存的引用,也即對對象的引用,或者稱為指向值的名稱,相對于全局變量,局部變量的賦值只是引用另一塊內(nèi)存。C語言中一個(gè)變量代表一塊特定的內(nèi)存,而Python不像C語言,可以看成數(shù)據(jù)已經(jīng)存放在內(nèi)存之中了,被Python的變量對內(nèi)存進(jìn)行引用。即使變量不存在了,內(nèi)存里值也不會(huì)受到任何影響。
if __name__ == "__main__":a = 1b = 2print(id(a))print(id(b))a = bprint(id(a))print(id(1))print(id(2))sys.exit(0)輸出的是:
10919424
10919456
10919456
10919424
10919456
從輸出結(jié)果來看,很明顯同一塊內(nèi)存數(shù)據(jù)其實(shí)是可以被多個(gè)變量引用,且常量和變量的內(nèi)存地址是相對應(yīng)的。
輸出結(jié)果:
10919424
10919424
10919456
10919424
從輸出結(jié)果可以看出,若是當(dāng)全局變量和局部變量的數(shù)值一致時(shí),其對應(yīng)的內(nèi)存地址是一致的,當(dāng)全局變量被賦予其他值時(shí),其內(nèi)存地址發(fā)生改變,而局部變量未有變化。
總結(jié):Python變量的定義和賦值是同時(shí)進(jìn)行的,Python的全局變量和局部變量的定義聲明時(shí),是基于內(nèi)存已有數(shù)據(jù)的基礎(chǔ)上,為變量分配地址進(jìn)行引用,變量即對象的引用,而不是分別分配一塊內(nèi)存進(jìn)行賦值,所以變量不進(jìn)行賦值的話就會(huì)出現(xiàn)未定義的錯(cuò)誤,,這時(shí)就會(huì)出現(xiàn)一個(gè)問題,這將會(huì)造成一個(gè)問題就是對象和數(shù)據(jù)將會(huì)越來越多,會(huì)消耗很大的內(nèi)存空間,這時(shí)將會(huì)啟動(dòng)Python的垃圾回收機(jī)制,當(dāng)某一段內(nèi)存塊的引用計(jì)數(shù)為0時(shí)進(jìn)行回收,這個(gè)是后話了。
變量的作用域—看不見的字典
C語言中每一對大括號作為一個(gè)代碼塊,if,for,while,switch語句是可以加上大括號的作為一個(gè)塊級作用域,for,while()語句在括號中定義的變量是包含在大括號里面的,就是包含在大括號的作用域里,而每一個(gè)代碼塊就是一個(gè)局部的作用域,所有代碼塊內(nèi)部變量優(yōu)先級大于代碼塊外的同名變量。
Python的作用域,就如同是Python的基礎(chǔ)類型中的一部字典,在這部字典里記錄著值(對象)與指向值的名稱(變量),不同的作用域組成了不同的字典,而Python中能改變變量作用域的關(guān)鍵字只有class,def,lamba,所以在Python的關(guān)鍵語句(if,for,while…)中是不進(jìn)行作用域的劃分的,所以在(if,for,while…)語句對變量進(jìn)行賦值,其變量的作用域可以被外部所引用。
并且Python不存在塊級作用域,在嵌套作用域中會(huì)生成作用域鏈,由內(nèi)到外,引用時(shí)優(yōu)先選取內(nèi)部同名變量。
在類與實(shí)例的作用域中
輸出的是:
A name id = 140654891768216
set global name = 140654890720536
set.name = xxx
A id = 20336920
a id = 140654890787168
A.name = 140654891768216
a.name id = 140654890720704
A.what id = 140654890720536
a.what id = 140654890720536
A.set id = 140654690844744
a.set id = 140654891845576
所以,作用域是對于變量而言的而不是內(nèi)存而言,類與實(shí)例的作用域也是嵌套的
參考LEGB法則:
Local(本地作用域)–>Enclosing(閉包作用域)–>Global(全局作用域)–>Built-in(內(nèi)建作用域)
函數(shù)內(nèi)部–>嵌套函數(shù)內(nèi)部–>模塊內(nèi)部–>Python內(nèi)建
LEGB法則: 當(dāng)在函數(shù)中使用未確定的變量名時(shí),Python會(huì)按照優(yōu)先級依次搜索4個(gè)作用域,以此來確定該變量名的意義。首先搜索局部作用域(L),之后是上一層嵌套結(jié)構(gòu)中def或lambda函數(shù)的閉包作用域(E),之后是全局作用域(G),最后是內(nèi)建作用域(B)。按這個(gè)查找原則,在第一處找到的地方停止。如果沒有找到,則會(huì)發(fā)出錯(cuò)誤。
變量作用域在定義時(shí)已經(jīng)設(shè)定好,與調(diào)用的位置無關(guān)。
輸出的是:
???
所以變量的作用域與是否調(diào)用無關(guān),在變量定義時(shí)所處作用域已經(jīng)設(shè)定完成。
變量的生命周期—只要被需要便存在
C語言的局部變量是在函數(shù)調(diào)用完畢后進(jìn)行自動(dòng)銷毀,釋放棧區(qū)。
而基于Python存儲(chǔ)方式的特殊性,所以變量在函數(shù)調(diào)用完畢之后,并未立刻銷毀,對于Python的變量和變量所引用的對象,是使用類似堆的方式管理內(nèi)存,由Python內(nèi)部機(jī)制統(tǒng)一分配回收內(nèi)存,當(dāng)內(nèi)存的某一對象或者變量的引用計(jì)數(shù)為0時(shí)則由Python的內(nèi)存管理機(jī)制收回內(nèi)存,或者對對象手動(dòng)del掉對象以釋放內(nèi)存,不過del掉的對象不影響對象中依然被外部變量有引用的值。
輸出結(jié)果是:
39697096
1409448784
39697096
1409448784
1409448784
當(dāng)函數(shù)被調(diào)用完,只要類實(shí)例還被引用,那么類實(shí)例依然存在類似c++的new,當(dāng)del對象時(shí),不影響對象還在被外部變量引用的值。
當(dāng)我們?nèi)羰莇el掉classA后,再輸入print(id(classA)),會(huì)出現(xiàn)如下錯(cuò)誤:
總結(jié)
以上是生活随笔為你收集整理的Python变量的理解与内存管理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 虚拟服务器启动顺序,虚拟机开机启动项设置
- 下一篇: 软考——程序设计语言概述