基於 __new__ 方法的單例模式
阿新 • • 發佈:2019-03-01
地址 per 類方法 -a __main__ 結果 方法 額外 系列
單例模式定義
首次實例化創建實例化對象
之後的每次實例化都用最初的實例化對象 即單實例模式
__new__ 的原理
__new__ 方法可以在 __init__ 方法執行
這樣可以在初始化之前進行一系列的其他操作
比如在這裏創建一個全局實例
實現代碼
class A: __instance = False # 定義一個私有的變量,只能內部的去拿 def __init__(self, name, age): self.name = name self.age = age def __new__(cls, *args, **kwargs):if cls.__instance: # 第一次循環外部拿不到自然就是 False return cls.__instance else: # cls.__instance = object.__new__(A) # 借助object類創建的實例並賦值 cls.__instance = super().__new__(A) # 當然也可以借助 super 方法 return cls.__instance
關於使用父類方法的時候, super 方法是很好用的選擇. 3.0版本中super 使用更加簡單
代碼分析
第一次創建的__instance變量一定是 false 的 因此必然返回一個借助 object 類創建的實例並賦值 所創建的這個實例是什麽都沒有的,沒有self的屬性,只是開辟了一段空的內存地址給他用 之後在調用 __init__ 根據你的參數賦值屬性添加內存 __instance 是保存在類裏面的靜態變量 以後每次進來都是使用 cls.__instance 作為實例了
測試結果
a = A("a", 2) a.cloth = "女裝" b = A("b", 2)
測試單例
print(b) print(a)
""" <__main__.A object at 0x000000000255D208> <__main__.A object at 0x000000000255D208> """結果
測試實例屬性覆蓋
print(a.name) print(b.name)
""" # 在創建示例會覆蓋之前的實例的屬性,但是兩個示例都是存在的 b b # name 和age 都會被下一次實例化的時候被新值鎖覆蓋 """結果
測試實例額外屬性
print(a.cloth) print(b.cloth)
""" none # 盡管使用一個內存地址但是cloth 的屬性沒有被覆蓋,而且保存在地址裏面也不會被清除 none # sb示例並沒有創建 cloth 屬性,但是依然可以調用出來之前 suyang 示例的屬性 ,即繼承了之前的屬性 """結果
測試實例屬性覆蓋
b.hobby = "bb" print(a.hobby)
""" bb # 相同的沒有創建 hobby 的 suyang 示例 也可以繼承之後的 sb 創建的 hobby 屬性 """結果
全部代碼
class A: __instance = False # 定義一個私有的變量,只能內部的去拿 def __init__(self, name, age): self.name = name self.age = age def __new__(cls, *args, **kwargs): if cls.__instance: # 第一次循環外部拿不到自然就是 False return cls.__instance else: # cls.__instance = object.__new__(A) # 借助object類創建的實例並賦值 cls.__instance = super().__new__(A) # 當然也可以借助 super 方法 return cls.__instance """ 第一次創建的__instance變量一定是 false 的 因此必然返回一個借助 object 類創建的實例並賦值 所創建的這個實例是什麽都沒有的,沒有self的屬性,只是開辟了一段空的內存地址給他用 之後在調用 __init__ 根據你的參數賦值屬性添加內存 __instance 是保存在類裏面的靜態變量 以後每次進來都是使用 cls.__instance 作為實例了 """ a = A("a", 2) a.cloth = "女裝" b = A("b", 2) print(b) print(a) """ <__main__.A object at 0x000000000255D208> <__main__.A object at 0x000000000255D208> """ print(a.name) print(b.name) """ # 在創建示例會覆蓋之前的實例的屬性,但是兩個示例都是存在的 b b # name 和age 都會被下一次實例化的時候被新值鎖覆蓋 """ print(a.cloth) print(b.cloth) """ none # 盡管使用一個內存地址但是cloth 的屬性沒有被覆蓋,而且保存在地址裏面也不會被清除 none # sb示例並沒有創建 cloth 屬性,但是依然可以調用出來之前 suyang 示例的屬性 ,即繼承了之前的屬性 """ b.hobby = "bb" print(a.hobby) """ bb # 相同的沒有創建 hobby 的 suyang 示例 也可以繼承之後的 sb 創建的 hobby 屬性 """全部代碼
基於 __new__ 方法的單例模式