日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

Python变量的理解与内存管理

發布時間:2023/12/15 python 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Python变量的理解与内存管理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Python變量與內存管理

  –與C語言中的變量做對比,更好的理解Python的變量。

變量

變量在C語言中
  全局變量:其存放在內存的靜態變量區中。
  局部變量:代碼塊中存放在內存的代碼區當中,當被調用后存放在內存棧區。

而Python的變量存儲,則是使用類似堆的方式管理內存,由Python內部機制統一分配回收內存。

Python中的變量與變量存儲–引用與對象

  Python作為OOP(面向對象)編程,一直信奉著一個信條,就是萬物皆對象。
  所謂對象,它可以看成經過一系列的抽象以后,將具有共性的一類物體進行實例化(具象化)的個體,就如同我們每個人就是人類里面的一個對象。

class A():name = "123"def __init__(self):passdef funa(self):pass def funa():passif __name__ == "__main__":Fun = funaVariable = 1ClassA = A()ListA = [1,2,3]DictA = {'d':1,'e':2}TupleA = (1,2,3)Str = "python"print(type(Fun))print(type(Variable))print(type(ClassA))print(type(ListA))print(type(DictA))print(type(TupleA))print(type(Str))

輸出的是:
class ‘function’
class ‘int’
class ‘main.A’
class ‘list’
class ‘dict’
class ‘tuple’
class ‘str’

  很明顯,Python中不管是基礎數據類型,類,函數,所有的一切都是作為一個類的對象存儲在內存,也可以單純的看做一個值。

  而Python的變量就是作為一個引用,讀取對象所存儲的信息,與C面向過程所不同,Python變量即對象的引用,通俗來說就是指向值的名稱。
  

  所以Python的變量只是不過對于一塊指定內存的引用,也即對對象的引用,或者稱為指向值的名稱,相對于全局變量,局部變量的賦值只是引用另一塊內存。C語言中一個變量代表一塊特定的內存,而Python不像C語言,可以看成數據已經存放在內存之中了,被Python的變量對內存進行引用。即使變量不存在了,內存里值也不會受到任何影響。

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
  從輸出結果來看,很明顯同一塊內存數據其實是可以被多個變量引用,且常量和變量的內存地址是相對應的。
  
 

def funa():a = 1print(id(a))if __name__ == "__main__":a = 1funa()print(id(a))a = 2print(id(a))funa()sys.exit(0)

輸出結果:
10919424
10919424
10919456
10919424

  從輸出結果可以看出,若是當全局變量和局部變量的數值一致時,其對應的內存地址是一致的,當全局變量被賦予其他值時,其內存地址發生改變,而局部變量未有變化。
  
  
  總結:Python變量的定義和賦值是同時進行的,Python的全局變量和局部變量的定義聲明時,是基于內存已有數據的基礎上,為變量分配地址進行引用,變量即對象的引用,而不是分別分配一塊內存進行賦值,所以變量不進行賦值的話就會出現未定義的錯誤,,這時就會出現一個問題,這將會造成一個問題就是對象和數據將會越來越多,會消耗很大的內存空間,這時將會啟動Python的垃圾回收機制,當某一段內存塊的引用計數為0時進行回收,這個是后話了。

變量的作用域—看不見的字典

  C語言中每一對大括號作為一個代碼塊,if,for,while,switch語句是可以加上大括號的作為一個塊級作用域,for,while()語句在括號中定義的變量是包含在大括號里面的,就是包含在大括號的作用域里,而每一個代碼塊就是一個局部的作用域,所有代碼塊內部變量優先級大于代碼塊外的同名變量。
  
  Python的作用域,就如同是Python的基礎類型中的一部字典,在這部字典里記錄著值(對象)與指向值的名稱(變量),不同的作用域組成了不同的字典,而Python中能改變變量作用域的關鍵字只有class,def,lamba,所以在Python的關鍵語句(if,for,while…)中是不進行作用域的劃分的,所以在(if,for,while…)語句對變量進行賦值,其變量的作用域可以被外部所引用。
  并且Python不存在塊級作用域,在嵌套作用域中會生成作用域鏈,由內到外,引用時優先選取內部同名變量。
  在類與實例的作用域中
  

class A():name = 'x'what = 'xx'print('A name id =',id(name))def __init__(self,name,age):self.name = 'xxx'self.age = 18def set(self):self.name = 'xxx'self.age = 18global namename = 'xx'print('set global name = ',id(name))#與A.what的內存地址相同print('set.name = ',self.name)#作用域是對于變量而言的而不是內存而言if __name__ == "__main__":a = A('xx',18)a.set()print('A id = ', id(A))print('a id = ', id(a))print('A.name = ',id(A.name))print('a.name id = ',id(a.name))print('A.what id = ', id(A.what))print('a.what id = ',id(a.what))print('A.set id = ', id(A.set))print('a.set id = ', id(a.set))sys.exit(0)

輸出的是:
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

  所以,作用域是對于變量而言的而不是內存而言,類與實例的作用域也是嵌套的
  
  
  參考LEGB法則:
  Local(本地作用域)–>Enclosing(閉包作用域)–>Global(全局作用域)–>Built-in(內建作用域)
  函數內部–>嵌套函數內部–>模塊內部–>Python內建
  LEGB法則: 當在函數中使用未確定的變量名時,Python會按照優先級依次搜索4個作用域,以此來確定該變量名的意義。首先搜索局部作用域(L),之后是上一層嵌套結構中def或lambda函數的閉包作用域(E),之后是全局作用域(G),最后是內建作用域(B)。按這個查找原則,在第一處找到的地方停止。如果沒有找到,則會發出錯誤。
  變量作用域在定義時已經設定好,與調用的位置無關。

name ="???" def funa():print(name)def funb():name = "123"funa()if __name__ == "__main__":funa()sys.exit(0)

輸出的是:
???
  所以變量的作用域與是否調用無關,在變量定義時所處作用域已經設定完成。
  

變量的生命周期—只要被需要便存在

  C語言的局部變量是在函數調用完畢后進行自動銷毀,釋放棧區。
  
   而基于Python存儲方式的特殊性,所以變量在函數調用完畢之后,并未立刻銷毀,對于Python的變量和變量所引用的對象,是使用類似堆的方式管理內存,由Python內部機制統一分配回收內存,當內存的某一對象或者變量的引用計數為0時則由Python的內存管理機制收回內存,或者對對象手動del掉對象以釋放內存,不過del掉的對象不影響對象中依然被外部變量有引用的值。
  
  

class A():def __init__(self):self.a = 123def funa(self):c = a+1print(id(c)) variable = None classA = Nonedef initA():global classAglobal variablee = A()variable = e.aclassA = eprint(id(e))print(id(e.a))if __name__ == "__main__":a = 1e = NoneinitA()print(id(classA))print(id(variable))del classA#print(id(classA))print(id(variable))sys.exit(0)

輸出結果是:
39697096
1409448784
39697096
1409448784
1409448784
   當函數被調用完,只要類實例還被引用,那么類實例依然存在類似c++的new,當del對象時,不影響對象還在被外部變量引用的值。
   
  當我們若是del掉classA后,再輸入print(id(classA)),會出現如下錯誤:

Traceback (most recent call last):File "C:/Users/Administrator/PycharmProjects/pysidetest/demo.py", line 69, in <module>print(id(classA)) NameError: name 'classA' is not defined

總結

以上是生活随笔為你收集整理的Python变量的理解与内存管理的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。