目次
Python でシングルトンを実装する最良の方法
実装方法
方法 1: デコレータ
方法 2: 基本クラス
方法 3: メタクラス
方法 4: 同じ名前のクラスのデコレータを返す
方法 5: モジュール
推奨方法
メタクラスの役割
もちろん
Python 2 および 3 の互換バージョン
訂正
ホームページ バックエンド開発 Python チュートリアル Python でシングルトンを実装する最良の方法は何ですか?

Python でシングルトンを実装する最良の方法は何ですか?

Dec 17, 2024 pm 04:07 PM

What is the best way to implement a singleton in Python?

Python でシングルトンを実装する最良の方法

シングルトン設計パターンの長所と短所はこの記事の焦点では​​ありませんが、この記事では、シングルトン設計パターンの利点と欠点について説明します。可能な限り最善の方法で Python にシングルトンを実装するには、このパターンを Python 的な方法で実装します。ここで、「最も Python 的」とは、「最小の驚きの原則」に従うことを意味します。

実装方法

方法 1: デコレータ

def singleton(class_):
    instances = {}

    def getinstance(*args, **kwargs):
        if class_ not in instances:
            instances[class_] = class_(*args, **kwargs)
        return instances[class_]

    return getinstance

@singleton
class MyClass(BaseClass):
    pass
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

利点:

  • デコレータは追加のセックスを持ち、多重継承よりも直感的です。

欠点:

  • MyClass() を使用して作成されたオブジェクトは実際のシングルトン オブジェクトですが、MyClass 自体はクラスではなく関数です。したがって、クラスメソッドを呼び出すことはできません。

方法 2: 基本クラス

class Singleton(object):
    _instance = None

    def __new__(class_, *args, **kwargs):
        if not isinstance(class_._instance, class_):
            class_._instance = object.__new__(class_, *args, **kwargs)
        return class_._instance

class MyClass(Singleton, BaseClass):
    pass
ログイン後にコピー
ログイン後にコピー

利点:

  • これは実際のクラスです。

欠点:

  • 多重継承、不快。 2 番目の基本クラスから継承する場合、__new__ がオーバーライドされる可能性があります。

方法 3: メタクラス

class Singleton(type):
    _instances = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]

# Python2
class MyClass(BaseClass):
    __metaclass__ = Singleton

# Python3
class MyClass(BaseClass, metaclass=Singleton):
    pass
ログイン後にコピー

利点:

  • これは実際のクラスです。
  • 継承は自動的にカバーされます。
  • __metaclass__ を正しく使用してください (そして、それを理解させてください)。

デメリット:

  • デメリットはありません。

方法 4: 同じ名前のクラスのデコレータを返す

def singleton(class_):
    class class_w(class_):
        _instance = None

        def __new__(class_, *args, **kwargs):
            if class_w._instance is None:
                class_w._instance = super(class_w, class_).__new__(class_, *args, **kwargs)
                class_w._instance._sealed = False
            return class_w._instance

        def __init__(self, *args, **kwargs):
            if self._sealed:
                return
            super(class_w, self).__init__(*args, **kwargs)
            self._sealed = True

    class_w.__name__ = class_.__name__
    return class_w

@singleton
class MyClass(BaseClass):
    pass
ログイン後にコピー

利点:

  • です。本当のクラス。
  • 継承は自動的にカバーされます。

短所:

  • シングルトンにしたいクラスごとに 2 つのクラスを作成するとオーバーヘッドが発生しますか?私の場合はこれでうまくいきましたが、拡張できないのではないかと心配しています。
  • _sealed 属性の目的は何ですか?
  • 基底クラス内で同じ名前のメソッドを呼び出すのに super() を使用することは再帰的になるためできません。これは、__new__ をカスタマイズしたり、__​​init__ の呼び出しを必要とするクラスをサブクラス化したりできないことを意味します。

方法 5: モジュール

シングルトン モジュール singleton.py。

長所:

  • 複雑よりもシンプルの方が優れています。

欠点:

  • インスタンス化は遅延されません。

推奨方法

方法 2 を使用することをお勧めしますが、基本クラスの代わりにメタクラスを使用することをお勧めします。以下に実装例を示します:

class Singleton(type):
    _instances = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]

class Logger(object):
    __metaclass__ = Singleton
ログイン後にコピー

または Python3 の場合:

class Logger(metaclass=Singleton):
    pass
ログイン後にコピー

クラスが呼び出されるたびに __init__ を実行したい場合は、次のコードを Singleton.__call__ In に追加します。 if ステートメント:

def singleton(class_):
    instances = {}

    def getinstance(*args, **kwargs):
        if class_ not in instances:
            instances[class_] = class_(*args, **kwargs)
        return instances[class_]

    return getinstance

@singleton
class MyClass(BaseClass):
    pass
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

メタクラスの役割

メタクラスはクラスのクラス、つまり、クラスはそのメタクラスのインスタンスです。 Python のオブジェクトのメタクラスは、type(obj) によって見つけることができます。通常の新しいクラスは type 型です。 Logger の (唯一の) インスタンスがクラス 'your_module.Logger' であるのと同様に、上記の Logger はクラス 'your_module.Singleton' になります。 Logger() を使用してロガーが呼び出されるとき、Python はまずロガーのメタクラス Singleton に何をすべきかを尋ね、プリエンプティブなインスタンスの作成を可能にします。このプロセスは、Python が __getattr__ を呼び出してその属性をどのように処理するかをクラスに問い合わせる方法と似ており、myclass.attribute を実行してその属性を参照します。

メタクラスは基本的に、呼び出しクラスの意味とその意味の実装方法を決定します。たとえば、メタクラスを使用して Python で C スタイルの構造を再作成する http://code.activestate.com/recipes/498149/ を参照してください。ディスカッション スレッド [メタクラスの具体的な使用例は何ですか? ](https://codereview.stackexchange.com/questions/82786/what-are-some-concrete-use-cases-for-metaclasses) では、一般的に宣言型プログラミング、特にで使用される ORM に関連するいくつかの例も提供しています。 。

この場合、メソッド 2 を使用し、サブクラスで __new__ メソッドが定義されている場合、SubClassOfSingleton() が呼び出されるたびにこのメソッドが実行されます。これは、メソッドを呼び出す責任があるためです。保存されたインスタンスを返します。メタクラスの場合、一意のインスタンスの作成時に一度だけ実行されます。呼び出しクラスの定義をカスタマイズする必要があります。呼び出しクラスの定義は、その型によって決まります。

一般に、メタクラスを使用してシングルトンを実装することは理にかなっています。シングルトンはインスタンスが 1 回だけ作成されるため特別です。一方、メタクラスは、通常のクラスとは異なる動作をさせる、作成されたクラスのカスタム実装です。メタクラスを使用すると、シングルトン クラス定義をカスタマイズする必要がある場合に、より詳細な制御が可能になります。

もちろん

シングルトンには多重継承は必要ありません (メタクラスは基底クラスではないため)。ただし、継承でクラスのサブクラスを作成するには、シングルトンがclass は最初のメタクラスです。左端のメタクラスは __call__ を再定義します。これが問題になる可能性は低いです。インスタンス ディクショナリはインスタンスの名前空間にないため、誤って上書きされることはありません。

シングルトン パターンは、各クラスが 1 つのことだけを実行する必要があるという意味の「単一責任の原則」に違反しているということも聞きます。こうすることで、コードは独立していてカプセル化されているため、別のコードを変更する必要があるときにコードの動作が壊れることを心配する必要がなくなります。メタクラス実装はこのテストに合格します。メタクラスはパターンを強制し、シングルトンであることを意識する必要のないクラスとサブクラスを作成する責任があります。 メソッド 1 は、「MyClass 自体はクラスではなく関数であるため、クラス メソッドを呼び出すことができません」と指摘したように、このテストに失敗します。

Python 2 および 3 の互換バージョン

Python 2 および 3 でコードを記述するには、もう少し複雑なスキームが必要です。通常、メタクラスは型クラスのサブクラスであるため、メタクラスを使用して、実行時にメタクラスとして中間基本クラスを動的に作成し、その基本クラスをパブリック シングルトン基本クラスの基本クラスとして使用できます。これは次のように言うは易く行うは難しです:

def singleton(class_):
    instances = {}

    def getinstance(*args, **kwargs):
        if class_ not in instances:
            instances[class_] = class_(*args, **kwargs)
        return instances[class_]

    return getinstance

@singleton
class MyClass(BaseClass):
    pass
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

このアプローチの皮肉の 1 つは、サブクラス化を使用してメタクラスを実装していることです。考えられる利点の 1 つは、純粋なメタクラスとは異なり、isinstance(inst, Singleton) が True を返すことです。

訂正

別のトピックに関して、お気づきかもしれませんが、元の投稿の基本クラスの実装が間違っていました。クラス内の _instances を参照するには、呼び出し時には実際のクラスがまだ作成されていないため、super() またはクラス メソッドの静的メソッドを使用する必要があります。これはすべて、メタクラスの実装にも当てはまります。

class Singleton(object):
    _instance = None

    def __new__(class_, *args, **kwargs):
        if not isinstance(class_._instance, class_):
            class_._instance = object.__new__(class_, *args, **kwargs)
        return class_._instance

class MyClass(Singleton, BaseClass):
    pass
ログイン後にコピー
ログイン後にコピー

以上がPython でシングルトンを実装する最良の方法は何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Python vs. C:曲線と使いやすさの学習 Python vs. C:曲線と使いやすさの学習 Apr 19, 2025 am 12:20 AM

Pythonは学習と使用が簡単ですが、Cはより強力ですが複雑です。 1。Python構文は簡潔で初心者に適しています。動的なタイピングと自動メモリ管理により、使いやすくなりますが、ランタイムエラーを引き起こす可能性があります。 2.Cは、高性能アプリケーションに適した低レベルの制御と高度な機能を提供しますが、学習しきい値が高く、手動メモリとタイプの安全管理が必要です。

Pythonの学習:2時間の毎日の研究で十分ですか? Pythonの学習:2時間の毎日の研究で十分ですか? Apr 18, 2025 am 12:22 AM

Pythonを1日2時間学ぶだけで十分ですか?それはあなたの目標と学習方法に依存します。 1)明確な学習計画を策定し、2)適切な学習リソースと方法を選択します。3)実践的な実践とレビューとレビューと統合を練習および統合し、統合すると、この期間中にPythonの基本的な知識と高度な機能を徐々に習得できます。

Python vs. C:パフォーマンスと効率の探索 Python vs. C:パフォーマンスと効率の探索 Apr 18, 2025 am 12:20 AM

Pythonは開発効率でCよりも優れていますが、Cは実行パフォーマンスが高くなっています。 1。Pythonの簡潔な構文とリッチライブラリは、開発効率を向上させます。 2.Cのコンピレーションタイプの特性とハードウェア制御により、実行パフォーマンスが向上します。選択を行うときは、プロジェクトのニーズに基づいて開発速度と実行効率を比較検討する必要があります。

Python vs. C:重要な違​​いを理解します Python vs. C:重要な違​​いを理解します Apr 21, 2025 am 12:18 AM

PythonとCにはそれぞれ独自の利点があり、選択はプロジェクトの要件に基づいている必要があります。 1)Pythonは、簡潔な構文と動的タイピングのため、迅速な開発とデータ処理に適しています。 2)Cは、静的なタイピングと手動メモリ管理により、高性能およびシステムプログラミングに適しています。

Python Standard Libraryの一部はどれですか:リストまたは配列はどれですか? Python Standard Libraryの一部はどれですか:リストまたは配列はどれですか? Apr 27, 2025 am 12:03 AM

PythonListSarePartOfThestAndardarenot.liestareBuilting-in、versatile、forStoringCollectionsのpythonlistarepart。

Python:自動化、スクリプト、およびタスク管理 Python:自動化、スクリプト、およびタスク管理 Apr 16, 2025 am 12:14 AM

Pythonは、自動化、スクリプト、およびタスク管理に優れています。 1)自動化:OSやShutilなどの標準ライブラリを介してファイルバックアップが実現されます。 2)スクリプトの書き込み:Psutilライブラリを使用してシステムリソースを監視します。 3)タスク管理:スケジュールライブラリを使用してタスクをスケジュールします。 Pythonの使いやすさと豊富なライブラリサポートにより、これらの分野で優先ツールになります。

科学コンピューティングのためのPython:詳細な外観 科学コンピューティングのためのPython:詳細な外観 Apr 19, 2025 am 12:15 AM

科学コンピューティングにおけるPythonのアプリケーションには、データ分析、機械学習、数値シミュレーション、視覚化が含まれます。 1.numpyは、効率的な多次元配列と数学的関数を提供します。 2。ScipyはNumpy機能を拡張し、最適化と線形代数ツールを提供します。 3. Pandasは、データ処理と分析に使用されます。 4.matplotlibは、さまざまなグラフと視覚的な結果を生成するために使用されます。

Web開発用のPython:主要なアプリケーション Web開発用のPython:主要なアプリケーション Apr 18, 2025 am 12:20 AM

Web開発におけるPythonの主要なアプリケーションには、DjangoおよびFlaskフレームワークの使用、API開発、データ分析と視覚化、機械学習とAI、およびパフォーマンスの最適化が含まれます。 1。DjangoandFlask Framework:Djangoは、複雑な用途の迅速な発展に適しており、Flaskは小規模または高度にカスタマイズされたプロジェクトに適しています。 2。API開発:フラスコまたはdjangorestFrameworkを使用して、Restfulapiを構築します。 3。データ分析と視覚化:Pythonを使用してデータを処理し、Webインターフェイスを介して表示します。 4。機械学習とAI:Pythonは、インテリジェントWebアプリケーションを構築するために使用されます。 5。パフォーマンスの最適化:非同期プログラミング、キャッシュ、コードを通じて最適化

See all articles