Python中的__new__和__init__
寫了這么多的class,現在才知道還有個__new__方法, 那么它和__init__有什么區別呢?
class TestCls():
"""docstring for TestCls"""
def __init__(self, name):
print('init')
print(self)
print(type(self))
self.name = name
def __new__(cls, name):
print('new')
print(cls)
print(type(cls))
return super().__new__(cls)
c = TestCls("CooMark")
# new...
# <class '__main__.TestCls'>
# <class 'type'>
# init...
# <__main__.TestCls object at 0x02201130>
# <class '__main__.TestCls'>
異同點
1. 參數 * \_\_new\_\_的第一個占位參數是class對象 * \_\_init\_\_的第一個占位參數是class的實例對象 * 其他的參數應一致 2. 作用 * \_\_new\_\_ 用來創建實例,在返回的實例上執行\_\_init\_\_,如果不返回實例那么\_\_init\_\_將不會執行 * \_\_init\_\_ 用來初始化實例,設置屬性什么的
利用__new__我們能做哪些牛逼的事情?
>Python文檔 >>object.__new__(cls[, ...]) >>Called to create a new instance of class cls. __new__() is a static method (special-cased so you need not declare it as such) that takes the class of which an instance was requested as its first argument. The remaining arguments are those passed to the object constructor expression (the call to the class). The return value of __new__() should be the new object instance (usually an instance of cls). >> >>Typical implementations create a new instance of the class by invoking the superclass’s __new__() method using super(currentclass, cls).__new__(cls[, ...]) with appropriate arguments and then modifying the newly-created instance as necessary before returning it. >> >>If __new__() returns an instance of cls, then the new instance’s __init__() method will be invoked like __init__(self[, ...]), where self is the new instance and the remaining arguments are the same as were passed to __new__(). >> >>If __new__() does not return an instance of cls, then the new instance’s __init__() method will not be invoked. >> >>__new__() is intended mainly to allow subclasses of immutable types (like int, str, or tuple) to customize instance creation. It is also commonly overridden in custom metaclasses in order to customize class creation. >>
依照Python官方文檔的說法,__new__方法主要是當你繼承一些不可變的class時(比如int, str, tuple), 提供給你一個自定義這些類的實例化過程的途徑。還有就是實現自定義的metaclass。
- 繼承不可變class
參考
假如我們需要一個永遠都是正數的整數類型,通過集成int,我們可能會寫出這樣的代碼
class PositiveInteger(int):
def __init__(self, value):
super().__init__(self, abs(value))
i = PositiveInteger(-3)
print(i)
# # TypeError: object.__init__() takes no parameters
class PositiveInteger(int):
def __new__(cls, value):
return super(PositiveInteger, cls).__new__(cls, abs(value))
i = PositiveInteger(-3)
print(i)
# 3
- 用__new__來實現單例
class Singleton(object):
def __new__(cls):
# 關鍵在於這,每一次實例化的時候,我們都只會返回這同一個instance對象
if not hasattr(cls, 'instance'):
cls.instance = super(Singleton, cls).__new__(cls)
return cls.instance
obj1 = Singleton()
obj2 = Singleton()
obj1.attr1 = 'value1'
print( obj1.attr1, obj2.attr1)
print( obj1 is obj2)