ホームページ  >  記事  >  バックエンド開発  >  Python メタクラスでのシングルトン モードの使用の概要 (コード例)

Python メタクラスでのシングルトン モードの使用の概要 (コード例)

不言
不言オリジナル
2018-09-12 15:13:211664ブラウズ

この記事では、Python メタクラスでのシングルトン モードの使用方法 (コード例) を紹介します。これには一定の参考値があります。必要な友人は参照できます。お役に立てば幸いです。

1. Python メタクラスとは

参考記事Python メタクラスとは何ですか? Python メタクラスの概要

2. シングルトン パターンとは

シングルトン パターン (シングルトン パターン) は、一般的に使用されるソフトウェア設計パターンです。そのコア構造には、シングルトンと呼ばれる特別なクラスが 1 つだけ含まれています。シングルトン モードでは、システム内にクラスのインスタンスが 1 つだけ存在し、外部からそのインスタンスに簡単にアクセスできるようにすることができるため、インスタンス数の制御が容易になり、システム リソースが節約されます。特定のクラスのオブジェクトを 1 つだけシステム内に存在させたい場合は、シングルトン パターンが最適なソリューションです。

クラスのインスタンスが 1 つだけであること、およびこのインスタンスに簡単にアクセスできることを確認するにはどうすればよいですか? グローバル変数を定義すると、いつでもオブジェクトにアクセスできるようになりますが、複数のオブジェクトのインスタンス化が妨げられるわけではありません。より良い解決策は、クラス自体にその唯一のインスタンスの保存を担当させることです。このクラスは、他のインスタンスが作成されないことを保証し、インスタンスにアクセスするメソッドを提供します。これがシングルトン パターンの背後にあるパターンの動機です。

3. __new__ を使用してシングルトンを実装する

# -*- coding: utf8 -*-

class Singleton(object):
    def __init__(self):
        print 'entrance of __init__'

    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
        return cls._instance

if __name__ == '__main__':
    s1 = Singleton()
    s2 = Singleton()

    print s1, s2

Python では、通常、__new__ 関数を使用してシングルトン モードを実装します。 __new__ 関数は、C のコンストラクターと同様に、オブジェクトの構築を担当します。したがって、クラスがインスタンス オブジェクトを 1 つだけ作成するようにするには、__new__ 関数の動作をオーバーロードして、インスタンスを 1 つだけ構築できるようにします。上記のコードでは、_instance 属性が Singleton クラスに割り当てられています。_instance 属性が None の場合、インスタンス オブジェクトが作成され、_instance 属性はそのオブジェクトを参照 (ポイント) します。それ以外の場合は、_instance によって参照されるオブジェクトが直接返されます。 。したがって、コード内の s1 と s2 は実際には同じメモリ オブジェクトを参照します。 4. メタクラス __call__ を使用してシングルトンを実装する

# -*- coding: utf8 -*-

# 单例模式
class SingletonMetaClass(type):
    def __init__(cls, *args, **kwargs):
        """
        初始化类
        :param args:
        :param kwargs:
        """
        print 'MetaClass.__init__ called'
        print cls._instance
        super(SingletonMetaClass, cls).__init__(*args, **kwargs)


    def __new__(cls, name, bases, attrs):
        """
        创建类,负责类的行为和属性的创建
        :param name:
        :param bases:
        :param attrs:
        :return:
        """
        print 'MetaClass.__new__ called'

        # 单例模式
        cls._instance = None

        return type.__new__(cls, name, bases, attrs)

    # __call__方法其实和类的创建过程和实例化没有多大关系了,定义了__call__方法才能被使用函数的方式执行。
    # 被该元类创建的类,属于该元类的一个实例。因此创建其实例的时候,会调用元类的__call_方法
    def __call__(cls, *args, **kwargs):
        """
        使类变为可调用对象
        :param args:
        :param kwargs:
        :return:
        """
        print 'MetaClass.__call__ called'
        if cls._instance is None:
            # 这里会去调用类的__new__函数
            cls._instance = super.__call__(SingletonMetaClass, cls).__call__(*args, **kwargs)
        return cls._instance

class A():
    __metaclass__ = SingletonMetaClass

    def __new__(cls, *args, **kwargs):
        print 'A.__new__ called'
        return super(A, cls).__new__(cls, *args, **kwargs)

if __name__ == '__main__':
    # 因为类A是SingletonMetaClass的一个实例,执行A()时会调用元类SingletonMetaClass的__call__方法
    a1 = A()
    print a1
    a2 = A()
    print a2

Python ではクラスもオブジェクトであり、メタクラスはクラスを作成するクラスであることがわかっています。そのため、

クラスは実際には のインスタンス オブジェクトです。メタクラス

。 Python では、オブジェクトが __call__ メソッドを定義している場合、そのオブジェクトは呼び出し可能オブジェクトです。つまり、関数を呼び出すことでオブジェクトを呼び出すことができます。 Python の __new__ メソッドはオブジェクトの作成を担当し、 __init__ メソッドはオブジェクトの初期化を担当します。上記のコードでは、

クラス A のオブジェクトはクラス A を作成した後でしか作成できないため、最初にクラス A を作成するには、SingletonMetaClass の __new__ メソッドと __init__ メソッドが最初に実行されます。ステートメント A() を実行してクラス A のオブジェクトを作成すると、__call__ メソッドの定義に従って、クラス A はメタクラス SingletonMetaClass のオブジェクトであるため、メタクラス SingletonMetaClass の __call__ メソッドが呼び出されることが期待できます。 。

つまり、上記のコードの SiingletonMetaClass の __new__ メソッドと __init__ メソッドは 1 回だけ実行され、クラスのインスタンスを作成するために A() が呼び出されるたびに SingletonMetaClass が呼び出されます。 A. __call__ メソッド。したがって、シングルトンモードを実装するには、メタクラスの __call__ メソッドで cls の _instance 属性が None であるかどうかを判断し、None であればメタクラスの親クラス (つまり type) の __call__ メソッド、type を呼び出します。 __call_ _method は、クラス A の __new__ メソッドを呼び出してクラス A のインスタンスを作成し、_instance 属性をそのインスタンスにポイントすることで、インスタンスを 1 つだけ実現します。実行の結果は次のとおりです。

MetaClass.__new__ called
MetaClass.__init__ called
None
MetaClass.__call__ called
A.__new__ called
<__main__.A object at 0x00000000036D2EB8>
MetaClass.__call__ called
<__main__.A object at 0x00000000036D2EB8>

関連する推奨事項:

設計パターンで責任連鎖パターンとイテレータ パターンを使用した Python の例


redis プールを使用した Python のシングルトン実装の概要

以上がPython メタクラスでのシングルトン モードの使用の概要 (コード例)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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