Python 魔法方法(一) __new__()

首先,只有新式類纔有魔法方法__new__(),從Object類繼承的子類,都是新式類。

object類關於__new__()的定義如下:

@staticmethod # known case of __new__
    def __new__(cls, *more): # known special case of object.__new__
        """ T.__new__(S, ...) -> a new object with type S, a subtype of T """
        pass
參數說明:

(1)object將__new__()定義成靜態方法。

(2)傳入的參數至少一個cls參數,cls表示需要實例化的類。

 

如何使用,舉個例子:

class A(object):
    def __init__(self, value):
        print  "into __init__"
        self.value = value
    def __new__(cls, *args, **kwargs):
        print "into __new__"
        return super(A, cls).__new__(cls, *args, **kwargs)
 
a =  A(10)
 
# 結果如下:
# into __new__
# into __init__
可發現,在調用__init__()初始化前,先調用了__new__()。

在新式類中,__new__()對當前類進行了實例化,並將實例返回,傳給了__init__(),__init__()方法中是self就是__new__()傳過來的。

但是,執行了__new__(),並不一定會進入__init__(),只有__new__()返回了,當前類cls的實例,當前類的__init__()纔會進入。

看兩個例子:

class A(object):
    def __init__(self, value):
        print  "into A __init__"
        self.value = value
        
    def __new__(cls, *args, **kwargs):
        print "into A __new__"
        return object.__new__(cls, *args, **kwargs)
 
 
class B(A):
    def __init__(self, value):
        print  "into B __init__"
        self.value = value
        
    def __new__(cls, *args, **kwargs):
        print "into B __new__"
        return super(B, cls).__new__(cls, *args, **kwargs)
 
b = B(10)
 
b = B(10)
# 結果:
# into B __new__
# into A __new__
# into B __init__
 
 
 
class A(object):
    def __init__(self, value):
        print  "into A __init__"
        self.value = value
 
    def __new__(cls, *args, **kwargs):
        print "into A __new__"
        return object.__new__(cls, *args, **kwargs)
 
 
class B(A):
    def __init__(self, value):
        print  "into B __init__"
        self.value = value
 
    def __new__(cls, *args, **kwargs):
        print "into B __new__"
        return super(B, cls).__new__(A, *args, **kwargs) #改動了cls變爲A
 
b = B(10)
# 結果:
into B __new__
into A __new__
若__new__沒有正確返回當前類cls的實例,那__init__是不會被調用的,即使是父類的實例也不行,將沒有__init__被調用。

 

__new__的作用

(1)

__new__方法主要是當你繼承一些不可變的class時(比如int, str, tuple), 提供給你一個自定義這些類的實例化過程的途徑。

假如我們需要一個永遠都是正數的整數類型。

class PositiveInteger(int):
    def __init__(self, value):
        super(PositiveInteger, self).__init__(self, abs(value))
 
 
i = PositiveInteger(-3)
print i
 
# -3
 
class PositiveInteger(int):
    def __new__(cls, value):
        return super(PositiveInteger, cls).__new__(cls, abs(value))
 
 
i = PositiveInteger(-3)
print i
 
# 3
通過重載__new__方法,我們實現了需要的功能。

(2)實現單例

 

一些說明:

(1)在定義子類時沒有重新定義__new__()時,Python默認是調用該類的直接父類的__new__()方法來構造該類的實例,如果該類的父類也沒有重寫__new__(),那麼將一直按此規矩追溯至object的__new__()方法,因爲object是所有新式類的基類。

(2)除了一項兩個作用外,一般__new__()使用較少,能通過__init__()實現的儘量用__init__()實現。
————————————————
版權聲明:本文爲CSDN博主「yusuiyu」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/yusuiyu/article/details/87867186

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章