日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

解密 Python 的變量和對象,它們之間有什么區別和聯系呢?

來源: 責編: 時間:2024-05-08 09:17:06 228觀看
導讀Python 中一切皆對象在學習 Python 的時候,你肯定聽過這么一句話:Python 中一切皆對象。沒錯,在 Python 世界里,一切都是對象。整數是一個對象、字符串是一個對象、字典是一個對象,甚至 int, str, list 以及我們使用 class

Python 中一切皆對象

bYN28資訊網——每日最新資訊28at.com

bYN28資訊網——每日最新資訊28at.com

在學習 Python 的時候,你肯定聽過這么一句話:Python 中一切皆對象。沒錯,在 Python 世界里,一切都是對象。整數是一個對象、字符串是一個對象、字典是一個對象,甚至 int, str, list 以及我們使用 class 關鍵字自定義的類,它們也是對象。bYN28資訊網——每日最新資訊28at.com

像 int, str, list 等基本類型,以及自定義的類,由于它們可以表示類型,因此我們稱之為類型對象;類型對象實例化得到的對象,我們稱之為實例對象。但不管是哪種對象,它們都屬于對象。bYN28資訊網——每日最新資訊28at.com

因此 Python 將面向對象理念貫徹的非常徹底,面向對象中的類和對象在 Python 中都是通過對象實現的。bYN28資訊網——每日最新資訊28at.com

在面向對象理論中,存在著類和對象兩個概念,像 int、dict、tuple、以及使用 class 關鍵字自定義的類型對象實現了面向對象理論中類的概念,而 123、3.14,"string" 等等這些實例對象則實現了面向對象理論中對象的概念。但在 Python 里面,面向對象的類和對象都是通過對象實現的。bYN28資訊網——每日最新資訊28at.com

我們舉個例子:bYN28資訊網——每日最新資訊28at.com

# dict 是一個類,因此它屬于類型對象# 類型對象實例化得到的對象屬于實例對象print(dict)"""<class 'dict'>"""print(dict(a=1, b=2))"""{'a': 1, 'b': 2}"""

因此可以用一張圖來描述面向對象在 Python 中的體現。bYN28資訊網——每日最新資訊28at.com

圖片圖片bYN28資訊網——每日最新資訊28at.com

而如果想查看一個對象的類型,可以使用 type,或者通過對象的 __class__ 屬性。bYN28資訊網——每日最新資訊28at.com

numbers = [1, 2, 3]# 查看類型print(type(numbers))"""<class 'list'>"""print(numbers.__class__)"""<class 'list'>"""

如果想判斷一個對象是不是指定類型的實例對象,可以使用 isinstance。bYN28資訊網——每日最新資訊28at.com

numbers = [1, 2, 3]# 判斷是不是指定類型的實例對象print(isinstance(numbers, list))"""True"""

但是問題來了,按照面向對象的理論來說,對象是由類實例化得到的,這在 Python 中也是適用的。既然是對象,那么就必定有一個類來實例化它,換句話說對象一定要有類型。bYN28資訊網——每日最新資訊28at.com

至于一個對象的類型是什么,就看這個對象是被誰實例化的,被誰實例化那么類型就是誰,比如列表的類型是 list,字典的類型是 dict 等等。bYN28資訊網——每日最新資訊28at.com

而 Python 中一切皆對象,所以像 int, str, tuple 這些內置的類對象也是具有相應的類型的,那么它們的類型又是誰呢?使用 type 查看一下就知道了。bYN28資訊網——每日最新資訊28at.com

>>> type(int)<class 'type'>>>> type(str)<class 'type'>>>> type(dict)<class 'type'>>>> type(type)<class 'type'>

我們看到類型對象的類型,無一例外都是 type。而 type 我們也稱其為元類,表示類型對象的類型。至于 type 本身,它的類型還是 type,所以它連自己都沒放過,把自己都變成自己的對象了。bYN28資訊網——每日最新資訊28at.com

因此在 Python 中,你能看到的任何對象都是有類型的,可以使用 type 查看,也可以獲取該對象的 __class__ 屬性查看。所以:實例對象、類型對象、元類,Python 中任何一個對象都逃不過這三種身份。bYN28資訊網——每日最新資訊28at.com

到這里可能有人會發現一個有意思的點,我們說 int 是一個類對象,這顯然是沒有問題的。因為站在整數(比如 123)的角度上,int 是一個不折不扣的類對象;但如果站在 type 的角度上呢?顯然我們又可以將 int 理解為實例對象,因此 class 具有二象性。bYN28資訊網——每日最新資訊28at.com

至于 type 也是同理,雖然它是元類,但本質上也是一個類對象。bYN28資訊網——每日最新資訊28at.com

注:不僅 type 是元類,那些繼承了 type 的類也可以叫做元類。bYN28資訊網——每日最新資訊28at.com

然后 Python 中還有一個關鍵的類型(對象),叫做 object,它是所有類型對象的基類。不管是什么類,內置的類也好,我們自定義的類也罷,它們都繼承自 object。因此 object 是所有類型對象的基類、或者說父類。bYN28資訊網——每日最新資訊28at.com

那如果我們想獲取一個類都繼承了哪些基類,該怎么做呢?方式有三種:bYN28資訊網——每日最新資訊28at.com

class A: passclass B: passclass C(A): passclass D(B, C): pass# 首先 D 繼承自 B 和 C, C 又繼承 A# 我們現在要來查看 D 繼承的父類# 方法一: 使用 __base__print(D.__base__)  """<class '__main__.B'>"""# 方法二: 使用 __bases__print(D.__bases__)  """(<class '__main__.B'>, <class '__main__.C'>)"""# 方法三: 使用 __mro__print(D.__mro__)"""(<class '__main__.D'>, <class '__main__.B'>,  <class '__main__.C'>, <class '__main__.A'>,  <class 'object'>)"""
  • __base__:如果繼承了多個類,那么只顯示繼承的第一個類,沒有顯式繼承則返回 <class 'object'>
  • __bases__:返回一個元組,會顯示所有直接繼承的父類,沒有顯式繼承則返回 (<class 'object'>,)
  • __mro__: mro(Method Resolution Order)表示方法查找順序,會從自身出發,找到最頂層的父類。因此返回自身、繼承的基類、以及基類繼承的基類, 一直找到 object

而如果想查看某個類型是不是另一個類型的子類,可以通過 issubclass。bYN28資訊網——每日最新資訊28at.com

print(issubclass(str, object))"""True"""

因此,我們可以得出以下兩個結論:bYN28資訊網——每日最新資訊28at.com

  • type 站在類型金字塔的最頂端,任何一個對象按照類型追根溯源,最終得到的都是 type;
  • object 站在繼承金字塔的最頂端,任何一個類型對象按照繼承關系追根溯源,最終得到的都是 object;

但要注意的是,我們說 type 的類型還是 type,但 object 的基類則不再是 object,而是 None。bYN28資訊網——每日最新資訊28at.com

print(    type.__class__)  # <class 'type'># 注:以下打印結果容易讓人產生誤解# 它表達的含義是 object 的基類為空# 而不是說 object 繼承 Noneprint(    object.__base__)  # None

但為什么 object 的基類是 None,而不是它自身呢?其實答案很簡單,Python 在查找屬性或方法的時候,自身如果沒有的話,會按照 __mro__ 指定的順序去基類中查找。所以繼承鏈一定會有一個終點,否則就會像沒有出口的遞歸一樣出現死循環了。bYN28資訊網——每日最新資訊28at.com

我們用一張圖將對象之間的關系總結一下:bYN28資訊網——每日最新資訊28at.com

圖片圖片bYN28資訊網——每日最新資訊28at.com

  • 實例對象的類型是類型對象,類型對象的類型是元類;
  • 所有類型對象的基類都收斂于 object;
  • 所有對象的類型都收斂于 type;

因此 Python 算是將一切皆對象的理念貫徹到了極致,也正因為如此,Python 才具有如此優秀的動態特性。bYN28資訊網——每日最新資訊28at.com

但是還沒結束,我們再重新審視一下上面那張圖,會發現里面有兩個箭頭看起來非常的奇怪。object 的類型是 type,type 又繼承了 object。bYN28資訊網——每日最新資訊28at.com

>>> type.__base__<class 'object'>>>> object.__class__<class 'type'>

因為 type 是所有類的元類,而 object 是所有類的基類,這就說明 type 要繼承自 object,而 object 的類型是 type。很多人都會對這一點感到奇怪,這難道不是一個先有雞還是先有蛋的問題嗎?其實不是的,這兩個對象是共存的,它們之間的定義其實是互相依賴的。而具體是怎么一回事,我們后續分析。bYN28資訊網——每日最新資訊28at.com

bYN28資訊網——每日最新資訊28at.com

Python 的變量其實是指針

bYN28資訊網——每日最新資訊28at.com

bYN28資訊網——每日最新資訊28at.com

Python 的變量只是一個名字,如果站在 C 語言的角度來看,那么就是一個指針。所以 Python 的變量保存的其實是對象的內存地址,或者說指針,而指針指向的內存存儲的才是對象。bYN28資訊網——每日最新資訊28at.com

所以在 Python 中,我們都說變量指向了某個對象。在其它靜態語言中,變量相當于是為某塊內存起的別名,獲取變量等于獲取這塊內存所存儲的值。而 Python 中變量代表的內存所存儲的不是對象,而是對象的指針(或者說引用)。bYN28資訊網——每日最新資訊28at.com

我們舉例說明,看一段 C 代碼。bYN28資訊網——每日最新資訊28at.com

#include <stdio.h>void main(){    int a = 666;    printf("address of a = %p/n", &a);    a = 667;    printf("address of a = %p/n", &a);}

編譯執行一下:bYN28資訊網——每日最新資訊28at.com

圖片圖片bYN28資訊網——每日最新資訊28at.com

賦值前后地址都是 0x7fff9eda521c,沒有變化,再來看一段 Python 代碼。bYN28資訊網——每日最新資訊28at.com

a = 666print(hex(id(a)))  # 0x7febf803a3d0a = 667print(hex(id(a)))  # 0x7fec180677b0

我們看到 Python 里面輸出的地址發生了變化,下面分析一下原因。bYN28資訊網——每日最新資訊28at.com

首先在 C 中,創建一個變量的時候必須規定好類型,比如 int a = 666,那么變量 a 就是 int 類型,以后在所處的作用域中就不可以變了。如果這時候再設置 a = 777,那么等于是把內存中存儲的 666 換成 777,a 的地址和類型是不會變化的。bYN28資訊網——每日最新資訊28at.com

而在 Python 中,a = 666 等于是先開辟一塊內存,存儲的值為 666,然后讓變量 a 指向這片內存,或者說讓變量 a 保存這塊內存的地址。然后 a = 777 的時候,再開辟一塊內存,然后讓 a 指向存儲 777 的內存,由于是兩塊不同的內存,所以它們的地址是不一樣的。bYN28資訊網——每日最新資訊28at.com

圖片圖片bYN28資訊網——每日最新資訊28at.com

所以 Python 的變量只是一個和對象關聯的名字,它代表的是對象的指針。換句話說 Python 的變量就是個便利貼,可以貼在任何對象上,一旦貼上去了,就代表這個對象被引用了。bYN28資訊網——每日最新資訊28at.com

bYN28資訊網——每日最新資訊28at.com

值傳遞?引用傳遞?

bYN28資訊網——每日最新資訊28at.com

bYN28資訊網——每日最新資訊28at.com

再來看看變量之間的傳遞,在 Python 中是如何體現的。bYN28資訊網——每日最新資訊28at.com

a = 666print(hex(id(a)))  # 0x1f4e8ca7fb0b = aprint(hex(id(b)))  # 0x1f4e8ca7fb0

我們看到打印的地址是一樣的,再用一張圖解釋一下。bYN28資訊網——每日最新資訊28at.com

圖片圖片bYN28資訊網——每日最新資訊28at.com

a = 666 的時候,先開辟一份內存,再讓 a 存儲對應內存的地址;然后 b = a 的時候,會把 a 拷貝一份給 b,所以 b 和 a 存儲了相同的地址,它們都指向了同一個對象。bYN28資訊網——每日最新資訊28at.com

因此說 Python 是值傳遞、或者引用傳遞都是不準確的,準確的說 Python 是變量的值傳遞,對象的引用傳遞。因為 Python 的變量可以認為是 C 的一個指針,在 b = a 的時候,等于把 a 指向的對象的地址(a 本身)拷貝一份給 b,所以對于變量來說是值傳遞;然后 a 和 b 又都是指向對象的指針,因此對于對象來說是引用傳遞。bYN28資訊網——每日最新資訊28at.com

在這個過程中,對象沒有重復創建,它只是多了一個引用。bYN28資訊網——每日最新資訊28at.com

另外還有最關鍵的一點,Python 的變量是一個指針,當傳遞變量的時候,傳遞的是指針;但是在操作變量的時候,會操作變量指向的內存。所以 id(a) 獲取的不是 a 的地址,而是 a 指向的內存的地址(在底層其實就是 a 本身);同理 b = a,是將 a 本身,或者說將 a 存儲的、指向某個具體的對象的地址傳遞給了 b。bYN28資訊網——每日最新資訊28at.com

另外在 C 的層面,顯然 a 和 b 屬于指針變量,那么 a 和 b 有沒有地址呢?顯然是有的,只不過在 Python 中是獲取不到的,解釋器只允許獲取對象的地址。bYN28資訊網——每日最新資訊28at.com

我們再舉個函數的例子:bYN28資訊網——每日最新資訊28at.com

def some_func(num):    print("address of local num", hex(id(num)))    num = 667    print("address of local num", hex(id(num)))num = 666print("address of global num", hex(id(num)))some_func(num)"""address of global num 0x2356cd698d0address of local num 0x2356cd698d0address of local num 0x2356c457f90"""

函數的參數也是一個變量,所以 some_func(num) 其實就是把全局變量 num 存儲的對象的地址拷貝一份給局部變量 num,所以兩個 num 指向了同一個對象,打印的地址相同。bYN28資訊網——每日最新資訊28at.com

然后在函數內部執行 num = 667,相當于讓局部變量指向新的對象,或者說保存新對象的地址,因此打印的結果發生變化。bYN28資訊網——每日最新資訊28at.com

bYN28資訊網——每日最新資訊28at.com

變量有類型嗎?

bYN28資訊網——每日最新資訊28at.com

bYN28資訊網——每日最新資訊28at.com

當提到類型時,這個類型指的是變量的類型還是對象的類型呢?不用想,肯定是對象的類型。因為 Python 的變量是個指針,操作指針會自動操作它指向的內存,所以使用 type(a) 查看的其實是變量 a 指向的對象的類型。bYN28資訊網——每日最新資訊28at.com

那么問題來了,我們在創建變量的時候,并沒有顯式地指定類型啊,那么 Python 是如何判斷一個變量指向的是什么類型的數據呢?答案是:解釋器是通過靠猜的方式,通過賦的值(或者說變量引用的值)來推斷類型。bYN28資訊網——每日最新資訊28at.com

因此在 Python 中,如果你想創建一個變量,那么必須在創建變量的時候同時賦值,否則解釋器就不知道這個變量指向的數據是什么類型。所以 Python 是先創建相應的值,這個值在 C 中對應一個結構體,結構體里面有一個成員專門用來存儲該值對應的類型,因此在 Python 中,類型是和對象綁定的,而不是和變量。當創建完值之后,再讓這個變量指向它,所以 Python 中是先有值后有變量。bYN28資訊網——每日最新資訊28at.com

但顯然在 C 里面不是這樣的,因為 C 的變量代表的內存所存儲的就是具體的值,所以在 C 里面可以直接聲明一個變量的同時不賦值。因為 C 要求聲明變量時必須指定類型,因此變量聲明之后,其類型和內存大小就已經固定了。bYN28資訊網——每日最新資訊28at.com

而 Python 的變量存的是個地址,它只是指向了某個對象,所以由于其便利貼的特性,可以貼在任意對象上面。但是不管貼在哪個對象,都必須先有對象才可以,不然變量貼誰去。bYN28資訊網——每日最新資訊28at.com

另外,盡管 Python 在創建變量的時候不需要指定類型,但 Python 是強類型語言,而且是動態強類型。bYN28資訊網——每日最新資訊28at.com

bYN28資訊網——每日最新資訊28at.com

小結

bYN28資訊網——每日最新資訊28at.com

bYN28資訊網——每日最新資訊28at.com

以上我們就聊了聊 Python 的變量和對象,核心就在于:變量保存的不是對象本身,而是對象的內存地址,站在 C 的角度上看變量就是一個指針。bYN28資訊網——每日最新資訊28at.com

盡管 Python 一切皆對象,但你拿到的都是對象的指針,變量是一個指針,函數是一個指針,元組、列表、字典里面存儲的還是指針。我們可以想象一下列表,它底層是基于數組實現的,由于 C 數組要求里面的每個元素的類型和大小都相同,因此從這個角度上講,列表內部存儲的只能是指針。bYN28資訊網——每日最新資訊28at.com

本文鏈接:http://m.www897cc.com/showinfo-26-87253-0.html解密 Python 的變量和對象,它們之間有什么區別和聯系呢?

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: TypeScript封裝一個根據背景色顯示適合的字體顏色

下一篇: JavaScript 原生深拷貝方法來啦!structuredClone 閃耀登場~

標簽:
  • 熱門焦點
Top 日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不
一区二区三区偷拍| 亚洲国产欧美精品| 欧美精品乱码久久久久久按摩| 久久久久免费| 久久久国产成人精品| 欧美在线免费| 久久精品欧洲| 久久国产66| 欧美精品在线免费观看| 欧美成人综合| 美女脱光内衣内裤视频久久影院| 欧美另类一区二区三区| 欧美日韩亚洲综合在线| 国产精品久久7| 国产婷婷色一区二区三区在线| 国内精品久久久久久| 99综合精品| 亚洲午夜在线| 亚洲自拍偷拍色片视频| 久久久久久亚洲精品杨幂换脸| 久久午夜精品一区二区| 国产精品日韩欧美一区| 国产小视频国产精品| 国产在线视频欧美| 亚洲三级免费观看| 在线视频中文亚洲| 欧美亚一区二区| 国产精品成人午夜| 国产一区二区三区不卡在线观看| 激情视频一区二区三区| 亚洲精品免费观看| 先锋影院在线亚洲| 欧美成人免费在线观看| 在线播放日韩欧美| 日韩一区二区免费看| 国内精品模特av私拍在线观看| **欧美日韩vr在线| 亚洲一区二区三区高清不卡| 久久成人免费电影| 欧美日韩视频在线一区二区观看视频 | 欧美视频精品一区| 精品动漫av| 欧美在线观看视频一区二区| 国产精品久久久久久久7电影 | 久久综合色一综合色88| 国产亚洲综合性久久久影院| 亚洲免费中文| 国产精品毛片| 久久精品亚洲国产奇米99| 欧美福利在线观看| 欧美日韩国产色视频| 欧美大片在线看| 欧美成人午夜免费视在线看片| 久久精品国产99国产精品| 久久久青草婷婷精品综合日韩 | 欧美日韩另类国产亚洲欧美一级| 在线不卡a资源高清| 老色鬼精品视频在线观看播放| 欧美理论视频| 国产日韩欧美综合一区| 亚洲美女av网站| 免费观看在线综合| 一区在线视频| 久久综合九色综合网站| 国产资源精品在线观看| 久久久国产精品一区| 亚洲国产日韩欧美| 欧美久久久久免费| 亚洲视频香蕉人妖| 国产噜噜噜噜噜久久久久久久久 | 欧美日韩在线观看一区二区三区| 亚洲精品久久久久久久久久久| 欧美暴力喷水在线| 亚洲一区二区免费视频| 国产日韩欧美在线播放不卡| 乱中年女人伦av一区二区| 99亚洲一区二区| 国产精品亚洲产品| 在线亚洲成人| 国产精品yjizz| 欧美一区二区在线播放| 黄色亚洲在线| 欧美精品在线一区二区三区| 亚洲欧美另类在线观看| 国产情侣久久| 欧美精品在线视频| 久久久精品国产99久久精品芒果| 亚洲精品网站在线播放gif| 亚洲亚洲精品三区日韩精品在线视频| 欧美视频一区在线| 亚洲欧美日韩精品综合在线观看| 国产在线精品自拍| 玖玖国产精品视频| 午夜日韩激情| 在线视频精品一区| 黄色成人av在线| 国产精品一区二区三区观看| 欧美精品xxxxbbbb| 美女在线一区二区| 亚洲天堂激情| 亚洲国产女人aaa毛片在线| 欧美日韩亚洲一区在线观看| 久久精品一区四区| 亚洲欧美视频在线观看| 99国产一区二区三精品乱码| 亚洲大片av| 亚洲日本成人网| 亚洲人成啪啪网站| 国产丝袜美腿一区二区三区| 欧美国产在线电影| 欧美精品一区在线播放| 免费成人黄色片| 欧美刺激午夜性久久久久久久| 欧美在线一区二区三区| 亚洲视频日本| 亚洲少妇在线| 亚洲主播在线| 欧美一区二区三区电影在线观看| 久久超碰97人人做人人爱| 美日韩精品免费| 久久久99国产精品免费| 欧美一级理论性理论a| 亚洲字幕一区二区| 亚洲欧美久久久| 欧美一区二区三区视频在线| 久久精品久久99精品久久| 美女图片一区二区| 欧美午夜视频在线观看| 国产精品扒开腿做爽爽爽视频 | 欧美成人综合网站| 欧美区视频在线观看| 国产精品毛片| 亚洲在线日韩| 欧美亚洲一级片| 欧美在线三区| 鲁大师影院一区二区三区| 欧美99久久| 国产美女精品| 亚洲国产影院| 欧美亚洲一区三区| 欧美一级久久| 久久综合色一综合色88| 欧美日韩激情网| 国产女主播视频一区二区| 影音先锋成人资源站| 亚洲一区二区三区乱码aⅴ| 欧美成人午夜影院| 韩日欧美一区二区| 亚洲激情中文1区| 亚洲性色视频| 久久人人看视频| 欧美色播在线播放| 亚洲电影中文字幕| 亚洲一级片在线观看| 欧美精品免费在线观看| 亚洲国产欧美精品| 亚洲男女自偷自拍图片另类| 久久成人这里只有精品| 国产精品va| 亚洲国产日韩欧美综合久久| 欧美综合国产精品久久丁香| 国产精品高潮呻吟视频| 在线视频精品| 欧美日本簧片| 亚洲国产女人aaa毛片在线| 久久久久国产精品一区| 国产美女扒开尿口久久久| 亚洲少妇自拍| 欧美亚一区二区| 午夜国产精品影院在线观看| 欧美激情成人在线视频| 国模私拍视频一区| 性色av一区二区三区在线观看| 欧美视频亚洲视频| 亚洲一区二区视频在线观看| 欧美日韩一级黄| 亚洲自拍都市欧美小说| 欧美日韩国产123区| 夜夜嗨av一区二区三区中文字幕 | 欧美成人高清视频| 在线精品一区二区| 玖玖视频精品| 亚洲第一网站免费视频| 欧美+日本+国产+在线a∨观看| 亚洲二区精品| 欧美日韩免费网站| 欧美亚洲一区二区在线| 欧美日韩在线不卡一区| 日韩亚洲精品电影| 欧美日韩免费观看一区三区| 一本色道久久综合亚洲二区三区| 欧美日韩亚洲一区二| 羞羞答答国产精品www一本| 一区在线观看视频| 欧美成人tv| 99在线精品观看| 黑人一区二区三区四区五区| 久久久999精品视频| 在线免费观看日本欧美| 米奇777在线欧美播放| 亚洲人www| 国产午夜精品理论片a级探花| 久久精品国产96久久久香蕉 | 久久久久久久成人|