8.17 创建�调用init方法的实例¶
问题¶
ä½ æƒ³åˆ›å»ºä¸€ä¸ªå®žä¾‹ï¼Œä½†æ˜¯å¸Œæœ›ç»•è¿‡æ‰§è¡Œ __init__() 方法。
解决方案¶
�以通过 __new__() 方法创建一个未�始化的实例。例如考虑如下这个类:
class Date:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
下�演示如何�调用 __init__() 方法�创建这个Date实例:
>>> d = Date.__new__(Date)
>>> d
<__main__.Date object at 0x1006716d0>
>>> d.year
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Date' object has no attribute 'year'
>>>
结果å�¯ä»¥çœ‹åˆ°ï¼Œè¿™ä¸ªDate实例的属性year还ä¸�å˜åœ¨ï¼Œæ‰€ä»¥ä½ 需è¦�手动åˆ�始化:
>>> data = {'year':2012, 'month':8, 'day':29}
>>> for key, value in data.items():
... setattr(d, key, value)
...
>>> d.year
2012
>>> d.month
8
>>>
讨论¶
当我们在å��åº�列对象或者实现æŸ�ä¸ªç±»æ–¹æ³•æž„é€ å‡½æ•°æ—¶éœ€è¦�绕过 __init__() 方法æ�¥åˆ›å»ºå¯¹è±¡ã€‚
例如,对于上é�¢çš„Dateæ�¥è®²ï¼Œæœ‰æ—¶å€™ä½ å�¯èƒ½ä¼šåƒ�下é�¢è¿™æ ·å®šä¹‰ä¸€ä¸ªæ–°çš„æž„é€ å‡½æ•° today() :
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()
d.year = t.tm_year
d.month = t.tm_mon
d.day = t.tm_mday
return d
å�Œæ ·ï¼Œåœ¨ä½ å��åº�列化JSONæ•°æ�®æ—¶äº§ç”Ÿä¸€ä¸ªå¦‚下的å—典对象:
data = { 'year': 2012, 'month': 8, 'day': 29 }
å¦‚æžœä½ æƒ³å°†å®ƒè½¬æ�¢æˆ�一个Date类型实例,å�¯ä»¥ä½¿ç”¨ä¸Šé�¢çš„æŠ€æœ¯ã€‚
å½“ä½ é€šè¿‡è¿™ç§�é�žå¸¸è§„æ–¹å¼�æ�¥åˆ›å»ºå®žä¾‹çš„æ—¶å€™ï¼Œæœ€å¥½ä¸�è¦�直接去访问底层实例å—典,除é�žä½ 真的清楚所有细节。
å�¦åˆ™çš„è¯�,如果这个类使用了 __slots__ ã€�properties ã€�descriptors 或其他高级技术的时候代ç �就会失效。
而这时候使用 setattr() æ–¹æ³•ä¼šè®©ä½ çš„ä»£ç �å�˜å¾—æ›´åŠ é€šç”¨ã€‚