python新式类中的__new__方法与__init__方法

Posted bitcarmanlee

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python新式类中的__new__方法与__init__方法相关的知识,希望对你有一定的参考价值。

1.旧式类

在讲新式类之前,先看看旧式类是怎么用的。

class OldClass:
    pass

OldClass()

上面就是旧式类的写法,默认继承type类。

2.新式类

python2中,如果定义一个新式类

class NewClass(object):
    pass

而在python3中,所有的类,均默认继承object,所以括号里也可以不显示指定object。

3.__new__方法与__init__方法

如果我们再IDE里面输入__new__字样,IDE会自动给我们补全方法如下:

class NewClass(object):

    def __new__(cls, *args, **kwargs):
        super().__new__()

而如果是输入__init__字样,IDE会自动给我们补全方法如下:

class NewClass(object):

    def __new__(cls, *args, **kwargs):
        super().__new__()

    def __init__(self):
        pass

先说结论:

__new__的第一个参数是cls(当然你也可以叫别的名字,但是cls是约定俗成),是用来创建类的实例的(constructor)。
__init__的第一个参数是self,是用来初始化实例的(initializer),这个实例的名字就是self。

class NewClass(object):

    def __new__(cls, *args, **kwargs):
        print("this is __new__ method!")
        instance = super(NewClass, cls).__new__(cls)
        return instance


    def __init__(self):
        print("this is __init__ method!")
        pass

NewClass()

代码的输出为:

this is __new__ method!
this is __init__ method!

从上面代码的执行结果可以看出,在创建NewClass类实例并初始化的过程中,__new__方法与__init__方法都被调用了。先是通过__new__方法创建了一个类实例,然后再通过__init__方法初始化。

如果我们把__new__方法中的return一行去掉,不返回任何对象,则__init__方法不会被调用!

class NewClass(object):

    def __new__(cls, *args, **kwargs):
        print("this is __new__ method!")
        instance = super(NewClass, cls).__new__(cls)


    def __init__(self):
        print("this is __init__ method!")
        print("self is: ", self)
        pass

NewClass()

代码输出结果为

this is __new__ method!

如果__new__方法返回一个已经存在的对象,不管该对象是什么类型,__init__方法也不会被调用。

s = "abc"

class NewClass(object):

    def __new__(cls, *args, **kwargs):
        print("this is __new__ method!")
        instance = super(NewClass, cls).__new__(cls)
        return s


    def __init__(self):
        print("this is __init__ method!")
        print("self is: ", self)
        pass

NewClass()

代码输出结果为

this is __new__ method!

4.__init__必须返回None

在__init__方法中,返回类型必须为None。看如下代码

class NewClass(object):
    def __new__(cls, *args, **kwargs):
        instance = super(NewClass, cls).__new__(cls)
        return instance

    def __init__(self):
        return "abc"

NewClass()

执行结果如下:

TypeError: __init__() should return None, not 'str'

5.__new__方法的作用

按照python官方文档的解释,__new__方法主要是当你继承一些不可变的class时(比如int, str, tuple), 提供给你一个自定义这些类的实例化过程的途径。

class PositiveNum(int):

    def __new__(cls, value):
        return super().__new__(cls, abs(value))

num = PositiveNum(-10)
print(num)

上面的例子,就是通过重写new方法,得到了一个正整数的类。

6.__new__实现单例模式

我们可以通过new方法,来实现一个单例模式。

class Singleton(object):

    _instance = None

    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super().__new__(cls, *args, **kwargs)

        return cls._instance

def test_singleton():
    s1 = Singleton()
    s2 = Singleton()
    print(s1)
    print(s2)

test_singleton()
<__main__.Singleton object at 0x116e65a50>
<__main__.Singleton object at 0x116e65a50>

通过上面的例子可以看出来,s1与s2的内存地址一样,指向的是同一个实例对象。

7.工厂模式

class Bird(Animal):
    def __init__(self):
        pass

    def print_name(self):
        print("my name is Bird!")

class Cat(Animal):
    def __init__(self):
        pass

    def print_name(self):
        print("my name is Cat!")


class Factory(object):

    animals = "bird": Bird, "cat": Cat

    def __new__(cls, name):
        if name in cls.animals.keys():
            return cls.animals[name]()

        else:
            return Animal

def test_factory():
    bird = Factory("bird")
    cat = Factory("cat")
    bird.print_name()
    cat.print_name()


test_factory()
my name is Bird!
my name is Cat!

以上是关于python新式类中的__new__方法与__init__方法的主要内容,如果未能解决你的问题,请参考以下文章

Python 的 __new__()方法与实例化

python中的__new__与__init__,新式类和经典类(2.x)

Python中的__new__()方法的使用

Python中的__new__()方法的使用

Python新式类 单例模式与作用域

python单例模式控制成只初始化一次,常规型的python单例模式在新式类和经典类中的区别。