最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python實現(xiàn)單例模式的幾種常見方式

 更新時間:2026年05月06日 09:34:20   作者:huzhongqiang  
本文分享 Python 單例模式四種實現(xiàn)方式(裝飾器、new、函數(shù)、lru_cache),對比優(yōu)缺點后建議優(yōu)先顯式獲取單例,強調(diào)編程應(yīng)回歸樸素,避免過度設(shè)計,簡單直白的代碼更易維護,需要的朋友可以參考下

前言

最近在整理代碼時,重新審視了項目中用到的單例模式實現(xiàn)。發(fā)現(xiàn)自己對單例模式的理解經(jīng)歷了一個有趣的循環(huán):從懵懂使用,到追求各種"巧妙"實現(xiàn),再到回歸樸素。

今天想分享幾種 Python 實現(xiàn)單例模式的方式,并談?wù)勎叶嗄昃幊痰囊粋€感悟:樸素的就是最好的。

一、單例模式簡介

單例模式(Singleton Pattern)是一種設(shè)計模式,確保一個類只有一個實例,并提供一個全局訪問點。

適用場景

場景說明
數(shù)據(jù)庫連接全局共享一個連接池
日志記錄器避免重復(fù)打開文件
配置管理器全局只讀一份配置
緩存實例全局共享緩存

二、四種實現(xiàn)方式

方式一:類裝飾器

def singleton(cls):
    """單例裝飾器:閉包保存唯一實例"""
    _instance = None

    def wrapper(*args, **kwargs):
        nonlocal _instance
        if _instance is None:
            _instance = cls(*args, **kwargs)
        return _instance

    return wrapper


@singleton
class DBConnect:
    def __init__(self, host):
        self.host = host
        print("數(shù)據(jù)庫連接初始化")


# 使用
obj1 = DBConnect("127.0.0.1")
obj2 = DBConnect("192.168.1.1")  # 不會重新初始化

print(obj1 is obj2)  # True
print(obj1.host)     # 127.0.0.1

特點:裝飾器語法優(yōu)雅,使用時一目了然。

方式二:__new__方法

class MySingleton:
    """單例類:通過 __new__ 控制實例創(chuàng)建"""
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance


# 使用
obj1 = MySingleton()
obj2 = MySingleton()
print(obj1 is obj2)  # True

特點:最直接的方式,但 _instance 作為類變量暴露在外。我之前的博文 Playwright理解與封裝就是使用這種方式,感覺不太好,準(zhǔn)備重構(gòu)一下,那個類根本不需要單例模式,如果使用者覺得有必要,可以顯式自行單例化即可。

方式三:函數(shù)

from typing import Type, TypeVar

T = TypeVar('T')

def singleton(cls: Type[T], *args, **kwargs) -> T:
    """單例工廠函數(shù)"""
    if not hasattr(cls, '_instance'):
        cls._instance = cls(*args, **kwargs)
    return cls._instance


# 使用
class TargetClass:
    def __init__(self, config):
        self.config = config

obj = singleton(TargetClass, config="value")

特點:需要顯式調(diào)用 singleton(),語義明確但稍顯繁瑣。

方式四:functools.lru_cache

from functools import lru_cache

@lru_cache(maxsize=1)
def get_instance():
    return MyClass(arg1="value")


# 使用
obj1 = get_instance()
obj2 = get_instance()
print(obj1 is obj2)  # True

特點:Python 內(nèi)置,簡單直接,還能享受緩存的好處。

三、優(yōu)缺點對比

實現(xiàn)方式優(yōu)點缺點推薦指數(shù)
類裝飾器語法優(yōu)雅、語義清晰、易于理解對于非必要實現(xiàn)單例的類,對使用者會造成困擾????
new 方法最直觀、最簡單實例變量暴露、可復(fù)用性不好??
單例函數(shù)顯式調(diào)用、可控性強,使用者清楚知道正在做什么每次都要調(diào)用、不夠直觀???
lru_cache內(nèi)置、無需額外代碼語義上不是單例、更像緩存,但是勝在簡單????

四、我的建議

優(yōu)先使用顯式單例

相比把類變成單例,顯式獲取單例的寫法更加清晰:

# ? 推薦:顯式獲取單例
_db = None
def get_db():
    global _db
    if _db is None:
        _db = Database()
    return _db

# 或者更簡潔地用 lru_cache
@lru_cache
def get_db():
    return Database()
# ? 不推薦:把類變成單例,除非很確定此類必須是單例類,不會造成使用者誤解
@singleton
class Database:
    ...

為什么?

  1. 透明性:使用者能清楚看到這個類是全局共享的
  2. 可控性:可以靈活控制何時創(chuàng)建、如何創(chuàng)建
  3. 易測試:mock 和替換更容易
  4. 少歧義:不會讓使用者誤以為每次 new 都是新實例

五、多年編程感悟

樸素的就是最好的。所有當(dāng)時自鳴得意的所謂編程技巧,最后都會被證明要用更多的代價來理解和維護它。

幾個教訓(xùn)

當(dāng)年覺得"巧妙"后來發(fā)現(xiàn)的問題
復(fù)雜的繼承鏈調(diào)試時一頭霧水
動態(tài)修改類屬性難以追蹤狀態(tài)變化
魔法裝飾器新人看不懂
元編程炫技給自己挖坑

回歸樸素

# 曾經(jīng)的我:要用單例模式!
@singleton
class ConfigManager:
    ...

# 現(xiàn)在的我:簡單就好
@lru_cache
def get_db():
    return Database()

簡單、直白、不需要解釋。這才是好的代碼。

六、總結(jié)

要點回顧

  1. 裝飾器方式是最推薦的類單例實現(xiàn)(針對必須實現(xiàn)單例的類)
  2. 顯式獲取單例比把類變成單例更好
  3. lru_cache 是最簡單的單例緩存方案
  4. 樸素思維:能用簡單方式解決的問題,不要過度設(shè)計

以上就是Python實現(xiàn)單例模式的幾種常見方式的詳細內(nèi)容,更多關(guān)于Python實現(xiàn)單例模式的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 基于Python+Pyqt5開發(fā)一個應(yīng)用程序

    基于Python+Pyqt5開發(fā)一個應(yīng)用程序

    今天給大家?guī)淼氖顷P(guān)于Python的相關(guān)知識,文章圍繞著Python+Pyqt5開發(fā)一個應(yīng)用程序展開,文中有非常詳細的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • python3.X 抓取火車票信息【修正版】

    python3.X 抓取火車票信息【修正版】

    這篇文章主要介紹了python3.X 抓取火車票信息修正版,本文是在源代碼的基礎(chǔ)上進行的修改,需要的朋友可以參考下
    2018-06-06
  • Python使用SpeechRecognition庫實現(xiàn)語音識別功能

    Python使用SpeechRecognition庫實現(xiàn)語音識別功能

    SpeechRecognition 是 Python 生態(tài)中最主流的語音識別第三方庫,它封裝了多個國內(nèi)外主流語音識別引擎的接口,本文將帶大家了解Python的SpeechRecognition庫的功能、使用方法,并通過具體案例掌握它在不同場景下的應(yīng)用,需要的朋友可以參考下
    2026-01-01
  • Python中子類繼承父類傳遞參數(shù)的方法

    Python中子類繼承父類傳遞參數(shù)的方法

    在面向?qū)ο缶幊讨?繼承是一種使得一個類(稱為子類)能夠獲取另一個類(稱為父類)的屬性和方法的機制,Python支持繼承,并提供了靈活的方式來繼承和擴展類的功能,本文將詳細介紹如何在Python中使用子類繼承父類,并傳遞參數(shù),需要的朋友可以參考下
    2025-03-03
  • 線程安全及Python中的GIL原理分析

    線程安全及Python中的GIL原理分析

    這篇文章主要介紹了線程安全及Python中的GIL原理,較為詳細的分析了線程安全及Python中的GIL相關(guān)概念、原理、理解及操作注意事項,需要的朋友可以參考下
    2019-10-10
  • Python3.x版本中新的字符串格式化方法

    Python3.x版本中新的字符串格式化方法

    這篇文章主要介紹了Python3.x版本中新的字符串格式化方法,本文對比給出了Python2.x和Python3.x中字符串格式化方法實例代碼,需要的朋友可以參考下
    2015-04-04
  • selenium自動化測試框架方式

    selenium自動化測試框架方式

    這篇文章主要介紹了selenium自動化測試框架方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2020-02-02
  • Python +Selenium解決圖片驗證碼登錄或注冊問題(推薦)

    Python +Selenium解決圖片驗證碼登錄或注冊問題(推薦)

    這篇文章主要介紹了Python Selenium解決圖片驗證碼登錄或注冊問題,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-02-02
  • 一波神奇的Python語句、函數(shù)與方法的使用技巧總結(jié)

    一波神奇的Python語句、函數(shù)與方法的使用技巧總結(jié)

    這篇文章主要介紹了一波神奇的Python函數(shù)與方法的使用技巧總結(jié),包括裝飾器和with語句等的不常見用法,需要的朋友可以參考下
    2015-12-12
  • python循環(huán)引用和解決過程

    python循環(huán)引用和解決過程

    文章討論了在Python中解決循環(huán)引用問題的幾種方法,包括延遲導(dǎo)入、使用`importlib`、重構(gòu)代碼和類型提示的前向引用,這些方法可以幫助開發(fā)者避免導(dǎo)入循環(huán)導(dǎo)致的錯誤,并使代碼更加模塊化和易于維護
    2025-12-12

最新評論

泗洪县| 同心县| 甘洛县| 兴宁市| 鄂尔多斯市| 武陟县| 天全县| 甘德县| 阿拉善右旗| 高雄市| 报价| 应城市| 镇远县| 房产| 黄骅市| 汝阳县| 咸阳市| 新龙县| 喜德县| 天全县| 中山市| 罗定市| 泉州市| 景德镇市| 洛川县| 湾仔区| 峡江县| 东方市| 保康县| 丰城市| 喀喇沁旗| 武陟县| 丹东市| 定结县| 大埔县| 铜山县| 金塔县| 大关县| 安溪县| 洛南县| 桦甸市|