當前位置:首頁 » 編程語言 » Python新類

Python新類

發布時間: 2025-08-04 22:57:57

python中的舊樣式類和新樣式類有什麼區別

  1. 在Python 2.1之前,舊式類是用戶可用的唯一樣式。

  2. (舊式)類的概念與類型的概念無關:如果x是舊式類的實例,則x.__class__指定的類x,但type(x)始終為<type
    'instance'>。這反映了這樣一個事實,即所有舊式實例(獨立於其類)均使用稱為實例的單個內置類型實現。

  3. 在Python 2.2中引入了新的類,以統一class和type的概念。新型類只是用戶定義的類型,不多也不少。如果x是新樣式類的實例,則type(x)通常與x 相同x.__class__(盡管不能保證–允許新樣式類實例覆蓋為返回的值x.__class__)。

  4. 引入新型類的主要動機是提供具有完整元模型的統一對象模型。

  5. 它還具有許多直接的好處,例如能夠對大多數內置類型進行子類化,或者引入了「描述符」,以啟用計算屬性。出於兼容性原因,默認情況下,類仍為舊樣式。通過將另一個新樣式類(即一種類型)指定為父類或「頂級類型」對象(如果不需要其他父類)來創建新樣式類。

  6. 新樣式類的行為與舊樣式類的行為不同,除了返回什麼類型外,還有許多重要的細節。其中一些更改是新對象模型的基礎,例如調用特殊方法的方式。其他是出於兼容性考慮而無法實現的「修復程序」,例如在多重繼承的情況下的方法解析順序。

  7. Python 3僅具有新型類。無論是否從中繼承子類object,類都是Python 3中的新型樣式。

Ⅱ 關於python的實例方法問題

題主你好,

python中創建新實例的時候, 如果相應的類中定義了__init__()方法的話, 會自動調用這個方法. 你可能認為名稱"init"和"__init__"差不多, 但計算機其實是個很笨的東西, 它會完全按照設計去執行. 也就是說,在設計的時候就已經定死了, 默認情況下, 創建新實例的時候, 會自動調用類中定義的__init__()方法, 只要你的方法名和__init__有一點不一樣也不行.

下圖是我在官網上找的關於__init__()調用的簡單說明:

高亮部分說的大概意思就是上面講的,如果相應類中定義了__init__()方法,則在創建該類實例的時候會自動調用裡面定義的__init__()方法.

-----

希望可以幫到題主, 歡迎追問.

Ⅲ 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類的繼承的認識了,希望對大家能有所幫助

Ⅳ 使用python的super時出現的TypeError: must be type, not classobj 原因及解決

示例如下:

但是運行報錯:TypeError: must be type, not classobj

查找資料之後發現,python中super只能應用於襪拿睜新類,而不能應用於經典類

所謂新類 : 就是所有類都必須要有繼承的類,如果什麼都不想繼承,就繼承到告歲object類。下面是一個新類的例子

所謂經典類 : 就是什麼都不用繼承的類,例如:

產上上面的問題,而自己又不知道父類該繼承什麼,最簡單的方法就是讓它去繼承object類敏談,例如:

Ⅳ [Python]使用metaclass創建類對象

在Python中,使用metaclass創建類對象的過程可以概括為以下幾個關鍵步驟:

  1. 定義元類

    • 創建一個類作為元類,這個類需要繼承自type
    • 在這個元類中,可以實現控制類對象創建行為的特定邏輯,例如修改類屬性或方法。
  2. 實現元類邏輯

    • 元類接收三個參數:類名基類列表以及類屬性字典
    • 通過這些參數,元類可以動態地創建和修改類對象。
  3. 指定元類

    • 在需要被元類控制的類定義中,使用metaclass=MyMetaClass來明確指定該類的元類。
  4. 創建類對象

    • 當Python解釋器遇到指定了元類的類定義時,它會將類定義中的參數傳遞給元類。
    • 元類根據這些參數創建並返回一個新的類對象。

重點內容元類是用於創建類對象的類自定義元類通常通過繼承type類實現在類定義中使用metaclass關鍵字指定自定義元類

通過自定義元類,可以實現對類創建過程的精細控制,例如動態添加類屬性、修改類行為等,從而提高代碼的靈活性和擴展性。但需要注意的是,過度使用或不當使用自定義元類可能會導致代碼難以理解和維護,因此應謹慎使用。

熱點內容
java返回this 發布:2025-10-20 08:28:16 瀏覽:585
製作腳本網站 發布:2025-10-20 08:17:34 瀏覽:881
python中的init方法 發布:2025-10-20 08:17:33 瀏覽:574
圖案密碼什麼意思 發布:2025-10-20 08:16:56 瀏覽:761
怎麼清理微信視頻緩存 發布:2025-10-20 08:12:37 瀏覽:677
c語言編譯器怎麼看執行過程 發布:2025-10-20 08:00:32 瀏覽:1005
郵箱如何填寫發信伺服器 發布:2025-10-20 07:45:27 瀏覽:250
shell腳本入門案例 發布:2025-10-20 07:44:45 瀏覽:108
怎麼上傳照片瀏覽上傳 發布:2025-10-20 07:44:03 瀏覽:799
python股票數據獲取 發布:2025-10-20 07:39:44 瀏覽:705