pythonの中で単一の例の常用するいくつかの実現方法の総括


前言
最近この二日間は自分の前に書いたコードを見ていますので、使ったものを整理しています。シングルモデルは、日常のコード作業にもよく使われています。
そこで、これまで使ってきた様々な形で実現した一例をまとめてみます。
単例とは何ですか?
あるクラスが一例だけであることを保証し、システム全体にこの例を直接的に実行して提供する。このクラスは一例クラスと呼ばれ、一例モードはオブジェクト作成モードである。
単例モードはどんな用途がありますか?一般的な例を挙げると、私たちが普段使っているパソコンには回収ステーションがあります。全体のオペレーティングシステムでは、回収ステーションは一例しかありません。システム全体がこの唯一の例を使用しています。また、回収ステーションは自分のインスタンスを提供しています。したがって、回収ステーションはシングルモードのアプリケーションです。
装飾器の方式
このような方式も仕事でよく使われています。使いやすいです。コードは次のように実現されます。

def Singleton(cls):
 _instance = {}

 def _singleton(*args, **kwargs):
  if cls not in _instance:
   _instance[cls] = cls(*args, **kwargs)
  return _instance[cls]

 return _singleton
もし私達の仕事の一つの種類が単例で次のような方式で実現すればいいです。

@Singleton
class A(object):

 def __init__(self, x):
  self.x = x
個人的にはこのような方式が好きです。
クラスの方式実現
ここには実はいくつかの問題がありますので、注意が必要です。まず、エラーコードを見てみてください。

class Member(object):

 @classmethod
 def instance(cls, *args, **kwargs):
  if not hasattr(Member, "_instance"):
   Member._instance = Member(*args, **kwargs)
  return Member._instance
このクラスは一例では実現されているようですが、マルチスレッドの場合、特に現在のクラスの初期化対象には時間がかかります。
例えば以下のコード:

#! /usr/bin/env python3
# .-*- coding:utf-8 .-*-

import time
import threading
import random


class Member(object):
 
 def __init__(self):
  time.sleep(random.randint(1,3))

 @classmethod
 def instance(cls, *args, **kwargs):
  if not hasattr(Member, "_instance"):
   Member._instance = Member(*args, **kwargs)
  return Member._instance


def task(arg):
 obj = Member.instance()
 print(obj)

for i in range(5):
 t = threading.Thread(target=task, args=[i,])
 t.start()
このコードの実行結果には、複数のオブジェクトが実例化されてしまい、あなたが書いた一例が役に立たなくなります。
もちろん自然にロックを思い出します。ロックでコントロールします。上のコードを変更します。

#! /usr/bin/env python3
# .-*- coding:utf-8 .-*-


import time
import threading
import random


class Member(object):
 _instance_lock = threading.Lock()

 def __init__(self):
  i = random.randint(1, 3)
  print(i)
  time.sleep(i)

 @classmethod
 def instance(cls, *args, **kwargs):
  with Member._instance_lock:
   if not hasattr(Member, "_instance"):
    Member._instance = Member(*args, **kwargs)
  return Member._instance


def task():
 obj = Member.instance()
 print(obj)

for i in range(5):
 threading.Thread(target=task,).start()
しかし、上のコードにはもう一つの問題があります。つまり、私達はすでに実用化されてから毎回instanceを呼び出してロックを要請します。だからこれはよくないです。だから、この部分のコードを再度変更します。

@classmethod
 def instance(cls, *args, **kwargs):
  if not hasattr(Member, "_instance"):
   with Member._instance_lock:
    if not hasattr(Member, "_instance"):
     Member._instance = Member(*args, **kwargs)
  return Member._instance
このようにして、マルチスレッドが使える一例を実現します。
締め括りをつける
以上はこの文章の全部の内容です。本文の内容は皆さんの学習や仕事に対して一定の参考となる学習価値を持っています。質問があれば、メッセージを書いて交流してください。ありがとうございます。