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!
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值