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__()实现。

 

 

你可能感兴趣的:(python’)