python和C语言不同,在构造函数时不能够分配内存空间,但是在构造函数时,也可以通过__new__函数来实现一些跟内存相关的操作,比如单例模式。
估计有很多小盆友不知道什么是单例,python的单例就是在实例化时,不管实例化多少次都用的同一块内存空间。
另外需要说明的是,构造函数需要用__new__来实现,而__init__为初始化函数,__init__在实例化时调用,__new__在构造函数时调用。
先举个例子:
class Test:
def __new__(cls, *args, **kwargs):
print("This is new!")
return object.__new__(cls, *args, **kwargs)
def __init__(self):
print("This is init!")
test = Test()
运行后打印结果为:
This is new!
This is init!
可以看到,__new__是在__init__之前运行,并且__new__需要返回object.__new__(),将cls本身作为参数传递。
所以__new__可以在构造函数时,对函数动点手脚,比如单例:
class Single(object):
# 在构造函数时,先检查instance
def __new__(cls, *args, **kwargs):
if not hasattr(cls, 'instance'):
cls.instance = super(Single, cls).__new__(cls)
return cls.instance
def test():
pass
tmp1 = Single()
print(tmp1)
tmp2 = Single()
print(tmp2)
print(Single().test)
打印结果为:
<__main__.Single object at 0x0000000002A5CF60>
<__main__.Single object at 0x0000000002A5CF60>
<bound method Single.test of <__main__.Single object at 0x0000000002A5CF60>>
可以看到,不管怎么实例化,被分配的都是同一块内存,而当我把__new__函数去掉时:
class Single(object):
def test():
pass
tmp1 = Single()
print(tmp1)
tmp2 = Single()
print(tmp2)
print(Single().test)
打印结果为:
<__main__.Single object at 0x00000000028A9908>
<__main__.Single object at 0x0000000002A5CC50>
<bound method Single.test of <__main__.Single object at 0x0000000002A60160>>
可以看到,不是单例情况下,每次实例化都会开辟一块新的内存出来。
另外需要注意的是,单例模式每次实例化都会覆盖掉之前定义的参数,比如:
class Single:
def __new__(cls, *args, **kwargs):
if not hasattr(cls, 'instance'):
cls.instance = super(Single, cls).__new__(cls)
return cls.instance
def __init__(self, input):
self.input = input
def test(self):
print(self.input)
tmp1 = Single("This is NO.1")
tmp2 = Single("This is NO.2")
tmp1.test()
打印结果为:
This is NO.2
可以看到tmp1已经完全被覆盖了。