検索
ホームページバックエンド開発Python チュートリアルPython でシングルトンを実装する最良の方法は何ですか?

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 までご連絡ください。
Pythonの実行モデル:コンパイル、解釈、またはその両方?Pythonの実行モデル:コンパイル、解釈、またはその両方?May 10, 2025 am 12:04 AM

pythonisbothcompiledinterted.whenyourunapythonscript、itisfirstcompiledintobytecode、これはdenepythonvirtualmachine(pvm).thishybridapproaChallowsforplatform-platform-denodent-codebutcututicut。

Pythonはラインごとに実行されますか?Pythonはラインごとに実行されますか?May 10, 2025 am 12:03 AM

Pythonは厳密に行ごとの実行ではありませんが、最適化され、インタープレーターメカニズムに基づいて条件付き実行です。インタープリターは、コードをPVMによって実行されるBytecodeに変換し、定数式または最適化ループを事前促進する場合があります。これらのメカニズムを理解することで、コードを最適化し、効率を向上させることができます。

Pythonの2つのリストを連結する代替品は何ですか?Pythonの2つのリストを連結する代替品は何ですか?May 09, 2025 am 12:16 AM

Pythonに2つのリストを接続する多くの方法があります。1。オペレーターを使用しますが、これはシンプルですが、大きなリストでは非効率的です。 2。効率的ですが、元のリストを変更する拡張メソッドを使用します。 3。=演算子を使用します。これは効率的で読み取り可能です。 4。itertools.chain関数を使用します。これはメモリ効率が高いが、追加のインポートが必要です。 5。リストの解析を使用します。これはエレガントですが、複雑すぎる場合があります。選択方法は、コードのコンテキストと要件に基づいている必要があります。

Python:2つのリストをマージする効率的な方法Python:2つのリストをマージする効率的な方法May 09, 2025 am 12:15 AM

Pythonリストをマージするには多くの方法があります。1。オペレーターを使用します。オペレーターは、シンプルですが、大きなリストではメモリ効率的ではありません。 2。効率的ですが、元のリストを変更する拡張メソッドを使用します。 3. Itertools.chainを使用します。これは、大規模なデータセットに適しています。 4.使用 *オペレーター、1つのコードで小規模から中型のリストをマージします。 5. numpy.concatenateを使用します。これは、パフォーマンス要件の高い大規模なデータセットとシナリオに適しています。 6.小さなリストに適したが、非効率的な追加方法を使用します。メソッドを選択するときは、リストのサイズとアプリケーションのシナリオを考慮する必要があります。

コンパイルされた通信言語:長所と短所コンパイルされた通信言語:長所と短所May 09, 2025 am 12:06 AM

compiledlanguagesOfferspeedandsecurity、foredlanguagesprovideeaseofuseandportability.1)compiledlanguageslikec arefasterandsecurebuthavelOnderdevelopmentsplat dependency.2)

Python:ループのために、そして最も完全なガイドPython:ループのために、そして最も完全なガイドMay 09, 2025 am 12:05 AM

Pythonでは、forループは反復可能なオブジェクトを通過するために使用され、条件が満たされたときに操作を繰り返し実行するためにしばらくループが使用されます。 1)ループの例:リストを通過し、要素を印刷します。 2)ループの例:正しいと推測するまで、数値ゲームを推測します。マスタリングサイクルの原則と最適化手法は、コードの効率と信頼性を向上させることができます。

Python concatenateリストを文字列に入れますPython concatenateリストを文字列に入れますMay 09, 2025 am 12:02 AM

リストを文字列に連結するには、PythonのJoin()メソッドを使用して最良の選択です。 1)join()メソッドを使用して、 '' .join(my_list)などのリスト要素を文字列に連結します。 2)数字を含むリストの場合、連結する前にマップ(str、数字)を文字列に変換します。 3) '、'などの複雑なフォーマットに発電機式を使用できます。 4)混合データ型を処理するときは、MAP(STR、Mixed_List)を使用して、すべての要素を文字列に変換できるようにします。 5)大規模なリストには、 '' .join(lage_li)を使用します

Pythonのハイブリッドアプローチ:コンピレーションと解釈を組み合わせたPythonのハイブリッドアプローチ:コンピレーションと解釈を組み合わせたMay 08, 2025 am 12:16 AM

pythonusesahybridapproach、コンコイリティレーショントビテコードと解釈を組み合わせて、コードコンピレッドフォームと非依存性bytecode.2)

See all articles

ホット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 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

DVWA

DVWA

Damn Vulnerable Web App (DVWA) は、非常に脆弱な PHP/MySQL Web アプリケーションです。その主な目的は、セキュリティ専門家が法的環境でスキルとツールをテストするのに役立ち、Web 開発者が Web アプリケーションを保護するプロセスをより深く理解できるようにし、教師/生徒が教室環境で Web アプリケーションを教え/学習できるようにすることです。安全。 DVWA の目標は、シンプルでわかりやすいインターフェイスを通じて、さまざまな難易度で最も一般的な Web 脆弱性のいくつかを実践することです。このソフトウェアは、

VSCode Windows 64 ビットのダウンロード

VSCode Windows 64 ビットのダウンロード

Microsoft によって発売された無料で強力な IDE エディター

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。

PhpStorm Mac バージョン

PhpStorm Mac バージョン

最新(2018.2.1)のプロフェッショナル向けPHP統合開発ツール