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

2018-02-24 15:26 更新

問題

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

解決方案

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

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

下面演示如何不調(diào)用 __init__() 方法來創(chuàng)建這個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
>>>

討論

當我們在反序列對象或者實現(xiàn)某個類方法構造函數(shù)時需要繞過 __init__() 方法來創(chuàng)建對象。例如,對于上面的Date來來講,有時候你可能會像下面這樣定義一個新的構造函數(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ù)時產(chǎn)生一個如下的字典對象:

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

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

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

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

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號