python的__init__和__new__方法

网上有很多文章描述,我只是做一些笔记。

__new__是类的方法,在创建对象之前调用,__init__是对象的方法,在创建对象之后调用。如下代码:

class A(object):
    def __init__(self, name):
        print("init:%s" % name)
        print(self)
    def __new__(cls, name):
        print("new:%s" % name)
        res = super(A, cls).__new__(cls, name)
        print(res)
        return res

if __name__ == '__main__':
    a = A('haha')
    print(a)

其输出为:

new:haha
<__main__.A object at 0x7f8923c236d0>
init:haha
<__main__.A object at 0x7f8923c236d0>
<__main__.A object at 0x7f8923c236d0>

__new__带来了很多好处,官方说法是用于继承一些不可变的基本类型,举例如下:

class MyInt(int):
    def __init__(self, val):
        super(MyInt, self).__init__(self, -val)

class MyInt2(int):
    def __new__(cls, val):
        return super(MyInt2, cls).__new__(cls, -val)

class MyStr(str):
    def __init__(self, val):
        super(MyStr, self).__init__(self, 'prefix' + val)

class MyStr2(str):
    def __new__(cls, val):
        return super(MyStr2, cls).__new__(cls, 'prefix' + val)

if __name__ == '__main__':
    a = MyInt(100)
    print(a)
    b = MyInt2(100)
    print(b)

    c = MyStr('abc')
    print(c)
    d = MyStr2('abc')
    print(d)

输出为:

100
-100
abc
prefixabc

可见python里的基本类型创建对象之后,就不能再改变了。__new__能够在创建之前完成必要的计算。不过实际中,很少会有继承基本类型的需求。

__new__带来更多的好处是便于实现各种设计模式。比如单例模式:

class Singleton(object):
    def __new__(cls):
        if not hasattr(cls, '_instance'):
            cls._instance = super(Singleton, cls).__new__(cls)
        return cls._instance

if __name__ == '__main__':
    a = Singleton()
    print(a)
    b = Singleton()
    print(b)

因为__new__可以返回任何类型的对象,再比如工厂模式:

class Car(object):
    pass

class Truck(object):
    pass

class Train(object):
    pass

class Vehicle(object):
    def __new__(cls, name):
        if name == 'Car':
            return Car()
        elif name == 'Truck':
            return Truck()
        elif name == 'Train':
            return Train()


if __name__ == '__main__':
    a = Vehicle('Car')
    print(a)
    b = Vehicle('Truck')
    print(b)
    c = Vehicle('Train')
    print(c)

总之,__new__用来在类型上塞meta data,而__init__用来在实例上塞member data。

发表于 2016年07月21日 00:40   评论:0   阅读:1859  



回到顶部

首页 | 关于我 | 关于本站 | 站内留言 | rss
python logo   django logo   tornado logo