當前位置:首頁 » 編程語言 » python繼承初始化類

python繼承初始化類

發布時間: 2023-03-18 16:32:40

A. __init__ 為什麼python類需要初始化

通常構造一個類,用 init 初始化:

為什麼python類需要初始化
1.python 類初始化屬性 def __init__() 中定義,實例化對象後可直接調用
2.python 類非初始化屬性在 def func() 中定義,實例化對象後, 先調用調用函數,再調用屬性

結果:

B. Python類的多重繼承問題深入分析

Python類的多重繼承問題深入分析
首先得說明的是,Python的類分為經典類 和 新式類
經典類是python2.2之前的東西,但是在2.7還在兼容,但是在3之後的版本就只承認新式類了
新式類在python2.2之後的版本中都可以使用
經典類和新式類的區別在於:
經典類是默認沒有派生自某個基類的,而新式類是默認派生自object這個基類的:
代碼如下:
# old style
class A():pass
# new style
class A(obejct):pass
2.經典類在類多重繼承的時候是採用從左到右深度優先原則匹配方法的..而新式類是採用C3演算法(不同於廣度優先)進行匹配的
3.經典類是沒有__MRO__和instance.mro()調用的,而新式類是有的.
為什麼不用經典類,要更換到新式類
因為在經典類中的多重繼承會有些問題...可能導致在繼承樹中的方法查詢繞過後面的父類:
代碼如下:
class A():
def foo1(self):
print "A"
class B(A):
def foo2(self):
pass
class C(A):
def foo1(self):
print "C"
class D(B, C):
pass
d = D()
d.foo1()
按照經典類的查找順序從左到右深度優先的規則,在訪問d.foo1()的時候,D這個類是沒有的..那麼往上查找,先找到B,裡面沒有,深度優先,訪問A,找到了foo1(),所以這時候調用的是A的foo1(),從而導致C重寫的foo1()被繞過.
所以python引入了新式類的廳扒塌概念,每個基類都繼承自object並且,他的匹配此姿規則也從深度優先換到扮圓了C3
C3演算法
C3演算法是怎麼做匹配的呢..在問答版塊上面討論之後,歸結如下:
C3演算法的一個核心是merge.
在merge列表中,如果第一個序列mro的第一個類是出現在其它序列,並且也是第一個,或者不出現其它序列,那麼這個類就會從這些序列中刪除,並合到訪問順序列表中
比如:(引用問題中zhuangzebo的回答@zhuangzebo)
代碼如下:
class A(O):pass
class B(O):pass
class C(O):pass
class D(A,B):pass
class E(C,D):pass

首先需要知道 O(object)的mro(method resolution order)列表是[O,]
那麼接下來是:
代碼如下:
mro(A) = [A, O]
mro(B) = [B, O]
mro(C) = [C, O]
mro(D) = [D] + merge(mro(A), mro(B), [A, B])
= [D] + merge([A, O], [B, O], [A, B])
= [D, A] + merge([O], [B, O], [B])
= [D, A, B] + merge([O], [O])
= [D, A, B, O]
mro(E) = [E] + merge(mro(C), mro(D), [C, D])
= [E] + merge([C, O], [D, A, B, O], [C, D])
= [E, C] + merge([O], [D, A, B, O], [D])
= [E, C, D] + merge([O], [A, B, O])
= [E, C, D, A, B] + merge([O], [O])
= [E, C, D, A, B, O]

然後還有一種特殊情況:
比如:
merge(DO,CO,C) 先merge的是D
merge(DO,CO,C) 先merge的是C
意思就是.當出現有 一個類出現在兩個序列的頭(比如C) 這種情況和 這個類只有在一個序列的頭(比如D) 這種情況同時出現的時候,按照順序方式匹配。
新式類生成的訪問序列被存儲在一個叫MRO的只讀列表中..
你可以使用instance.__MRO__或者instance.mro()來訪問
最後匹配的時候就按照MRO序列的順序去匹配了
C3和廣度優先的區別:
舉個例子就完全明白了:
代碼如下:
class A(object):pass
class B(A):pass
class C(B):pass
class D(A):pass
class E(D):pass
class F(C, E):pass

按照廣度優先遍歷,F的MRO序列應該是[F,C,E,B,D,A]
但是C3是[F,E,D,C,B,A]
意思是你可以當做C3是在一條鏈路上深度遍歷到和另外一條鏈路的交叉點,然後去深度遍歷另外一條鏈路,最後遍歷交叉點
新式類和經典類的super和按類名訪問問題
在經典類中,你如果要訪問父類的話,是用類名來訪問的..
代碼如下:
class A():
def __init__(self):
print "A"
class B(A):
def __init__(self):
print "B"
A.__init__(self) #python不會默認調用父類的初始化函數的

這樣子看起來沒三問題,但是如果類的繼承結構比較復雜,會導致代碼的可維護性很差..
所以新式類推出了super這個東西...
代碼如下:
class A():
def __init__(self):
print "A"
class B(A):
def __init__(self):
print "B"
super(B,self).__init__()

這時候,又有一個問題:當類是多重繼承的時候,super訪問的是哪一個類呢?
super實際上是通過__MRO__序列來確定訪問哪一個類的...實際上就是調用__MRO__中此類後面的一個類的方法.
比如序列為[F,E,D,C,B,A]那麼F中的super就是E,E的就是D
super和按照類名訪問 混合使用帶來的坑
代碼如下:
class A(object):
def __init__(self):
print "enter A"
print "leave A"
class B(object):
def __init__(self):
print "enter B"
print "leave B"
class C(A):
def __init__(self):
print "enter C"
super(C, self).__init__()
print "leave C"
class D(A):
def __init__(self):
print "enter D"
super(D, self).__init__()
print "leave D"
class E(B, C):
def __init__(self):
print "enter E"
B.__init__(self)
C.__init__(self)
print "leave E"
class F(E, D):
def __init__(self):
print "enter F"
E.__init__(self)
D.__init__(self)
print "leave F"
這時候列印出來是:
代碼如下:
enter F
enter E
enter B
leave B
enter C
enter D
enter A
leave A
leave D
leave C
leave E
enter D
enter A
leave A
leave D
leave F

可以看出來D和A的初始化函數被亂入了兩次!
按類名訪問就相當於C語言之前的GOTO語句...亂跳,然後再用super按順序訪問..就有問題了
所以建議就是要麼一直用super,要麼一直用按照類名訪問
最佳實現:
避免多重繼承
super使用一致
不要混用經典類和新式類
調用父類的時候注意檢查類層次
以上便是本人對於python類的繼承的認識了,希望對大家能有所幫助

C. python在類中初始化另一個類

第一個問題:queryservice繼承了service,第一個問題處的意思是同樣把service里的init method原封不動繼承過來。沒有保存什麼值。
第二個問題:你用init初始化時後面的括弧里是self和request,而request你給的默認值是none,也就是說編譯完了用的時候,我可以QueryService(request='xxxx') 也可以直接QueryService()。而self.request = request的意思是把用戶輸入的request,也就是'xxx'保存到內部。

解釋的不太清楚,建議閱讀一下各種python書面向對象編程這塊,lz問的都是最基礎的問題

D. python中類的繼承以及父類中的變數繼承是如何使用的

你必須在Equilateral的__init__方法中顯式調用父類Triangle的__init__方法。

E. Python繼承父類parent的正確格式為

格式:

class 子類名(父類1,父類2)

類的繼承就是讓子類擁有父類的屬性和方法。

幾個注意:py支持多繼承

子類繼承的父類只能初始化一次,如果父類1和父類2有共同的父類或者祖先類,則類初始化的時候會失敗。

當父類具有相同方法時,會調用最先繼承的父類中的方法,如果要指定父類,則需要重寫此方法,並通過父類名.方法名來調用指定父類方法。

F. Python中的多繼承

單繼承:一個派生類的基類只有一個
多繼承:一個派生類的基類有多個
一句話區分就是:單繼承是一個生一個,多繼承是多個生一個
多繼承的基本語法:

子類定義構造方法時,需要將父類的構造方法調用一次。
案例演示:

在則答掘多繼承中,所有基類的方法可以直接繼承,但是屬性需要手工初始舉閉化。如果派生類中沒有 __init__ 方法,則默認獲得第一個類的屬性。如果派生類中有 __init__ 方法,則所有基類的屬性都不會獲得,需要手動逐孫核一初始化。

我們定義一個ChineseStudent類,其繼承關系如下:

調用基類的屬性和方法

在不同的基類中存在相同的方法,派生類對象調用方法時會調用哪個父類的方法呢?
默認情況下,如果多個基類中有相同的方法,越在前面,優先順序越高。
為了避免後期沒必要的錯誤,建議基類之間存在重名的屬性和方法應該盡量避免。

MRO(Method Resolution Order)方法解析順序

如果是經典類(舊式類),MRO的方法--DFS(深度優先搜索)策略

如果是新式類,MRO的方法--BFS(廣度優先搜索)策略

G. python中子類對父類初始化變數的賦值

1、使用self.x = x這樣來添加變數
2、對於父類的初始化參數,如果不寫,默認就使用父類無參的__init__方法
3、子類初始化父類參數B.__init__(self,aa,ab)
4、使用super(子類類型,子類對象).foo()調用父類方法

H. python 編程, 類初始化問題

1.self.__class__
self是當前,類的實例的變數,self.__class__用於獲得對應的類的本身的變數。

2.前面通過
class Circle:
定義而來一個類,叫做Circle
其中,定義了類的變數:
all_circles = []
表示是:一個名叫all_circles的列表,並且初始化賦值為[],表示一個空的列表。

3.all__這是什麼用法?
是你看錯了。
實際是:
all_circles
這是一個單個的變數而已;
這個變數,是之前類Circle中的變數all_circles。

關於這部分內容,建議你去看看我所總結的:
【整理】Python中:self和init__的含義 + 為何要有self和__init__

【整理】Python中變數的作用域(variable scope)
就懂了。
裡面有截圖解釋的,便於你理解。

(此處不給貼地址,請自己用google搜標題,即可找到帖子地址)

I. python的初始化方法有什麼用

1.
在程序執行時一定執行一次的操作

2.
python中初始化init 參數第一個必須要加 self

3.
對變數進行賦值 繼承: 子類繼承父類

J. Python子類繼承,如果不用父類的函數和方法,應該怎麼寫

子類繼承父類時,如果父類有需要初始化的屬性,那麼必須在子類中調用父類的初始化方法,幫助父類進行初始化,否則,子類可以不調用父類的初始化方法

代碼示例

"""
父類Car中沒有屬性需要初始化,所有子類中也不需要調用父類的初始化方法
"""


classCar:

defshow_name(self):
print('carname')


classEeleCar(Car):
pass


car=EeleCar()
car.show_name()
熱點內容
動態規劃01背包演算法 發布:2024-11-05 22:17:40 瀏覽:846
nasm編譯器如何安裝 發布:2024-11-05 22:01:13 瀏覽:176
登錄密碼在微信的哪裡 發布:2024-11-05 22:00:29 瀏覽:735
c防止反編譯工具 發布:2024-11-05 21:56:14 瀏覽:243
安卓虛擬機怎麼用 發布:2024-11-05 21:52:48 瀏覽:340
php時間搜索 發布:2024-11-05 20:58:36 瀏覽:475
燕山大學編譯原理期末考試題 發布:2024-11-05 20:13:54 瀏覽:524
華為電腦出現臨時伺服器 發布:2024-11-05 20:05:08 瀏覽:405
斗戰神免費挖礦腳本 發布:2024-11-05 19:53:25 瀏覽:662
網吧伺服器分別是什麼 發布:2024-11-05 19:45:32 瀏覽:389