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

歡迎訪問 生活随笔!

生活随笔

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

python

python pointer_python 的隐式指针特征与class inheritance

發布時間:2023/12/19 python 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python pointer_python 的隐式指针特征与class inheritance 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

python的隱式指針特征

pointer是C/C++的里非常熟悉也容易令人困惑的一個功能點,python里的變量賦值一般表現也和指針類似,但是沒有顯式地語法指出,·在這里我用自己的理解做一個比喻來幫助大家理解。

當我們寫下一行語句,比如a=1 (python)或者int a=1(C++),電腦內存到底做了什么呢?這里的數據“1”在電腦內存里實際上是一個二級制序列,任何數據最終都以這種形式存儲。而序列儲存的位置,則是這份數據的地址,這個地址在內存中,通過“a”這個代號來獲取。

所以,如果把地址比作是一棟房子,數據就像是房子里裝的家具,而房子門口的門牌號,就是地址的名字。只不過在程序里,一個房子可以有多個門牌號,共同指向同一個房子,但是不能有多個房子,共享同一個門牌號。

a=1,a=2,是更改了a對應房子里存儲的東西(數據)

a=1,b=a,是賦予“1”這個數據所在的房子兩塊門牌號(a,b)

此時修改a,b任意變量名的值,a、b的值均被修改,換句話說,python賦值默認是指針賦值,但是在class內賦值、copy賦值例外。

python class及inheritance

為什么需要class?

答案是我們需要用數據結構來存儲數據的關系,而不是記在腦子里,或者是靠修改變量名稱。比如我們需要程序計算,高中生的各科成績求和。顯然,一個簡單的sum函數可以完成這樣的運算,再來一個for循環,對所有的學生都算一遍。但是這樣做之后,我們無法知道把學生的名字、單科成績、各科成績對應起來,雖然他們在循環中的次序是對應的。如果代碼里稍有不慎修改了成績的原始排序,就會出現驢唇對馬嘴的情況。

class 作為一種復雜的數據結構,能夠幫我們記錄下一個綜合體及其各個屬性的關系,以支持更復雜的操作。

此外還能夠提高代碼可讀性,減少重復代碼塊粘貼,提高效率。

class 數據結構還能繼承,不斷延展功能的同時,不干擾舊的代碼功能,用盡量少的代碼支持更多操作。

基本語法

class A(object):def __init__(self):print('A init called')self.num=1class B(A):def __init__(self):print('B init called')A.__init__(self) a=A() b=B() b.num

首先我們定了一個class 結構A,它的初始化/構造函數(類似于C++里的constructor)打印一句話,并且給自己多了一個成員 num,值為1

然后定義了一個class 結構B,B繼承了A,B的構造函數打印了一句話,然后調用了A的構造函數,這里的調用,等同于把A的_init_函數完全復制到B里,并且執行,也就是繼承了A的init

結果是

A init called #a=A()

B init called#b=B()的構造函數print

A init called#b的init里 call A的init,并且給B增加了一個成員self.num

1 #b.num

更規范的繼承寫法

上邊的例子中,在B的init我們指定繼承A的init,形如baseclass._init_(self),這種寫法在一層繼承中沒有問題,但是在多層繼承中,會喪失靈活性,因為此時,parent class被hard-coded,而不是按照繼承鏈自動追溯,喪失了靈活性。

參考這篇文章的例子

What is the difference between old style and new style classes in Python??stackoverflow.comclass

上邊的代碼中,Unsuperchild class的繼承寫法是固定的,和上邊的class B一樣。而superchild class的繼承方法是使用了super(括號可以省略)關鍵詞,兩者都繼承自somebaseclass。那么到底有什么后果呢?我們再加入一層繼承

class InjectMe(SomeBaseClass):def __init__(self):print('InjectMe.__init__(self) called')super(InjectMe, self).__init__()class UnsuperInjector(UnsuperChild, InjectMe): passclass SuperInjector(SuperChild, InjectMe): pass

InjectMe class 也繼承自somebaseclass。同時UnsuperInjector繼承UnsuperChild,和InjectMe,SuperInjector繼承SuperChild,和InjectMe

現在的繼承關系有三級

somebaseclass (grandparent)

unsuperchild superchild InjectMe (parent)

unsuperinjector superinjector (child)

根據Method Resolution Order (MRO)法則,當我生成一個第三級class 的實例時,會按照“先左后右再向上”的順序調用super

比如我創建一個UnsuperInjector的實例,它的左邊parent是UnsuperChild,先調用了UnsuperChild的init,UnsuperChild的init里寫了,固定調用sombaseclass 的init,因此,不用super()關鍵字繼承時,會受到固定parent class的限制,不會再調用injectme class

o = UnsuperInjector() # 打印 UnsuperChild.__init__(self) called #打印 SomeBaseClass.__init__(self) called

而如果run下邊一句結果就不同

o2 = SuperInjector() SuperChild.__init__(self) called InjectMe.__init__(self) called SomeBaseClass.__init__(self) called

SuperInjector上一級左邊是SuperChild,SuperChild的init里有super().init,,右邊是InjectMe,也有super().init,因此SuperChild的super 指向InjectMe,InjectMe的super指向SomeBaseClass,因此打印結果如上邊代碼塊所示。

總結

在multiple inheritance模式下,super().繼承方法能夠避免固定繼承導致其他parent class繼承失效的問題,增加了代碼靈活性。同時注意繼承的順序由MRO決定,遵循同級先左后右,再增加深度的原則。

總結

以上是生活随笔為你收集整理的python pointer_python 的隐式指针特征与class inheritance的全部內容,希望文章能夠幫你解決所遇到的問題。

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