1. 程式人生 > >基於 __new__ 方法的單例模式

基於 __new__ 方法的單例模式

地址 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__ 方法的單例模式