8.17 創(chuàng)建不調(diào)用init方法的實(shí)例

2018-02-24 15:26 更新

問題

你想創(chuàng)建一個(gè)實(shí)例,但是希望繞過執(zhí)行 __init__() 方法。

解決方案

可以通過 __new__() 方法創(chuàng)建一個(gè)未初始化的實(shí)例。例如考慮如下這個(gè)類:

class Date:
    def __init__(self, year, month, day):
        self.year = year
        self.month = month
        self.day = day

下面演示如何不調(diào)用 __init__() 方法來創(chuàng)建這個(gè)Date實(shí)例:

>>> 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'
>>>

結(jié)果可以看到,這個(gè)Date實(shí)例的屬性year還不存在,所以你需要手動(dòng)初始化:

>>> data = {'year':2012, 'month':8, 'day':29}
>>> for key, value in data.items():
...     setattr(d, key, value)
...
>>> d.year
2012
>>> d.month
8
>>>

討論

當(dāng)我們?cè)诜葱蛄袑?duì)象或者實(shí)現(xiàn)某個(gè)類方法構(gòu)造函數(shù)時(shí)需要繞過 __init__() 方法來創(chuàng)建對(duì)象。例如,對(duì)于上面的Date來來講,有時(shí)候你可能會(huì)像下面這樣定義一個(gè)新的構(gòu)造函數(shù) 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數(shù)據(jù)時(shí)產(chǎn)生一個(gè)如下的字典對(duì)象:

data = { 'year': 2012, 'month': 8, 'day': 29 }

如果你想將它轉(zhuǎn)換成一個(gè)Date類型實(shí)例,可以使用上面的技術(shù)。

當(dāng)你通過這種非常規(guī)方式來創(chuàng)建實(shí)例的時(shí)候,最好不要直接去訪問底層實(shí)例字典,除非你真的清楚所有細(xì)節(jié)。否則的話,如果這個(gè)類使用了 __slots__ 、properties 、descriptors 或其他高級(jí)技術(shù)的時(shí)候代碼就會(huì)失效。而這時(shí)候使用 setattr() 方法會(huì)讓你的代碼變得更加通用。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)