老样子,抛出个问题,我们想要创建一个实例,但是由于某些原因想绕过__init__方法,用别的方式来进行创建。
举个栗子
小贱贱反序列化数据,或者说实现一个类方法将其作为备选的构造函数,都属于这种情况。举个栗子:
class Date:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
采用下面的方法可以不用调用__init__()创建一个Date实例:
d = Date.__new__(Date)
但是注意,此时使用d.year就会给你报个错
因为得到的实例是未经初始化的,因此给实例变量设定合适的初始值现在就成了我们的责任。
ok……在下面的例子中给出:
from time import localtime class Date:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day @classmethod
def today(cls):
d = cls.__new__(cls)
t = localtime()
t.year = t.tm_year
t.month = t.tm_mon
t.day = t.tm_mday
return d
类似的,假如正在反序列化JSON数据,要产生下面酱紫的字典:
要产生类似字典的数据咋搞呢?
from time import localtime class Date:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day @classmethod
def today(cls):
d = cls.__new__(cls)
t = localtime()
T = {}
T['year'] = t.tm_year
T['month'] = t.tm_mon
T['day'] = t.tm_mday
for key, value in T.items():
setattr(d, key, value)
return d
x = Date(2018,6,5)
youxi=x.today()
print(youxi.year, youxi.month, youxi.day)
总结:
当通过非标准方法去创建实例的时候,最好不要对他们的实现做过多的假设,不要直接操作底层的字典__dict__的代码,除非你保证它完全被定义了,否则,一旦类中使用了
__slots__、proprety属性、描述符(魔术方法),那么你的代码就会崩溃。通过使用setattr()来为属性定值,代码就会尽可能的通用。