要点
__new__()
是创建对象的构造函数,而__init()__
是初始化函数;
__new__()
返回的对象即为self;
__new__()
会自动调用__init()__
。
简单例子
class Person(object):
def __new__(cls, name, age):
print(cls)
print('__new__ is called')
# test = super().__new__(cls)
# return test
return super().__new__(cls) # object.__new__() receives only one para
def __init__(self, name, age):
print('__init__ is called')
self.name = name
self.age = age
def __str__(self):
return('<Person: %s(%s)>' % (self.name, self.age))
name = Person('Tom', 24)
print(name)
__new__()
创建了Person实例,其返回值其赋值给self。然后自动调用__init()__
,且参数self为__new__()
返回值,name和age来自于__new__()
的参数。注意object.__new()__
只接受cls参数,而cls参数是由解释器自动赋值的。
子类调用父类__new()__
import datetime
class MfDateSub(datetime.date):
def __init__(self, year, month, day):
super().__new__(datetime.date, year, month, day)
def next_day(self):
result = datetime.date(self.year, self.month, self.day+1)
return result
mfdate = MfDateSub(2018, 11, 4)
print(mfdate.next_day())
而datetime包中date类并无__init()__
,只有__new__()
:
class date:
def __new__(cls, year, month=None, day=None):
"""Constructor.
Arguments:
year, month, day (required, base 1)
"""
if month is None and isinstance(year, bytes) and len(year) == 4 and \
1 <= year[2] <= 12:
# Pickle support
self = object.__new__(cls)
self.__setstate(year)
self._hashcode = -1
return self
year, month, day = _check_date_fields(year, month, day)
self = object.__new__(cls)
self._year = year
self._month = month
self._day = day
self._hashcode = -1
return self
MfDateSub的作用是扩展date类为其增加next_day功能。MfDateSub的__init()__
只能调用date的__new__()
,而date的__new__()
调用object的__new__()
将其赋值给date的self。MfDateSub继承了date,也继承了date的self。所以,MfDateSub的__init()__
执行后,就有了date的self。
参考资料
[1] new and init in Python
[2] python的__new__方法
[3] The Python Language Reference, Data Model, object.new(cls[, …])