程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

python中__init__subclass__方法用法詳解

編輯:Python

先看下面代碼執行的效果:

示例代碼1:

class Test(object):
def __init_subclass__(cls, **kwargs):
print("__init_subclass__", cls, kwargs)
class A(Test, name="張三", age=16):
pass
"""
代碼運行直接輸出下面的結果:
__init_subclass__ <class '__main__.A'> {'name': '張三', 'age': 16}
"""

運行結果:

        上面代碼中定義了一個Test類,然後讓A這個類繼承它。發現還沒有實例化,而是在創建類的時候就有輸出結果了。

        對於一個類,如果這個類被作為父類繼承,那麼會觸發其內部的__init_subclass__方法,這裡的Test被A繼承,那麼Test中的__init_subclass__就會被觸發。而且看到,裡面的cls,就是定義的字類A,也就是繼承它的類,**kwargs,就是額外傳遞的參數。但是發現,第一個參數不是self,而是cls,而且這個cls還不是Test,而是繼承它的類。其實這個方法是隱式的被classmethod裝飾了。

        有時候想控制類的生成過程,怎麼辦呢?顯然可以通過元類的的方式,但是如果場景比較簡單,也沒必要使用元類。直接使用__init_subclass__即可

示例代碼2:

class Test(object):
def __init_subclass__(cls, **kwargs):
for k, v in kwargs.items():
type.__setattr__(cls, k, v)
class A(Test, name="張三", age=16):
pass
print(A.name) # 張三
print(A.age) # 16

運行結果:

        可以看到,在不使用元類的情況下,通過__init_subclass__實現了類的自定義過程。當然這比較簡單,也可以實現更復雜的邏輯,在某些場景下,可以替代元類。

示例代碼3:

class TestBase(object):
def __init_subclass__(cls, default_name, **kwargs):
super().__init_subclass__(**kwargs)
cls.default_name = default_name
print(cls.default_name)
class Test(TestBase, default_name="張三"):
pass
class NewTest(Test, default_name="李四"):
pass

運行結果:

         在上述代碼3中,當有子類繼承了 TestBase類時,那麼 __init_subclass__ 就會調用。內容也很簡單,父類 TestBase為它的所有子類都設置了default_name 屬性。

        __init_subclass__ 就像是個鉤子函數,當子類定義之後觸發。

        默認實現 object.__init_subclass__ 不執行任何操作。但默認實現不能傳遞任何參數,否則報錯。
        值得注意的是,示例中的 __init_subclass__ 第一個參數是 cls 而不是常見的 self 。這是因為這個方法隱式地被 @classmethod 裝飾。

        __init_subclass__() 是鉤子函數,它解決了如何讓父類知道被繼承的問題。鉤子中能改變類的行為,而不必求助與元類或類裝飾器。鉤子用起來也更簡單且容易理解。


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved